当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL 死锁排查工作流:从 InnoDB 状态到事务顺序优化

MySQL 死锁排查工作流:从 InnoDB 状态到事务顺序优化

来源:17golang原创 2026-06-17 16:43:15 0浏览 收藏

MySQL 死锁不是“数据库坏了”,而是两个或多个事务互相等待对方持有的锁,最后 InnoDB 主动回滚其中一个事务。线上看到的现象通常是接口偶发失败、日志里出现 deadlock、用户刷新后又好了。

这类问题最怕只盯着报错重试,而不去看事务访问顺序。本文按完整工作流梳理:从应用报错到 InnoDB 状态,从锁等待环到事务顺序优化,最后加上有限重试和上线检查点。

目录
  • 目标和边界
  • 全流程总览
  • 阶段一:抓到死锁现场
  • 阶段二:还原锁等待环
  • 阶段三:统一事务顺序和缩短锁持有时间
  • 阶段四:业务侧加有限重试保护
  • 我的推荐流程
  • 容易踩坑
  • 落地速查表

目标和边界

本文讨论的是 InnoDB 行锁场景下的典型死锁排查,不展开 MySQL 内核实现,也不把主题扩展成全量性能优化。读完后,你应该能完成三件事:

  1. 知道从哪里拿到最近一次死锁信息。
  2. 能根据事务、SQL、锁等待关系还原死锁链路。
  3. 能用统一加锁顺序、短事务和有限重试降低线上影响。

先说结论:死锁不是完全可以消灭的异常,尤其在高并发更新场景里,业务侧必须有重试保护。但重试不能替代治理,真正要修的是事务访问顺序、锁范围和锁持有时间。

全流程总览

一个实用的 MySQL 死锁排查流程可以拆成五步:应用报错、查看 InnoDB 状态、识别锁等待环、调整事务顺序、加重试保护。每一步都有明确产物,不能只停留在“日志里有 deadlock”。

MySQL 死锁排查从应用报错到重试保护的流程图

阶段 目标 关键动作 检查点
抓现场 确认是不是 InnoDB 死锁 记录错误码、接口、请求参数和事务入口 能关联到具体业务操作
看状态 读取最近一次死锁详情 使用 SHOW ENGINE INNODB STATUS 能看到两个事务和等待的锁
还原链路 找出循环等待关系 对比 SQL、索引、where 条件、加锁顺序 能画出谁等谁
修事务 减少再次死锁概率 统一访问顺序,减少事务内慢操作 高并发压测死锁次数下降
做保护 降低偶发死锁对用户的影响 有限重试、幂等校验、失败告警 重试次数可观测,失败可回溯

阶段一:抓到死锁现场

目标

先确认问题是不是死锁,而不是普通锁等待超时、连接池耗尽或接口超时。死锁通常会伴随 “Deadlock found when trying to get lock” 这类信息,被选中的事务会回滚。

关键动作

应用层日志至少记录四类信息:业务动作、请求 ID、SQL 所在方法、事务开始和结束位置。没有这些上下文,即使拿到了数据库死锁信息,也很难映射回代码。

request_id=pay-20260617-001
action=pay_order
db_error=Deadlock found when trying to get lock
tx_entry=PayService.payOrder
order_id=10086
sku_id=SKU-9

数据库侧先查看最近一次死锁详情:

SHOW ENGINE INNODB STATUS\G

如果线上死锁比较频繁,排查窗口内可以临时打开全部死锁记录,让信息进入 MySQL 错误日志。排查完成后要按团队规范评估是否关闭,避免日志过多影响观察。

SET GLOBAL innodb_print_all_deadlocks = ON;

常用工具/代码选择

小团队可以先用应用日志加 `SHOW ENGINE INNODB STATUS`;复杂系统建议把请求 ID、事务入口、SQL 模板和数据库错误码打到统一日志里,方便按时间线检索。

检查点

你应该能回答:哪一个接口触发了死锁、哪两个 SQL 参与了冲突、哪个事务被回滚、发生时间是否和业务峰值重合。

阶段二:还原锁等待环

目标

死锁排查的核心不是记住某条 SQL,而是还原循环等待:事务 A 拿着什么锁、还想要什么锁;事务 B 拿着什么锁、又在等什么锁。

关键动作

从 InnoDB 状态中摘出两个事务的 SQL、等待的索引、记录锁类型和回滚结果。然后回到业务代码,看这些 SQL 是不是在同一个事务里按不同顺序访问了相同资源。

事务 A:
1. 更新订单表 order_id=10086
2. 继续更新库存表 sku_id=SKU-9

事务 B:
1. 更新库存表 sku_id=SKU-9
2. 继续更新订单表 order_id=10086

结果:
A 等库存表,B 等订单表,形成循环等待。

还要检查索引是否命中。如果 where 条件没有走到合适索引,锁范围会扩大,原本只想改一行,结果锁住更多记录或间隙,死锁概率会被放大。

常用工具/代码选择

可以结合 `EXPLAIN` 看访问路径,用业务日志确认事务顺序,用压测脚本复现高并发场景。不要只在本地单线程点几次接口,那通常复现不出真实锁冲突。

检查点

排查到这一步,应该能画出一张等待关系图:事务 A 持有订单锁并等待库存锁,事务 B 持有库存锁并等待订单锁。画不出来,就说明证据还不够。

阶段三:统一事务顺序和缩短锁持有时间

修死锁时,最常见也最有效的思路是统一资源访问顺序。只要所有路径都按同一种顺序加锁,就能减少“你等我、我等你”的循环等待。

MySQL 反向加锁形成循环等待以及固定顺序短事务提交的对比图

目标

让所有涉及相同资源的事务按统一顺序访问,并尽量缩短锁被持有的时间。

关键动作

假设支付成功后要改订单和扣库存,团队可以约定所有事务都先锁订单,再锁库存。另一条补偿、取消、库存回写链路也要遵守同一顺序。

-- 推荐:所有入口都按相同顺序访问资源
START TRANSACTION;

SELECT id FROM orders
WHERE id = 10086
FOR UPDATE;

SELECT sku_id FROM stock
WHERE sku_id = 'SKU-9'
FOR UPDATE;

UPDATE orders
SET status = 'paid'
WHERE id = 10086;

UPDATE stock
SET quantity = quantity - 1
WHERE sku_id = 'SKU-9' AND quantity > 0;

COMMIT;

同时把事务里的非数据库动作移出去,例如远程接口调用、文件处理、复杂计算、消息发送。事务内只保留必须一起提交的数据库读写,锁持有时间越短,冲突窗口越小。

常用工具/代码选择

可以在服务层封装事务模板,把资源访问顺序写成团队约定;对核心表建立访问规范,例如订单相关事务先订单后明细,库存相关事务先库存主表后流水表。

检查点

检查所有入口:正向下单、取消订单、退款回滚、定时补偿、后台人工修复,是否都遵守同一加锁顺序。只改一个接口,另一个入口仍然反向访问,死锁还会回来。

阶段四:业务侧加有限重试保护

目标

即使事务顺序已经优化,高并发下仍可能出现偶发死锁。业务侧要把死锁当成可重试异常处理,但重试必须有限、幂等、可观测。

关键动作

只对明确的死锁错误做有限重试,例如最多 2 到 3 次,每次短暂退避。重试前确认业务动作具备幂等保护,例如订单支付不能重复扣款,库存扣减不能重复生成流水。

def run_with_deadlock_retry(action, max_retry=3):
    for i in range(max_retry):
        try:
            return action()
        except DeadlockError:
            if i == max_retry - 1:
                raise
            sleep_ms(50 * (i + 1))

如果重试成功,要记录一次可观测事件;如果最终失败,要把请求 ID、订单号、事务入口和重试次数打到告警里,方便后续复盘。

常用工具/代码选择

Java、Go、Python 都可以在数据访问层或应用服务层封装重试。关键不是语言,而是不要把所有数据库错误都重试,也不要无限重试。

检查点

上线后观察两条曲线:死锁次数是否下降,重试后成功率是否稳定。如果死锁次数不降反升,说明事务顺序或锁范围还没有治理到位。

我的推荐流程

真正处理线上死锁时,我建议按下面顺序来:

  1. 先记录应用错误码、请求 ID、业务参数和事务入口。
  2. 立刻查看 `SHOW ENGINE INNODB STATUS`,保存最近一次死锁文本。
  3. 把两个事务的 SQL 摘出来,标记它们持有什么锁、等待什么锁。
  4. 回到业务代码,查所有会访问这些表的入口,不只看报错接口。
  5. 统一资源访问顺序,补齐必要索引,移出事务内慢动作。
  6. 加有限重试和幂等保护,并把重试次数纳入监控。
  7. 用并发压测复现旧路径,再验证新路径死锁次数是否下降。

容易踩坑

坑点 表现 修法
只加重试 接口表面恢复,数据库死锁仍然很多 继续排查事务顺序和锁范围
只看一条 SQL 误以为某个 UPDATE 本身有问题 把两个事务的完整顺序都还原出来
索引缺失 where 条件锁到更多记录 补齐高选择性索引,并用访问计划确认
事务里做慢动作 锁持有时间变长,高峰期更容易冲突 把远程调用、消息发送、复杂计算移到事务外
补偿链路被忽略 主流程修好了,定时任务仍然反向加锁 统一梳理所有入口的资源访问顺序

落地速查表

检查项 最低要求 上线前确认
应用日志 记录请求 ID、业务参数、事务入口和数据库错误 能从日志定位到代码路径
死锁文本 保存 InnoDB 最近一次死锁详情 能识别两个事务和等待关系
索引检查 核心 where 条件命中合适索引 不会意外扩大锁范围
事务顺序 所有入口按同一资源顺序加锁 补偿、后台、定时任务也已检查
事务时长 事务内不放远程调用和慢逻辑 锁持有时间可被压测观察
重试保护 仅对死锁做有限重试,并保证幂等 重试成功率和最终失败都有监控

总结一下,MySQL 死锁排查要从“报错”走向“等待关系”,再从“等待关系”回到“事务设计”。把现场、锁环、顺序、索引、短事务和有限重试串起来,死锁就不再是只能碰运气的线上问题。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
AI Agent 工具调用失败排查:从 Schema 到超时兜底的完整工作流AI Agent 工具调用失败排查:从 Schema 到超时兜底的完整工作流
上一篇
AI Agent 工具调用失败排查:从 Schema 到超时兜底的完整工作流
Go map 并发读写为什么会崩:从 fatal error 到三种安全改法
下一篇
Go map 并发读写为什么会崩:从 fatal error 到三种安全改法
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ljg-skills -
    ljg-skills
    ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
    393次使用
  • MELO音乐 - AI 音乐生成平台,支持多模态创作能力
    MELO音乐
    MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
    403次使用
  • UniScribe - AI 免费在线音视频转文字平台
    UniScribe
    UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
    372次使用
  • 剧云 - 免费 AI 智能中文剧本创作平台
    剧云
    剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
    546次使用
  • 万象有声 - AI 一站式有声内容创作平台
    万象有声
    万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
    530次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码