web-dev-qa-db-ja.com

get_lockの現在のロックをすべて表示する

GET_LOCK function を使用して取り出されたすべての現在のロックを選択/表示する方法はありますか?

GET_LOCKロックは、LOCK TABLESで取得したもののように、テーブルロックとは異なることに注意してください-thoseロックは次のように読み取る必要があります ロックされたテーブルの検出(LOCK TABLEによってロック)

57
braunbaer

MySQL 5.7以降、パフォーマンススキーマは、GET_LOCK()関数に関連するロックを含むすべてのメタデータロックを公開します。

http://dev.mysql.com/doc/refman/5.7/en/metadata-locks-table.html を参照してください

18
Marc Alff
SHOW FULL PROCESSLIST;

あなたはそこにロックが表示されます

14
Robert

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)
13
Mark Amery

particularという名前のロックが現在保持されているかどうかだけを確認したい場合は、 IS_USED_LOCK を使用できます。

SELECT IS_USED_LOCK('foobar');

何らかの接続がロックを保持している場合、その接続のIDが返されます。それ以外の場合、結果はNULLです。

5
Mark Amery

ロックの名前を知っている場合に使用できる次の方法を見つけました

select IS_USED_LOCK('lockname');

ただし、すべての名前をリストする方法についての情報は見つかりませんでした。

1
arheops

別の簡単な方法は以下を使用することです:

mysqladmin debug 

これにより、多くの情報(ロックを含む)がエラーログにダンプされます。

0
Sonicthoughts

この投稿からの参照:

このスクリプトを使用して、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
0
Anvesh