直接查sys.innodb_lock_waits即可定位阻塞源头,它整合waiting_pid、blocking_pid、wait_age、object_schema、object_name、index_name及sql_kill_blocking_query等关键字段,一行展示完整锁等待关系,比information_schema.innodb_lock_waits更直观高效。

直接查 sys.innodb_lock_waits 就能定位阻塞源头
MySQL 5.7+ 默认启用 sys 库,sys.innodb_lock_waits 是最简明的锁等待视图,不需要手动 JOIN 多张表。它把阻塞方、被阻塞方、等待时长、涉及表和索引都整合进一行结果里,比原始 information_schema.INNODB_LOCK_WAITS 更直观。
执行这条语句就能看到当前所有活跃的锁等待:
SELECT * FROM sys.innodb_lock_waits;
关键字段要盯住这几个:
-
waiting_pid和blocking_pid:对应SHOW PROCESSLIST中的 ID,可直接用于KILL -
wait_age:已等待秒数,数值越大越紧急 -
object_schema/object_name:锁发生在哪个库哪张表 -
index_name:具体是哪个索引上的锁(比如PRIMARY或idx_status) -
sql_kill_blocking_query:生成好的 KILL QUERY 命令,复制粘贴就能用
为什么 sys.innodb_lock_waits 有时查不到 blocking_query
常见现象是 blocking_query 字段为 NULL,不是视图坏了,而是阻塞事务早已执行完那条 SQL,现在正卡在 SLEEP、网络 IO、或没提交的事务里空转。这时候光看视图不够,得顺藤摸瓜。
按这个顺序查:
- 先从
blocking_pid查到线程 ID:SELECT THREAD_ID FROM performance_schema.threads WHERE PROCESSLIST_ID = <blocking_pid></blocking_pid> - 再查它最后执行的语句:
SELECT SQL_TEXT FROM performance_schema.events_statements_current WHERE THREAD_ID = <thread_id></thread_id> - 如果还是空,说明语句已退出,查历史:
SELECT SQL_TEXT FROM performance_schema.events_statements_history WHERE THREAD_ID = <thread_id> ORDER BY TIMER_START DESC LIMIT 1</thread_id>
注意:这些查询依赖 performance_schema 的采集开关,确保 setup_consumers 中启用了 events_statements_current 和 events_statements_history。
sys.innodb_lock_waits 在 MySQL 8.0 的行为差异
MySQL 8.0 把底层数据源从 information_schema 切到了 performance_schema.data_lock_waits,所以字段更细、精度更高,但代价是——它默认不显示未提交事务的完整上下文。
如果你发现 blocking_query 总是 NULL,且 waiting_query 明显在等某行更新,大概率是阻塞方持有一个长事务但没执行新 SQL。这时必须配合 INNODB_TRX 表确认:
SELECT trx_id, trx_started, trx_state, trx_mysql_thread_id, trx_query FROM information_schema.INNODB_TRX WHERE trx_state = 'RUNNING' AND trx_started <p>重点关注 <code>trx_state = 'RUNNING'</code> 但 <code>trx_query IS NULL</code> 的记录——这就是“静默持锁者”。</p><h3>别只盯着视图,<code>SHOW ENGINE INNODB STATUS</code> 才是真相现场</h3><p><code>sys.innodb_lock_waits</code> 是快照,<code>SHOW ENGINE INNODB STATUS\G</code> 是实时录像。尤其当锁等待刚发生、视图还没刷出数据时,它是最可靠的兜底手段。</p><p>执行后重点翻到 <code>TRANSACTIONS</code> 部分,找带 <code>LOCK WAIT</code> 标记的事务块。里面会明确写出:</p>
- 谁在等(
---TRANSACTION xxx, ACTIVE xxx sec, waiting for lock) - 谁在挡路(
mysql tables in use 1, locked 1后面跟着的lock struct(s)) - 锁在哪一行(
Record lock, heap no 5 PHYSICAL RECORD)
注意:SHOW ENGINE INNODB STATUS 输出是单次快照,不会自动刷新;而且默认不输出锁结构细节,需提前执行:SET GLOBAL innodb_status_output_locks = ON;











