首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MySQL 死锁排查与根治:从日志分析到设计预防

MySQL 死锁排查与根治:从日志分析到设计预防

原创
作者头像
PikeTalk
发布于 2026-10-17 07:37:52
发布于 2026-10-17 07:37:52
170
举报

死锁不可怕,可怕的是不知道它发生了

MySQL InnoDB 会自动检测并回滚死锁中代价较小的事务,业务层只看到一个「Deadlock found」报错——多数团队的错误日志里死锁报错常年存在却无人处理,直到某天大促时死锁风暴拖垮下单链路。死锁治理的第一步是把它当作常驻指标监控,而不是偶发噪音。一、先看清现场:三份材料

  1. SHOW ENGINE INNODB STATUS:LATEST DETECTED DEADLOCK 段落展示最近一次死锁双方持有与等待的锁资源——注意它只保留最后一次,且输出被截断时开启 innodb_print_all_deadlocks=ON 把所有死锁打进错误日志;
  2. information_schema.INNODB_TRX / performance_schema.data_locks(8.0):死锁发生瞬间查当前事务与锁等待关系(事后查不到,需配合监控触发抓取);
  3. 业务 SQL 日志:死锁日志只有 SQL 片段,要还原完整事务需要应用侧的 SQL 审计日志对照。

二、四大常见死锁模式与根治

  1. 不同顺序更新同一组行:事务 A 先更新订单再更新库存,事务 B 相反——根治:全局约定加锁顺序(按 ID 排序后再逐行更新),代码评审把它列为检查项;
  2. 间隙锁冲突(RR 隔离级别):范围 UPDATE/DELETE 对不存在的行也加间隙锁,两个事务插入相邻区间互卡——根治:改 RC 隔离级别(多数互联网业务的标准选择),或把「先查再插」改为「直接插入 + 唯一约束兜底」;
  3. 唯一键冲突与死锁叠加:并发 INSERT 同一唯一键,一个事务持 S 锁等待升级——根治:插入前用 Redis 去重,或改用 INSERT IGNORE / ON DUPLICATE KEY 语义化处理;
  4. 外键与级联的隐藏锁:外键约束会在父表行上加共享锁,容易与更新事务互卡——根治:互联网业务普遍去掉外键约束,把一致性检查放到应用层。

三、预防性设计清单

  1. 事务要短:长事务是死锁温床,把跨 RPC 调用挪出事务体(先 RPC 后落库,或用本地消息表异步化);
  2. 批量操作分批 + 排序:批量 UPDATE 按 ID 排序分批,每批控制在百行级;
  3. 索引要准:走错索引会锁住更多行,锁范围与扫描范围成正比;
  4. 重试兜底:应用层对死锁报错(ER_LOCK_DEADLOCK)做自动重试(2~3 次退避),因为回滚的那个事务本身没做错任何事——重试是死锁治理的最后防线。

四、验收

治理后用两组指标确认效果:错误日志中死锁频率(目标:趋近于零)、死锁重试成功率(目标:100%——重试后应成功)。死锁无法绝对避免,但「可监控、有根因、能重试」的死锁是可控的死锁。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 死锁不可怕,可怕的是不知道它发生了
  • 二、四大常见死锁模式与根治
  • 三、预防性设计清单
  • 四、验收
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档