首页/数据/SQL 速查/死锁日志解读与预防
性能与执行计划72 条

死锁日志解读与预防

SHOW ENGINE INNODB STATUS 的 LATEST DETECTED DEADLOCK 段记录最近死锁的事务与等待;根本对策是统一加锁顺序、缩短事务。

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

死锁日志怎么读

死锁不是故障,而是并发控制机制的主动止损:两个及以上事务循环等待对方持有的锁,数据库挑选代价较小的一方回滚,让其他事务继续推进。状态输出里保留最近一次死锁现场,包含两个事务正在执行的语句、各自持有的锁与正在等待的锁,以及被回滚的是哪一方。读它的目的是找到访问顺序上的冲突点,而不是找出「谁的错」。

基本信息

适用平台MySQL 8.0(InnoDB)
查看方式查看引擎状态,输出中定位最近一次死锁的段落
保留范围默认只保留最近一次,需打开专门开关才能记录全部
被回滚方引擎选择代价较小的事务回滚,属于正常机制
应用要求捕获死锁错误后回滚并重试整个事务

典型使用场景

  • 线上偶发报错排查:确认是否真的发生死锁以及涉及哪两条语句
  • 批量任务与在线业务互撞:定位哪一类的访问模式在制造循环等待
  • 上线前验证:把新增语句放进状态观察,看是否引入新的等待关系
  • 统计死锁频率:评估是否需要对访问顺序做统一规范
  • 复盘事故:把被回滚事务的语句与业务动作对应起来

查看与记录

查看与记录
-- 查看引擎状态,在输出中定位最近一次死锁段落
SHOW ENGINE INNODB STATUS;
-- 关注三块内容:
--   两个事务各自的语句、持有的锁与等待的锁
--   输出末尾会说明回滚了哪一方
--   若出现等待关系成环,即构成死锁

-- 排查期打开开关,把每次死锁都写入错误日志
SET GLOBAL innodb_print_all_deadlocks = ON;

-- 结合锁信息表定位当前正在等待的锁
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.data_lock_waits;

-- 排查结束后记得关闭,避免日志量持续增长
SET GLOBAL innodb_print_all_deadlocks = OFF;

输出段读法

内容块说明用它做什么
事务语句参与死锁的双方正在执行的语句定位业务代码与访问路径
持有锁列表每个事务已拿到的锁找到冲突的键与区间
等待锁列表每个事务正在等待的锁看出等待关系如何成环
回滚标记指明被牺牲的事务确认应用需要从哪一步重试
记录范围默认仅最近一次历史多次排查需打开全量记录开关
多数死锁的根因在应用访问行为上:同一批数据在不同代码路径里被按不同顺序更新,或者一次事务里锁了过多行。统一加锁顺序、缩短事务范围,比在数据库层调参数有效得多。
把死锁当成需要彻底消灭的对象会走进误区:只要存在并发写入,死锁就可能发生。正确的目标是让应用能接住它并重试,同时把发生频率控制在可接受范围。

易错点

  • 把死锁当纯数据库问题排查,忽略应用访问顺序这一主要根因,问题反复出现
  • 被回滚的事务直接报错给用户:这属于正常机制,应用应当幂等重试
  • 只保留最近一次记录就宣称「死锁很少发生」,实际频率需要打开全量记录统计
  • 打开全量记录后忘记关闭,错误日志持续增长,最终影响磁盘与采集
  • 重试时不重新读取数据:基于旧值重放事务,仍然会再次冲突

数据来源与参考

  • MySQL 8.0 Reference Manual · InnoDB Deadlocks
  • MySQL 8.0 Reference Manual · SHOW ENGINE Statement
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌