别再被死锁坑了!3个最常见的死锁场景及一键避坑清单

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
PolarDB Agent Express,2核4GB
简介: 详解MySQL死锁:本质是事务循环等待资源,InnoDB自动回滚牺牲者。通过`SHOW ENGINE INNODB STATUS`定位锁链,结合索引优化、统一加锁顺序、降隔离级(RC)、加重试等手段可有效防控。死锁非故障,而是高并发下的必然现象。

大家好,这里还是小耶。

今天聊一个让我半夜爬起来好几次的话题:数据库死锁。

前阵子有个读者跟我描述了一个场景:某个电商大促期间,订单系统突然大面积报 Deadlock found,业务方快疯了。他赶紧执行了 SHOW ENGINE INNODB STATUS,看到 LATEST DETECTED DEADLOCK 下面一大段日志,每个字母都认识,串起来完全看不懂。CPU 一度飙到 70%,所有 update/insert 都在排队等锁释放。

死锁的可怕之处在于:系统内有 4 万毫秒的强制锁释放超时设置,这意味着单个锁的等待最多 40 秒。一旦上万个请求同时堆积,不仅是数据库,整个应用层在 40 秒内都会体验断崖式响应延迟。如果是核心交易系统,用户看到的就是白屏和“网络异常”。

死锁到底是什么?

先说明白这个问题。

死锁,是指两个或多个事务在执行过程中,因争夺同一资源而互相等待,结果谁也无法继续执行,形成一个循环等待的僵局。事务 A 拿着资源 1 在等资源 2,事务 B 拿着资源 2 在等资源 1,谁也等不到,最后只能被数据库内核强制中止其中一个。死锁通常发生在使用 InnoDB 行锁且并发较高的事务中。

要让死锁发生,必须同时满足四个条件:

  • 互斥​:资源不能被共享,一次只能被一个事务占用
  • 持有并等待​:事务已持有一部分资源,同时还在等待其他事务持有的资源
  • 非抢占​:资源不能被强行剥夺,必须由持有的事务主动释放
  • 循环等待​:事务之间形成了 A 等 B、B 等 A 的闭环

理论上打破其中任何一个,死锁就不会发生。但在高并发业务中,这四者几乎会同时出现。

InnoDB 在解决死锁时会做什么?

InnoDB 默认死锁检测是开启的。一旦检测到死锁,会自动回滚其中一个事务(通常选择执行成本较小或持有锁较少的事务来作为牺牲者),另一个事务继续执行。这就是为什么 Deadlock found 错误往往是偶发性的——有时候死锁触发了,其中一个事务被回滚,报错出现;有时候刚好绕过去了,业务不受影响。但如果业务本身对事务提交失败没有重试机制,每一次死锁都是一个定时炸弹。

SHOW ENGINE INNODB STATUS 完整解读

我第一次看到这个命令的输出,满屏的十六进制地址、锁结构体,完全看不懂。后来在线上一遍遍对日志、查文档,才慢慢啃下来。今天把精华拆给你看。

SHOW ENGINE INNODB STATUS 返回的内容很长,只会有一次最近的死锁记录(如果发生过多次,也只会保存最后一次),所以运维上建议开启 innodb_print_all_deadlocks = ON,把所有死锁日志记录进错误日志,方便长期追踪。

下面是一个典型死锁日志的核心结构拆解:

------------------------
LATEST DETECTED DEADLOCK
------------------------
2026-01-15 14:23:45 0x7f8a2c001700
*** (1) TRANSACTION:
TRANSACTION 310298, ACTIVE 0 sec fetching rows
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 12345, OS thread handle 14000, query id 67890 10.0.0.1 app_user updating
UPDATE orders SET status = 'PAID' WHERE order_id = 10086
*** (1) HOLDS THE LOCK(S):
RECORD LOCKS space id 100 page no 3 n bits 72 index PRIMARY of table `db`.`orders` 
trx id 310298 lock_mode X locks rec but not gap
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 100 page no 5 n bits 72 index idx_status of table `db`.`orders` 
trx id 310298 lock_mode X locks gap before rec insert intention waiting
*** (2) TRANSACTION:
TRANSACTION 310299, ACTIVE 0 sec fetching rows
...
*** (2) HOLDS THE LOCK(S):
...
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
...
*** WE ROLL BACK TRANSACTION (1)

逐行解读:

  • TRANSACTION ​行​:ACTIVE 0 sec 表示当前事务已经活跃 0 秒,说明死锁在短时间内就被检测到了。
  • mysql tables in use 1, locked 1​:事务用了几张表,锁了几张表。
  • LOCK WAIT​:当前事务正在等待锁。
  • HOLDS THE LOCK(S)​:关键部分。表示当前事务已经拿到了哪些锁。这里 lock_mode X 表示排他锁,locks rec but not gap 表示行锁(记录锁),没有锁住间隙。看到 gap before recinsert intention 时,需要警惕间隙锁——很多死锁都源于间隙锁与插入意向锁的冲突。尤其是在 MySQL 默认的 REPEATABLE READ 隔离级别下,间隙锁范围会被扩大,死锁概率大增。
  • WE ROLL BACK TRANSACTION (1)​:谁被选中作为牺牲者回滚了。可以据此调整事务顺序,让不关键的 SQL 成为被回滚的一方。

补充工具:Performance Schema

从 MySQL 8.0 开始,官方推荐使用 Performance Schema 来更精细地监控锁竞争:

-- 查看当前所有锁信息
SELECT * FROM performance_schema.data_locks;

-- 查看当前锁等待关系
SELECT * FROM performance_schema.data_lock_waits;

-- 结合当前事务状态一起分析
SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id 
FROM information_schema.INNODB_TRX 
WHERE trx_state = 'LOCK WAIT';

这些视图能看到死锁发生前实际的阻塞链条,比 SHOW ENGINE INNODB STATUS 的被动后置分析更主动。

常见死锁场景与解决方案

1. 多表访问顺序不一致(最常见)
事务 A:UPDATE t1 → UPDATE t2;事务 B:UPDATE t2 → UPDATE t1。解法:统一规定业务代码中的访问顺序,按表名或主键 ID 升序访问。

2. 批量更新时的死锁
SQL 执行计划异常导致全表扫描,一次性锁了大量行。解法:在 WHERE 条件上建立合适的索引,缩小扫描范围。

3. 并发插入时的间隙锁冲突
RR 隔离级别下,InnoDB 会锁住间隙防止幻读,多个事务同时插入时可能互相等待。解法:考虑降级为 READ COMMITTED 隔离级别(RC 模式无间隙锁),同时 binlog 格式设置为 ROW。

4. 外键约束引发的死锁
更新主表时不仅要锁本表,还要检查关联子表,高并发下容易死锁。

一点个人体会

我是运营转行做的 DBA。早期处理故障时,总习惯先看监控大盘、重启应用、发公告——这是运营的“止血思维”。后来被线上问题教育了几次才明白,DBA 得反过来:先看锁日志、定位具体 SQL、再决定怎么处理。盲目重启只是掩盖问题,过不了多久还会再崩。这个思维转换,比学会任何一条命令都重要。

死锁预防的最佳实践清单

  1. 统一加锁顺序​:所有事务严格按相同顺序访问表和行。
  2. 拆分长事务​:事务越短越好,避免在事务中调用外部 API 或做耗时操作。
  3. 建好索引​:让 WHERE 条件筛选尽可能少的行,降低锁冲突范围。
  4. 考虑降隔离级别​:业务允许时使用 READ COMMITTED,消除间隙锁导致的死锁。
  5. 添加重试机制​:应用层捕获 Deadlock found 后重试,往往能绕过瞬时的锁竞争。

总结

死锁排查的核心方法:先用 SHOW ENGINE INNODB STATUS 确认死锁及涉及 SQL,然后分析锁等待链,找出形成循环的两个事务,接着排查索引是否生效、是否存在全表扫描,最后从代码层面统一访问顺序、拆分长事务、完善重试。

死锁不是玄学,它是数据库并发控制的必然产物。理解它、排查它,是 DBA 和普通开发的分水岭。

小耶在手,SQL 不愁

还有什么想了解的,欢迎留言!小耶一定知无不言言无不尽……我们下次见~

相关文章
|
2天前
|
人工智能 弹性计算 安全
阿里云38元、9.9元与199元轻量应用服务器,99元与199元云服务器购买入口及相关规则解析
2026年阿里云推出的几款特惠云服务器主要涉及四款产品:轻量应用服务器2核2G(38元/年,限时抢购)、2核4G(9.9元/月或199元/年),以及ECS云服务器2核2G(99元/年)和2核4G(199元/年)。本文为大家介绍了各产品的配置参数、抢购资格与时间、购买入口、续费政策及适用场景,并提供了对比和选购策略建议:新用户追求极致性价比可抢购轻量服务器,注重长期稳定则推荐ECS"99计划"(新购续费同价至2027年),企业用户适合199元独享型实例。同时涵盖OpenClaw等AI镜像快速部署方案。
191 21
|
17天前
|
SQL 关系型数据库 MySQL
一张5000万行的表,加索引从45秒到0.02秒——索引设计你真的会吗
本文实测5000万订单表:无索引查询45秒,加索引后仅0.02秒(提升2250倍)。详解索引原理、建索引时机、联合索引最左前缀、覆盖索引及隐式转换陷阱,干货不啰嗦!
|
2天前
|
人工智能 缓存 安全
【AI 尝鲜实验室】5.22 号上新 | DeepSeek-TUI:终端里 DeepSeek 版的 Claude Code
DeepSeek-TUI是专为DeepSeek V4大模型打造的终端AI编程助手,支持100万Token超长上下文、实时推理可视化、文件/Shell/Git/网页等全栈操作,提供Plan/Agent/YOLO三种安全模式,无需图形界面,开箱即用。(239字)
|
3天前
|
并行计算 API 开发者
万字详解:普通开发者如何用Ollama、llama.cpp把大模型无缝跑在本地消费级显卡上?
本文详解普通开发者如何用Ollama与llama.cpp,将7B–14B大模型高效部署于本地消费级显卡(如RTX 4060 8GB)。涵盖显存评估、量化原理(Q4_K_M等)、一键运行与精细调优、避坑指南及跨平台(CUDA/ROCm/Metal)实测数据,助你零成本、高隐私、离线可用。
|
2天前
|
人工智能 API 开发者
NVIDIA 免费 API 从申请到 Claude Code 接入全攻略:CLIProxyAPI 与 CCR 代理实战
JeecgBoot AI专题研究 NVIDIA 免费 API 申请与 Claude Code 第三方模型接入实战指南 前言Claude Code 已经成了很多开发者日常编程的首选工具,但它的付费门槛让不少人望而却步——尤其是以人民币结算的用户,每月开支不算小。好消息是,NVIDIA 提供了免费
143 0
NVIDIA 免费 API 从申请到 Claude Code 接入全攻略:CLIProxyAPI 与 CCR 代理实战
|
24天前
|
SQL JSON 关系型数据库
慢SQL排查三板斧:SHOW PROCESSLIST + 慢查询日志 + EXPLAIN 实战
教你三招快速定位CPU 100%元凶:SHOW PROCESSLIST查活跃查询、开启慢日志+mysqldumpslow分析、EXPLAIN深度诊断SQL性能。干货不啰嗦,专治线上急症!
|
12天前
|
SQL 运维 关系型数据库
DBA必备技能:MySQL误删恢复完全指南(全量备份+binlog回放)
本文详解误删数据(如`DELETE FROM orders`)后的紧急恢复三步法:查Binlog→临时库回放→差异导回,并附4条血泪预防措施。不讲段子,只教能救命的操作!
|
1月前
|
SQL 数据库
多表关联查询入门:LEFT JOIN、INNER JOIN一文搞懂|转行学DB第6天
本文通俗易懂地讲解了数据库多表查询的三种JOIN操作:INNER JOIN(内连接)只返回两表匹配的数据,适用于查询交集数据;LEFT JOIN(左连接)保留左表所有记录并匹配右表数据,适用于查询主表完整信息;RIGHT JOIN(右连接)则保留右表所有记录。
|
1月前
|
SQL 关系型数据库 MySQL
主键、外键和约束:让数据库“有规矩”才能不出错!|转行学DB第5天
本文用通俗易懂的语言讲解了主键(数据的唯一标识)、外键(表间关联)以及唯一约束、非空约束等其他常见约束规则。通过具体SQL示例展示了各种约束的使用方法,并分享了新手容易踩的坑和实用建议。
|
1月前
|
SQL 人工智能 安全
AI圈开始“养马”了?聊聊龙虾退位、爱马仕登基
AI智能体“龙虾”(OpenClaw)的衰落与“爱马仕”(Hermes Agent)的崛起:前者因API限策与高危漏洞(CVSS 9.9)式微;后者以持久记忆、技能自生成、跨平台互通等实用能力破圈,成技术圈新“拐杖”。但技术无银弹,懂你的工具才是真助力。