SHOW ENGINE INNODB STATUS 中需重点查看 LATEST DETECTED DEADLOCK 区块,比对两个事务的锁等待关系、持有锁、表访问顺序及索引类型,结合 ORDER BY 确保加锁顺序一致,并通过 SQLSTATE 40001 或错误码 1213 精准识别死锁以实现带退避的重试。

死锁发生时,SHOW ENGINE INNODB STATUS 看什么
死锁不是报错就完事,MySQL 会自动回滚其中一个事务,但真正要定位根因,得靠 SHOW ENGINE INNODB STATUS 输出里的 LATEST DETECTED DEADLOCK 区块。
这个区块里最关键的三行是:WAITING FOR THIS LOCK TO BE GRANTED(谁在等哪把锁)、HOLDS THE LOCK(S)(谁持有什么锁)、以及两段 TRANSACTION 的 mysql tables in use 和 lock struct(s)。别只扫一眼“Deadlock found”,重点比对两个事务访问的表顺序、索引类型、锁范围(record vs gap)。
- 常见错误现象:看到
lock_mode X locks rec but not gap waiting却误以为只是行锁冲突,其实可能是唯一索引上的插入意向锁(INSERT INTENTION)和间隙锁(gap lock)对上了 - 使用场景:线上突发大量
Deadlock found when trying to get lock,但应用层没做重试,导致部分写入静默失败 - 参数差异:该命令输出不依赖配置,但默认只保留最近一次死锁信息;如需长期追踪,得搭配定期采集脚本或开启
innodb_print_all_deadlocks = ON写入 error log
为什么降低事务隔离级别未必能解死锁
很多人第一反应是把 REPEATABLE READ 改成 READ COMMITTED,觉得“少加点锁就行”。但实际中,这往往治标不治本,甚至引入新问题。
READ COMMITTED 下虽然不加间隙锁(gap lock),但会增加幻读风险;更关键的是——它不减少行锁数量,也不改变加锁顺序。如果两个事务仍以不同顺序更新同一组主键,照样死锁。
- 常见错误现象:改完隔离级别后死锁变少了,但紧接着出现数据不一致(比如并发扣库存时多扣或少扣)
- 使用场景:金融类业务强制要求可重复读语义,盲目降级会导致业务逻辑失效
- 性能影响:在高并发更新热点行时,
READ COMMITTED可能导致更多锁等待(因每次SELECT ... FOR UPDATE都要重新加锁),反而拖慢吞吐
如何用 SELECT ... FOR UPDATE 控制加锁顺序
90% 的死锁源于多个事务以不同顺序获取锁。最稳妥的做法,是在事务开头就用 SELECT ... FOR UPDATE 按固定规则(比如主键升序)预先锁定所有可能涉及的行。
注意:必须用能命中索引的条件,否则会升级为表锁;且不能只查不更新——否则锁会在语句结束就释放,起不到保护作用。
- 常见错误现象:写了个
SELECT id FROM t WHERE status = 'pending' ORDER BY id LIMIT 10 FOR UPDATE,但status字段没索引,结果锁了整张表 - 使用场景:订单状态机、库存预占、分页任务分发等需要“先选再改”的流程
- 参数差异:加
ORDER BY id是为了确保所有事务按相同物理顺序加锁;若用ORDER BY created_at,而该字段有重复值,InnoDB 可能内部排序不稳定,仍存在风险
应用层重试时,Deadlock found when trying to get lock 怎么识别
MySQL 报这个错误时,返回的 SQLSTATE 是 40001,错误码是 1213。别依赖错误消息字符串匹配,尤其在多语言环境或中间件封装后容易失效。
重试逻辑必须带退避(比如指数退避),且限制最大重试次数(通常 ≤ 3)。无脑重试 + 无延迟,只会让死锁更密集。
- 常见错误现象:捕获到
"Deadlock found"就立刻重试,结果在毫秒级内反复触发,压垮数据库连接池 - 使用场景:Spring 的
@Transactional默认不重试,需手动用TransactionTemplate或 AOP 封装 - 兼容性影响:某些 ORM(如 SQLAlchemy)在执行
session.commit()时才抛出死锁异常,不是在session.add()阶段,所以重试粒度得覆盖整个事务块
死锁真正的难点不在发现,而在复现和归因——因为它是时间敏感的竞态,日志里看不到“谁先执行了哪一步”。所以线上一旦出现,优先抓全量慢日志 + INNODB STATUS 快照,而不是急着调参。










