如何分析innodb死锁日志_mysql死锁诊断

来源:这里教程网 时间:2026-02-28 20:38:15 作者:

直接看日志就能定位死锁根因,关键不是“有没有日志”,而是“怎么看懂每一段在说什么”。InnoDB死锁日志结构固定、信息密集,掌握几个核心字段和逻辑关系,5分钟内就能理清谁锁了谁、为什么卡住。

盯住LATEST DETECTED DEADLOCK标识

死锁日志一定以LATEST DETECTED DEADLOCK开头,这是整段日志的锚点。它后面紧跟着时间戳(如 2025-12-23 10:22:18),代表死锁被InnoDB检测到的确切时刻。这个时间要和业务异常时间比对——如果应用报“Lock wait timeout”却没对应死锁日志,大概率是锁等待超时而非死锁。

拆解两个事务的持有锁与等待锁

日志中会明确标出 *** (1) TRANSACTION 和 *** (2) TRANSACTION。重点对比两处:

*** (1) HOLDS THE LOCK(S):事务1当前持有哪些锁(比如 X locks rec but not gap on index PRIMARY,说明它在主键索引上加了行级排他锁) *** (1) WAITING FOR THIS LOCK TO BE GRANTED:事务1正在等什么锁(比如等事务2持有的某个二级索引上的S锁) 同理看事务2的持有锁和等待锁,自然就浮现循环等待链:A等B的锁,B又等A的锁

结合SQL语句还原执行路径

每个事务块里都有一行 query id xxx, SQL thread yyy, query zzz,直接给出引发死锁的具体语句,例如:

delete from orders where user_id = 123 and status = 'pending'

注意两点:

这条SQL是否走了预期索引?用 EXPLAIN 验证——走错索引会导致锁住不该锁的行或间隙 是否在事务中混用了 SELECT ... FOR UPDATE 和普通 UPDATE?顺序不一致极易触发死锁

快速判断回滚对象和优化方向

InnoDB总选一个事务回滚,日志末尾会写明:

*** WE ROLL BACK TRANSACTION (2)

被回滚的事务通常是 undo log 更小、修改行数更少的那个。但这不是优化目标——真正要改的是:

统一多事务对相同资源的访问顺序(比如都先更新用户表,再更新订单表) 缩短事务生命周期,避免在事务中做RPC调用或文件读写 检查隔离级别,REPEATABLE READ 下间隙锁易引发死锁,确认业务能否降为 READ COMMITTED

相关推荐