首页/数据/数据库速查/锁等待排查(sys.innodb_lock_waits)
性能与调优57 条

锁等待排查(sys.innodb_lock_waits)

锁等待诊断三板斧:谁在等(blocked)、谁挡着(blocking)、被什么锁(锁类型+索引);sys 视图已把三表联查封装好。

数据库速查数据更新于 2026-10-13

锁等待排查是什么

锁等待排查要回答三个问题:谁在等、谁挡着、被什么锁挡住。系统视图已经把底层的几张表联查封装好了,直接查询就能拿到等待关系、等待时长,以及阻塞方的语句与会话编号。定位到之后先别急着终止会话,确认阻塞事务的规模与影响面再决定处置方式。

基本信息

用途定位锁等待的等待方与阻塞方
核心视图锁等待视图,已封装等待关系查询
关键字段等待开始时间、等待语句、阻塞语句、阻塞会话编号
处置手段终止语句或终止会话,后者会触发回滚
前置动作先确认阻塞事务的规模与业务影响
风险提示大事务被终止后进入回滚,耗时可能很长

典型使用场景

  • 接口大面积超时:确认是否出现锁等待链
  • 在线改表被阻塞:确认是谁握着表的元数据锁
  • 批量更新引发阻塞:找到写了大量行的会话
  • 死锁复盘:确认事务的加锁顺序
  • 巡检输出等待时长与阻塞视图
  • 处置前的取证:记录语句与事务开始时间

定位阻塞链

定位阻塞链
SELECT * FROM sys.innodb_lock_waits\G   # 等待方、阻塞方与等待时长一览
SELECT THREAD_ID, PROCESSLIST_ID, PROCESSLIST_INFO   # 追到阻塞会话的完整语句
FROM performance_schema.threads
WHERE PROCESSLIST_ID = 12345;
KILL 12345;   # 评估影响之后再处置

相关视图

相关视图
SELECT * FROM information_schema.innodb_trx\G   # 长事务视角:事务状态、开始时间、改动行数
SELECT INDEX_NAME, LOCK_TYPE, LOCK_MODE, LOCK_DATA   # 8.0 可看锁住的具体对象
FROM performance_schema.data_locks
WHERE OBJECT_NAME = 'orders' LIMIT 50;   # 结合对象名定位热点表

关键字段读法

字段含义处置用途
等待时长等待已持续多久时间越长业务影响越大
等待方语句正在等待的查询确认业务受影响的范围
阻塞方语句挡住别人的查询判断是慢语句还是大事务
阻塞会话编号阻塞方会话标识处置时的操作对象
事务开始时间阻塞事务何时开启时间很长说明存在长事务
事务改动行数事务已经修改多少行行数大意味着回滚代价高
加锁模式共享锁还是排他锁判断能否并发读取
终止会话是大事务回滚的开始:回滚耗时可能比原事务执行还久,动手前先看它改了多少行,并确认真实业务影响面。
只终止等待方不解决根因:等待方被终止后新请求会立刻补位继续等待,必须处理阻塞方,或优化它的语句与索引。
加锁范围与条件列的索引直接相关:条件列没有索引时,更新会锁住扫描到的所有行,补索引往往比终止会话更有效。

锁等待处置清单

  • 先记录等待语句、阻塞语句与事务开始时间
  • 确认阻塞事务改动的行数与已经持续的时间
  • 评估终止会话带来的回滚代价
  • 终止之前先联系业务方确认影响面
  • 处置后观察等待队列是否真正消退
  • 把成因落到索引或事务边界上做根治
锁等待与死锁不是同一件事:单次等待可能只是短暂竞争,而死锁由数据库自行检测并回滚其中一个事务,遇到死锁要顺着加锁顺序去改业务逻辑,而不是只盯着某一条语句。

易错点

  • 只终止等待方不处理阻塞方:等待队列立刻被新请求填满,问题原样存在
  • 在生产直接终止大事务:回滚风暴拖慢整个实例,处置前必须评估改动行数
  • 不看条件列索引就反复终止会话:根因是锁范围过大,补索引才能减少锁冲突
  • 把锁等待当网络问题排查:等待发生在数据库内部,链路排查方向完全错误
  • 不做任何记录就直接清场:事后复盘缺少证据,同样的阻塞还会再来一次

数据来源与参考

  • MySQL 8.0 Reference Manual: sys schema innodb_lock_waits
  • MySQL 8.0 Reference Manual: KILL

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌