有没有办法选择/显示所有当前使用该GET_LOCK
功能取出的锁?
请注意,GET_LOCK
锁与表锁不同,就像那些获得的锁一样LOCK TABLES
- 想知道如何查看这些锁的读者应该阅读Detecting locked tables (locked by LOCK TABLE)
有没有办法选择/显示所有当前使用该GET_LOCK
功能取出的锁?
请注意,GET_LOCK
锁与表锁不同,就像那些获得的锁一样LOCK TABLES
- 想知道如何查看这些锁的读者应该阅读Detecting locked tables (locked by LOCK TABLE)
从 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
可以通过SELECT
在performance_schema.metadata_locks
桌子上运行来查看。如文档中所述,GET_LOCK
锁具有OBJECT_TYPE
of '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_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)
从 MySQL 5.7 开始,性能模式公开了所有元数据锁,包括与GET_LOCK()
函数相关的锁。
见http://dev.mysql.com/doc/refman/5.7/en/metadata-locks-table.html
SHOW FULL PROCESSLIST;
你会看到里面的锁
如果您只想确定当前是否持有特定的命名锁,您可以使用IS_USED_LOCK
:
SELECT IS_USED_LOCK('foobar');
如果某个连接持有锁,则返回该连接的 ID;否则,结果为NULL
。
如果您知道锁的名称,我发现了以下可以使用的方法
select IS_USED_LOCK('lockname');
但是我没有找到有关如何列出所有名称的任何信息。
您还可以使用此脚本在 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
另一种简单的方法是使用:
mysqladmin debug
这会将大量信息(包括锁)转储到错误日志中。