GET_LOCK
function を使用して取り出されたすべての現在のロックを選択/表示する方法はありますか?
GET_LOCK
ロックは、LOCK TABLES
で取得したもののように、テーブルロックとは異なることに注意してください-thoseロックは次のように読み取る必要があります ロックされたテーブルの検出(LOCK TABLEによってロック)
MySQL 5.7以降、パフォーマンススキーマは、GET_LOCK()
関数に関連するロックを含むすべてのメタデータロックを公開します。
http://dev.mysql.com/doc/refman/5.7/en/metadata-locks-table.html を参照してください
SHOW FULL PROCESSLIST;
あなたはそこにロックが表示されます
MySQL 5.7以降、これは可能ですが、最初に performance_schema.setup_instruments
テーブルでmdl
インストゥルメントを有効にする必要があります。次を実行することにより、一時的に(サーバーが再起動されるまで)これを行うことができます。
UPDATE performance_schema.setup_instruments
SET enabled = 'YES'
WHERE name = 'wait/lock/metadata/sql/mdl';
または永続的に、次の文言を[mysqld]
ファイルのmy.cnf
セクションに追加することにより(または、MySQLがインストール時に読み込む任意の設定ファイル):
[mysqld]
performance_schema_instrument = 'wait/lock/metadata/sql/mdl=ON'
(当然、後者のアプローチをとる場合、設定変更を有効にするにはMySQLを再起動する必要があります。)
取り出すロックaftermdl
インストゥルメントが有効になっていることを確認するには、 performance_schema.metadata_locks
テーブルに対してSELECT
を実行します。ドキュメントに記載されているように、GET_LOCK
ロックのOBJECT_TYPE
は'USER LEVEL LOCK'
であるため、WHERE
句を使用してクエリをフィルター処理できます。
mysql> SELECT GET_LOCK('foobarbaz', -1);
+---------------------------+
| GET_LOCK('foobarbaz', -1) |
+---------------------------+
| 1 |
+---------------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM performance_schema.metadata_locks
-> WHERE OBJECT_TYPE='USER LEVEL LOCK'
-> \G
*************************** 1. row ***************************
OBJECT_TYPE: USER LEVEL LOCK
OBJECT_SCHEMA: NULL
OBJECT_NAME: foobarbaz
OBJECT_INSTANCE_BEGIN: 139872119610944
LOCK_TYPE: EXCLUSIVE
LOCK_DURATION: EXPLICIT
LOCK_STATUS: GRANTED
SOURCE: item_func.cc:5482
OWNER_THREAD_ID: 35
OWNER_EVENT_ID: 3
1 row in set (0.00 sec)
mysql>
この結果の列の意味は、ほとんどの場合 https://dev.mysql.com/doc/refman/en/metadata-locks-table.html で十分に文書化されていますが、混乱の1つのポイントは注目に値する:OWNER_THREAD_ID
列には、ロックを保持するスレッドのnotconnection ID(PROCESSLIST
に表示されるか、CONNECTION_ID()
によって返される)が含まれます。紛らわしいことに、用語「スレッドID」は、MySQLのドキュメントで「接続ID」の同義語として使用されることがありますが、これはnotの1つです。 connectionロックを保持している接続のIDを決定する場合(たとえば、その接続を KILL
で強制終了するため)、検索する必要があります。 PROCESSLIST_ID
テーブルのTHREAD_ID
に対応するperformance_schema.threads
。たとえば、上のロックを保持していた接続を強制終了するには...
mysql> SELECT OWNER_THREAD_ID FROM performance_schema.metadata_locks
-> WHERE OBJECT_TYPE='USER LEVEL LOCK'
-> AND OBJECT_NAME='foobarbaz';
+-----------------+
| OWNER_THREAD_ID |
+-----------------+
| 35 |
+-----------------+
1 row in set (0.00 sec)
mysql> SELECT PROCESSLIST_ID FROM performance_schema.threads
-> WHERE THREAD_ID=35;
+----------------+
| PROCESSLIST_ID |
+----------------+
| 10 |
+----------------+
1 row in set (0.00 sec)
mysql> KILL 10;
Query OK, 0 rows affected (0.00 sec)
particularという名前のロックが現在保持されているかどうかだけを確認したい場合は、 IS_USED_LOCK
を使用できます。
SELECT IS_USED_LOCK('foobar');
何らかの接続がロックを保持している場合、その接続のIDが返されます。それ以外の場合、結果はNULL
です。
ロックの名前を知っている場合に使用できる次の方法を見つけました
select IS_USED_LOCK('lockname');
ただし、すべての名前をリストする方法についての情報は見つかりませんでした。
別の簡単な方法は以下を使用することです:
mysqladmin debug
これにより、多くの情報(ロックを含む)がエラーログにダンプされます。
このスクリプトを使用して、MySQLでロックを見つけることもできます。
SELECT
pl.id
,pl.user
,pl.state
,it.trx_id
,it.trx_mysql_thread_id
,it.trx_query AS query
,it.trx_id AS blocking_trx_id
,it.trx_mysql_thread_id AS blocking_thread
,it.trx_query AS blocking_query
FROM information_schema.processlist AS pl
INNER JOIN information_schema.innodb_trx AS it
ON pl.id = it.trx_mysql_thread_id
INNER JOIN information_schema.innodb_lock_waits AS ilw
ON it.trx_id = ilw.requesting_trx_id
AND it.trx_id = ilw.blocking_trx_id