You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

由重复键错误引发的两事务MySQL死锁问题排查求助

双事务下重复键引发死锁的解析

结合你提供的死锁日志和InnoDB锁机制,这个死锁的形成逻辑可以拆解成清晰的时序:

死锁形成的完整步骤

  1. 事务2(TRX 3802025922)先完成插入
    插入一条主键为K的记录,成功后持有这条记录的lock_mode X locks rec but not gap(排他行锁,仅锁定K对应的行,不含间隙锁)。

  2. 事务1(TRX 3802025924)触发重复键错误
    尝试插入同主键K的记录,InnoDB检查主键索引时发现K已存在,触发重复键错误。
    按照InnoDB规则,此时事务1会申请K对应行的lock mode S locks rec but not gap(共享行锁)——这么做是为了:如果事务2后续回滚,事务1能保证这段时间内没有其他事务修改或插入K,可以重试插入。
    但K的行锁被事务2的排他锁占用,所以事务1进入等待;关键是:事务1在做插入检测时,已经在主键索引中K所在的间隙(或相邻页的间隙)持有了插入意向锁(日志未直接显示,但这是死锁循环的核心)。

  3. 事务2未结束,继续执行新插入
    事务2紧接着插入另一条主键为M的记录,这个M落在主键索引的page 46338页,而该页的间隙锁正好被事务1之前持有的插入意向锁占用。
    事务2需要获取这个位置的lock_mode X insert intention(排他插入意向锁),但被事务1的锁阻塞,也进入等待。

  4. 双向等待形成死锁

    • 事务1等待事务2释放K的X行锁,才能拿到自己需要的S行锁;
    • 事务2等待事务1释放间隙的插入意向锁,才能完成新插入;
      双方互相阻塞,InnoDB检测到死锁后触发回滚。

为什么重复键会引发死锁?

你参考的官方文档提到“重复键错误会加共享锁”,这个逻辑完全适配你的场景:
重复键触发的共享锁申请,让事务1卡在等待事务2的排他锁;而事务2后续的插入操作又依赖事务1持有的间隙锁,形成了闭环的双向等待。文档里的3会话场景只是另一种触发形式,核心都是重复键导致的共享锁申请,和其他事务的锁操作形成循环依赖。

日志佐证

从你贴的死锁日志可以直接对应:

  • 事务2持有page 46337的X行锁(对应主键K),等待page 46338的插入意向锁;
  • 事务1等待page 46337的S行锁;
  • 隐含的是事务1持有page 46338相关的间隙锁——这是InnoDB插入的默认行为:插入前先获取插入意向锁,哪怕后续触发重复键错误,这个锁也不会立刻释放,直到事务结束。

内容的提问来源于stack exchange,提问作者Qiulang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 12:03:25