sys.innodb_lock_waits需关联innodb_trx和processlist才能定位持锁会话及sql;blocking_query常为null因阻塞事务空闲未提交,此时应查blocking_trx_started和sleep状态连接。

MySQL 8.0+ 中,sys.innodb_lock_waits 是最省力的入口,但仅靠它查不到“谁在持锁”,必须关联 sys.processlist 和 information_schema.INNODB_TRX 才能定位到具体会话和 SQL。
为什么 sys.innodb_lock_waits 的 blocking_query 经常是 NULL
因为阻塞方事务可能早已执行完语句、处于空闲状态(COMMAND = 'Sleep'),但事务未提交,锁仍被持有。此时 blocking_query 字段为空,但 blocking_trx_started 时间很早——这是典型长事务持锁信号。不能据此认为“没人在执行 SQL”,恰恰相反,它大概率是漏 COMMIT 或应用卡在外部调用中。
-
blocking_pid是processlist.id,可直接用于KILL QUERY或KILL - 若
blocking_pid查不到对应连接(比如返回空),要查information_schema.PROCESSLIST中COMMAND = 'Sleep'且TIME > 300的记录 - 注意:
blocking_trx_id≠processlist.id,需通过INNODB_TRX.trx_mysql_thread_id桥接
如何把锁等待链闭环到具体 SQL 和会话
单查 sys.innodb_lock_waits 只能看到“谁等谁”,看不到持锁者最后执行了什么。真正闭环需要三表关联:
- 从
sys.innodb_lock_waits拿到blocking_trx_id - 连
information_schema.INNODB_TRX查trx_mysql_thread_id和trx_query(若为空,说明事务已空闲) - 再连
sys.processlist(或information_schema.PROCESSLIST)获取ID、USER、HOST、INFO(即最后执行的语句)
典型查询:
SELECT w.waiting_pid, w.waiting_query, w.blocking_pid,
p.USER, p.HOST, p.DB, p.INFO AS blocking_last_sql,
t.trx_started, t.trx_state, t.trx_rows_locked
FROM sys.innodb_lock_waits w
JOIN information_schema.INNODB_TRX t ON w.blocking_trx_id = t.trx_id
JOIN sys.processlist p ON t.trx_mysql_thread_id = p.id;
排查时容易忽略的两个关键点
sys.innodb_lock_waits 视图本身不依赖 performance_schema instrument 开关,但它背后的锁数据源(如 data_locks)默认可能未启用采集。如果查不到等待链,先确认:
-
SELECT @@performance_schema;必须为 1 -
SELECT * FROM performance_schema.setup_instruments WHERE NAME = 'wait/lock/innoDB';的ENABLED要是YES
另外,sys.innodb_lock_waits 不展示锁在哪一行——想看到 LOCK_DATA(比如主键值 12345 或间隙 10, 20),必须查 performance_schema.data_locks 并关联 data_lock_waits,否则无法判断是热点行争用还是间隙锁冲突。











