2015年4月30日木曜日

MySQL 5.7.5から複数のユーザーレベルロック(get_lock関数のアレ)を取れるようになった

今までは

mysql56 1> SELECT @@pseudo_thread_id;
+--------------------+
| @@pseudo_thread_id |
+--------------------+
|                  3 |
+--------------------+
1 row in set (0.00 sec)

mysql56 1>SELECT get_lock('yoku0825', 1);
+-------------------------+
| get_lock('yoku0825', 1) |
+-------------------------+
|                       1 |
+-------------------------+
1 row in set (0.02 sec)

mysql56 2> SELECT is_used_lock('yoku0825');
+--------------------------+
| is_used_lock('yoku0825') |
+--------------------------+
|                        3 |
+--------------------------+
1 row in set (0.00 sec)

こんなロックを取った状態で次のロックを取ると


mysql56 1> SELECT get_lock('yoku08253', 1);
+--------------------------+
| get_lock('yoku08253', 1) |
+--------------------------+
|                        1 |
+--------------------------+
1 row in set (0.00 sec)

mysql56 2> SELECT is_used_lock('yoku0825');
+--------------------------+
| is_used_lock('yoku0825') |
+--------------------------+
|                     NULL |
+--------------------------+
1 row in set (0.00 sec)

何も言われずに古い方のロックはリリースされていた。
これが、


mysql57 1> SELECT @@pseudo_thread_id;
+--------------------+
| @@pseudo_thread_id |
+--------------------+
|                 89 |
+--------------------+
1 row in set (0.01 sec)

mysql57 1> SELECT get_lock('yoku0825', 1);
+-------------------------+
| get_lock('yoku0825', 1) |
+-------------------------+
|                       1 |
+-------------------------+
1 row in set (0.02 sec)

mysql57 2> SELECT is_used_lock('yoku0825');
+--------------------------+
| is_used_lock('yoku0825') |
+--------------------------+
|                       89 |
+--------------------------+
1 row in set (0.01 sec)

mysql57 1> SELECT get_lock('yoku08253', 1);
+--------------------------+
| get_lock('yoku08253', 1) |
+--------------------------+
|                        1 |
+--------------------------+
1 row in set (0.00 sec)

mysql57 2> SELECT is_used_lock('yoku0825');
+--------------------------+
| is_used_lock('yoku0825') |
+--------------------------+
|                       89 |
+--------------------------+
1 row in set (0.00 sec)

複数取っても勝手にリリースされなくなった。
ユーザーロックの状態もperformance_schemaで見られるようになった的なことが書いてあるんだけど

mysql57 2> SELECT * FROM performance_schema.metadata_locks;
Empty set (0.00 sec)

mysql57 2> SELECT @@performance_schema_max_metadata_locks;
+-----------------------------------------+
| @@performance_schema_max_metadata_locks |
+-----------------------------------------+
|                                      -1 |
+-----------------------------------------+
1 row in set (0.00 sec)


あれれ…まあいいや。
-1はautosizedって書いてある けど、実際autoでいくつに設定されたんだかよくわからん。。


ところでアレだ。ロックを順次取れるようになると必ず現れてくるアイツ。そう、アイツ。

mysql57 2> SELECT get_lock('yoku0826', 1);
+-------------------------+
| get_lock('yoku0826', 1) |
+-------------------------+
|                       1 |
+-------------------------+
1 row in set (0.00 sec)

mysql57 2> SELECT get_lock('yoku08253', 1000);

mysql57 1> SELECT get_lock('yoku0826', 1);
ERROR 3058 (HY000): Deadlock found when trying to get user-level lock; try rolling back transaction/releasing locks and restarting lock acquisition.

Error 3058番。ちゃんと検出してくれるのはありがたいんだけど、この間も2番目のスレッドはget_lock関数で待ちっぱなしの状態で勝手にリリースはしてくれない。
release_lockかrelease_all_locksでリリースしてやらないとダメ。


mysql57 1> SELECT release_all_locks();
+---------------------+
| release_all_locks() |
+---------------------+
|                   2 |
+---------------------+
1 row in set (0.00 sec)

mysql57 2> SELECT get_lock('yoku08253', 1000);
+-----------------------------+
| get_lock('yoku08253', 1000) |
+-----------------------------+
|                           1 |
+-----------------------------+
1 row in set (1 min 30.79 sec)

InnoDBのデッドロックと違って *勝手にリリースしてくれない* ので、エラーをハンドルしたらrelease_lockするか接続を閉じればロックは開放されるのでそうしなければならない。
そう、お前のことだ、 *つなぎっぱなしのConnector/J氏*


MySQL :: MySQL 5.7 Release Notes :: Changes in MySQL 5.7.5 (2014-09-25, Milestone 15)

ここで"get_lock"って探すと詳しく書いてありました。

0 件のコメント :

コメントを投稿