mysql 8.0+ 应优先使用 performance_schema.data_lock_waits 查锁等待关系,再通过 blocking_trx_id 关联 data_locks 定位持锁事务及具体行/页;需启用相关 instruments 并授权。

查哪些线程正在等锁:看 data_lock_waits 表
MySQL 8.0+ 的 performance_schema 把锁等待关系拆得挺细,核心就是 data_lock_waits 这张表。它不直接告诉你“谁持有什么锁”,而是告诉你“谁在等谁的锁”——顺着这个关系反推,就能定位持有者。
常见错误现象是执行 SELECT 突然卡住、事务长时间不返回,或者应用报错 Lock wait timeout exceeded。这时候别急着 kill,先查这张表:
SELECT * FROM performance_schema.data_lock_waits\G
重点关注三列:BLOCKING_ENGINE_LOCK_ID(谁在拦路)、REQUESTING_ENGINE_LOCK_ID(谁在干等)、BLOCKING_TRX_ID(持有锁的事务 ID)。
-
BLOCKING_TRX_ID是关键入口,拿它去查data_locks表能知道它到底锁了哪行/哪页 - 注意:该表只记录“当前正在发生的等待”,历史等待不会保留
- 默认可能没开采集,要确认
setup_instruments中wait/lock/metadata/sql/mdl和wait/lock/innodb/innodb_lock_monitor是ENABLED
查某个事务持有哪些锁:连查 data_locks + threads
光知道“谁在等”还不够,得知道“谁在占”。data_locks 表存所有活跃锁信息,但它的 THREAD_ID 是内部 ID,得关联 threads 表才能看出是哪个连接、哪个 SQL 在干活。
典型使用场景:发现某个事务 ID(比如 12345)老不提交,想确认它锁了什么资源,避免盲目 KILL。
SELECT t.PROCESSLIST_ID, t.PROCESSLIST_INFO, d.OBJECT_SCHEMA, d.OBJECT_NAME, d.INDEX_NAME, d.LOCK_TYPE, d.LOCK_MODE, d.LOCK_DATA FROM performance_schema.data_locks d JOIN performance_schema.threads t ON d.THREAD_ID = t.THREAD_ID WHERE d.TRANSACTION_ID = 12345;
-
LOCK_DATA字段对行锁特别有用:如果是主键值,会显示具体PRIMARY KEY值;如果是二级索引,可能显示索引字段内容 -
LOCK_TYPE是RECORD表示行锁,TABLE表示表级锁(比如ALTER TABLE期间) - 如果
PROCESSLIST_INFO为空,说明该线程当前没在执行 SQL,可能卡在锁等待或 sleep 状态
为什么 INFORMATION_SCHEMA.INNODB_TRX 不够用
老办法常用 INFORMATION_SCHEMA.INNODB_TRX 查事务,但它只给事务 ID、开始时间、SQL 摘要、锁等待状态这些概览信息,不暴露“锁了哪几行”“锁类型是否冲突”这种细节。
比如你看到 TRX_STATE = 'LOCK WAIT',但不知道它在等哪条记录;或者看到一个长事务 TRX_STARTED 很早,却无法判断它是否真的还拿着行锁(可能已经释放但事务没提交)。
-
INNODB_TRX的TRX_ROWS_LOCKED是估算值,不准,不能当依据 - 它不区分意向锁(
IX)、间隙锁(GAP)、临键锁(NEXT-KEY),而这些恰恰是死锁和幻读的关键 - MySQL 8.0 后官方明确推荐优先用
performance_schema.data_locks替代旧视图
容易被忽略的初始化开关和权限
开了 performance_schema 不等于自动收集锁信息。很多线上库默认关掉了锁相关的 instruments,查出来永远是空。
必须手动启用,而且需要 root 或带 SELECT 权限的账号访问 performance_schema 库。
- 检查开关:
SELECT NAME, ENABLED FROM performance_schema.setup_instruments WHERE NAME LIKE '%lock%';
关注wait/lock/innodb/innodb_lock_monitor和wait/lock/metadata/sql/mdl - 临时开启:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME IN ('wait/lock/innodb/innodb_lock_monitor', 'wait/lock/metadata/sql/mdl'); - 重启后失效?那就得加到配置文件:
performance-schema-instrument='wait/lock/%=ON' - 普通用户查不到?给权限:
GRANT SELECT ON performance_schema.* TO 'user'@'%';
锁信息不是实时全量采集的,它是采样式记录,尤其高并发下可能漏掉瞬时锁。真要抓死锁现场,得配合 innodb_print_all_deadlocks = ON 写日志,而不是只盯 performance_schema。











