查不到 data_lock_waits 数据是因为 wait/lock/innodb% 类 instruments 默认禁用,需在 MySQL 启动配置中设置 performance-schema-instrument='wait/lock/innodb%=ON' 并重启,运行时无法动态启用。

为什么查不到 data_lock_waits 的数据?
不是 SQL 写错了,而是锁采集根本没开——performance_schema 默认开启,但 wait/lock/innodb% 类 instruments 多数是 DISABLED。运行 SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE 'wait/lock%';,如果 data_locks 或 data_lock_waits 对应的 ENABLED 列是 NO,那查出来永远为空。
必须在 MySQL 启动时配置文件中添加:performance-schema-instrument='wait/lock/innodb%=ON';运行时动态启用对锁类 instrument 无效,重启不可避免。
如何用 data_lock_waits 快速定位被阻塞事务?
performance_schema.data_lock_waits 是 MySQL 8.0 官方推荐的锁等待关系表,它直接给出“谁在等谁”,比老版 INNODB_LOCK_WAITS 更可靠(后者在 8.0 中已废弃)。
-
BLOCKING_ENGINE_TRANSACTION_ID是阻塞方的内部事务 ID(非trx_id),需关联INFORMATION_SCHEMA.INNODB_TRX查线程和 SQL -
REQUESTING_ENGINE_TRANSACTION_ID是被阻塞方的 ID,对应INNODB_TRX.trx_id - 一次查询就能拿到两者的映射关系,不用拼接多张表再 join
实操语句示例:
SELECT r.trx_id AS waiting_trx_id, r.trx_mysql_thread_id AS waiting_thread, r.trx_query AS waiting_sql, b.trx_id AS blocking_trx_id, b.trx_mysql_thread_id AS blocking_thread, b.trx_query AS blocking_sql FROM performance_schema.data_lock_waits w JOIN INFORMATION_SCHEMA.INNODB_TRX r ON r.trx_id = w.REQUESTING_ENGINE_TRANSACTION_ID JOIN INFORMATION_SCHEMA.INNODB_TRX b ON b.trx_id = w.BLOCKING_ENGINE_TRANSACTION_ID;
INNODB_TRX 中哪些字段最该盯住?
光知道“被卡住了”不够,得快速判断要不要 kill、能不能等、风险在哪。重点关注以下字段:
-
TRX_STATE = 'LOCK WAIT':确认是真阻塞,不是慢查询或网络延迟 -
TRX_STARTED:算下已卡多久,超过业务容忍阈值(比如 30 秒)就该干预 -
TRX_WAITING_LOCK_ID:可关联data_locks.LOCK_ID查具体锁在哪张表哪行 -
TRX_ROWS_LOCKED和TRX_ROWS_MODIFIED:值异常大(如锁了几万行)说明 SQL 没走索引,大概率是全表扫描加锁 -
TRX_ISOLATION_LEVEL:若为REPEATABLE READ且无索引条件,gap lock 风险更高
KILL 前必须确认的三件事
终止线程不是按下回车就完事,错杀可能让问题更糟:
- 先查
performance_schema.threads确认PROCESSLIST_USER和PROCESSLIST_HOST,避免误杀监控、备份或主从同步线程 - 用
SELECT * FROM performance_schema.events_statements_history WHERE thread_id = ? ORDER BY event_id DESC LIMIT 5;看被 kill 线程最近执行了什么,确认它没在做关键 DDL 或事务提交 - 优先 kill
blocking_thread,而不是waiting_thread;否则只是清掉一个等待者,阻塞源还在,其他事务继续卡住
真正麻烦的从来不是“怎么查”,而是查到之后不敢动、不敢 kill、不敢改 SQL —— 因为没人确认过那个 TRX_QUERY 背后是不是个定时任务里的 delete 全表操作,或者是个没加 where 条件的 update。


















