65

有没有办法选择/显示所有当前使用该GET_LOCK功能取出的锁?

请注意,GET_LOCK锁与表锁不同,就像那些获得的锁一样LOCK TABLES- 想知道如何查看这些锁的读者应该阅读Detecting locked tables (locked by LOCK TABLE)

4

7 回答 7

24

从 MySQL 5.7 开始,这是可能的,但需要首先mdl在表中启用仪器performance_schema.setup_instruments。您可以通过运行以下命令临时执行此操作(直到服务器下次重新启动):

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 才能使配置更改生效。)

在仪器启用您取出的锁mdl可以通过SELECTperformance_schema.metadata_locks桌子上运行来查看。如文档中所述,GET_LOCK锁具有OBJECT_TYPEof '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中有充分的记录,但有一点值得注意:该OWNER_THREAD_ID没有包含持有锁的线程的连接ID(如将显示在PROCESSLIST或返回CONNECTION_ID())。令人困惑的是,术语“线程 ID”有时在 MySQL 文档中用作“连接 ID”的同义词,但这不是其中之一。如果您想确定持有锁的连接的连接ID(例如,为了使用 终止该连接KILL),您需要查找PROCESSLIST_IDTHREAD_IDperformance_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)
于 2017-02-21T00:02:12.083 回答
22

从 MySQL 5.7 开始,性能模式公开了所有元数据锁,包括与GET_LOCK()函数相关的锁。

http://dev.mysql.com/doc/refman/5.7/en/metadata-locks-table.html

于 2015-04-30T20:40:31.130 回答
12
SHOW FULL PROCESSLIST;

你会看到里面的锁

于 2012-07-11T15:43:01.003 回答
7

如果您只想确定当前是否持有特定的命名锁,您可以使用IS_USED_LOCK

SELECT IS_USED_LOCK('foobar');

如果某个连接持有锁,则返回该连接的 ID;否则,结果为NULL

于 2017-02-25T12:20:00.497 回答
2

如果您知道锁的名称,我发现了以下可以使用的方法

select IS_USED_LOCK('lockname');

但是我没有找到有关如何列出所有名称的任何信息。

于 2015-06-30T23:18:30.330 回答
2

来自这篇文章的参考:

您还可以使用此脚本在 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
于 2016-06-20T09:15:22.023 回答
-1

另一种简单的方法是使用:

mysqladmin debug 

这会将大量信息(包括锁)转储到错误日志中。

于 2015-02-19T17:56:21.403 回答