锁等待排查是什么
锁等待排查要回答三个问题:谁在等、谁挡着、被什么锁挡住。系统视图已经把底层的几张表联查封装好了,直接查询就能拿到等待关系、等待时长,以及阻塞方的语句与会话编号。定位到之后先别急着终止会话,确认阻塞事务的规模与影响面再决定处置方式。
基本信息
| 用途 | 定位锁等待的等待方与阻塞方 |
|---|---|
| 核心视图 | 锁等待视图,已封装等待关系查询 |
| 关键字段 | 等待开始时间、等待语句、阻塞语句、阻塞会话编号 |
| 处置手段 | 终止语句或终止会话,后者会触发回滚 |
| 前置动作 | 先确认阻塞事务的规模与业务影响 |
| 风险提示 | 大事务被终止后进入回滚,耗时可能很长 |
典型使用场景
- 接口大面积超时:确认是否出现锁等待链
- 在线改表被阻塞:确认是谁握着表的元数据锁
- 批量更新引发阻塞:找到写了大量行的会话
- 死锁复盘:确认事务的加锁顺序
- 巡检输出等待时长与阻塞视图
- 处置前的取证:记录语句与事务开始时间
定位阻塞链
定位阻塞链
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; # 结合对象名定位热点表关键字段读法
| 字段 | 含义 | 处置用途 |
|---|---|---|
| 等待时长 | 等待已持续多久 | 时间越长业务影响越大 |
| 等待方语句 | 正在等待的查询 | 确认业务受影响的范围 |
| 阻塞方语句 | 挡住别人的查询 | 判断是慢语句还是大事务 |
| 阻塞会话编号 | 阻塞方会话标识 | 处置时的操作对象 |
| 事务开始时间 | 阻塞事务何时开启 | 时间很长说明存在长事务 |
| 事务改动行数 | 事务已经修改多少行 | 行数大意味着回滚代价高 |
| 加锁模式 | 共享锁还是排他锁 | 判断能否并发读取 |
终止会话是大事务回滚的开始:回滚耗时可能比原事务执行还久,动手前先看它改了多少行,并确认真实业务影响面。
只终止等待方不解决根因:等待方被终止后新请求会立刻补位继续等待,必须处理阻塞方,或优化它的语句与索引。
加锁范围与条件列的索引直接相关:条件列没有索引时,更新会锁住扫描到的所有行,补索引往往比终止会话更有效。
锁等待处置清单
- 先记录等待语句、阻塞语句与事务开始时间
- 确认阻塞事务改动的行数与已经持续的时间
- 评估终止会话带来的回滚代价
- 终止之前先联系业务方确认影响面
- 处置后观察等待队列是否真正消退
- 把成因落到索引或事务边界上做根治
锁等待与死锁不是同一件事:单次等待可能只是短暂竞争,而死锁由数据库自行检测并回滚其中一个事务,遇到死锁要顺着加锁顺序去改业务逻辑,而不是只盯着某一条语句。