Skip to content
MySQL 事务、锁与高可用 · 第 2 篇 / 共 6 篇
领域数据与中间件
专题MySQL 专题
当前序列MySQL 事务、锁与高可用
阅读位置第 2 篇 / 共 6 篇当前专题第 2 个序列 / 共 7 个序列

MySQL 死锁怎么排查:为什么会互相等,怎么从 SQL 和事务顺序上减少死锁

死锁是数据库并发场景里非常经典的问题。

它不是“数据库坏了”,而是多个事务的资源获取顺序冲突后,系统只能主动回滚其中一方。

先说结论

遇到死锁时,最重要的不是只会:

  • 重试

而是要回头看三件事:

  • 事务是不是太大
  • 访问顺序是否不一致
  • 更新条件是否走到了合适索引

很多死锁最终都能回到这三层解释。

一、死锁到底是什么

可以先粗略理解成:

  • 事务 A 持有资源 1,等待资源 2
  • 事务 B 持有资源 2,等待资源 1

双方都过不去。

这时数据库为了打破僵局,会选一个事务回滚。

二、为什么 MySQL 里经常出现死锁

最常见原因通常包括:

  • 多事务更新同一批数据
  • 多表更新顺序不一致
  • 范围更新锁住了更大范围
  • 事务执行时间过长

三、为什么索引命中情况很关键

很多人会把死锁只理解成“并发太高”,但实际上:

  • 锁范围是不是过大

才是特别关键的问题。

如果更新没走到合适索引,就可能:

  • 扫更大范围
  • 锁更多记录

这会显著增加冲突概率。

四、排查死锁更实用的顺序

第一步:先看涉及哪些 SQL

确认到底是哪几类更新冲突最频繁。

第二步:看事务顺序是否一致

例如:

  • 某些代码先更新表 A 再更新表 B
  • 某些代码先更新表 B 再更新表 A

这就非常容易形成环路等待。

第三步:看事务是不是太大

事务里如果包含:

  • 多步更新
  • 外部调用
  • 过长业务处理

锁持有时间就会放大。

第四步:看索引和锁范围

确认:

  • 条件列是否命中索引
  • 是否是范围更新

五、怎么减少死锁

1. 缩短事务

事务越短,冲突窗口越小。

2. 固定访问顺序

多资源更新时,统一顺序非常重要。

3. 尽量走索引更新

锁范围更小,冲突概率更低。

4. 把非必要逻辑移出事务

例如:

  • RPC
  • 慢 IO
  • 非关键计算

六、为什么“完全避免死锁”不现实

在高并发系统里,死锁通常只能:

  • 尽量减少

很难承诺绝不发生。

所以更实际的做法是:

  • 设计上减少概率
  • 应用层对死锁错误做可控重试

一句话总结

MySQL 死锁不是偶发现象,而是并发更新模型的一种自然结果。

真正有效的治理方式,通常不是“看到死锁就重试”,而是回到事务长度、访问顺序和索引路径这三层去收敛风险。

延伸阅读相关文章优先当前专题,再补跨专题关联。
同一序列 · 顺着当前主线继续读MySQL 常见连接与包大小错误排查适合把事务锁、死锁、主从复制、写后读一致性和切换治理串起来看。MySQL 专题 · MySQL 事务、锁与高可用同一序列 · 顺着当前主线继续读MySQL 主从复制与读写分离适合把事务锁、死锁、主从复制、写后读一致性和切换治理串起来看。MySQL 专题 · MySQL 事务、锁与高可用同专题其他序列 · 共享标签:线上排障、案例排障MySQL 索引设计与慢 SQL 排查适合先把字段设计、索引、Explain、分页和慢 SQL 这条主线走顺。MySQL 专题 · MySQL 建模与查询优化同专题其他序列 · 共享标签:案例排障MySQL 慢 SQL 优化案例适合先把字段设计、索引、Explain、分页和慢 SQL 这条主线走顺。MySQL 专题 · MySQL 建模与查询优化跨专题关联 · 共享标签:并发、线上排障数据库死锁和锁等待超时案例怎么复盘适合把 K8s、RabbitMQ 和数据库锁等待问题放在一条故障治理主线上看。数据与基础设施排障专题 · 基础设施与中间件故障案例跨专题关联 · 共享标签:并发、线上排障线程池打满时怎么排查适合把 CPU、Full GC、线程池和接口超时这类应用层异常放在一组里看。应用运行时排障专题 · 应用运行时异常排查
继续阅读MySQL 事务、锁与高可用当前序列第 2 篇 / 共 6 篇当前专题第 2 个序列 / 共 7 个序列
往前看
上一篇MySQL 事务与锁回到当前序列上一章上一序列MySQL 建模与查询优化从第 1 篇开始:MySQL 字段类型怎么选
往后看
下一篇MySQL 常见连接与包大小错误排查继续当前序列下一章下一序列MySQL 存储引擎与执行细节从第 1 篇开始:MVCC 和 Read View 怎么理解

把零散经验整理成可查、可复用、可持续更新的企业级知识门户