当前位置: 首页 > news >正文

死锁的本质:形成条件、检测机制与排查策略

文章目录

    • 《死锁的本质:形成条件、检测机制与排查策略》
      • 一、前言:什么是死锁
      • 二、死锁的形成条件
      • 三、死锁示例:经典案例
        • 示例一:互相更新不同记录
        • 示例二:范围更新导致间隙锁死锁
      • 四、InnoDB 死锁检测机制
      • 五、死锁日志分析
      • 六、避免死锁的最佳实践
        • ① 保持统一的加锁顺序
        • ② 减少锁定范围
        • ③ 控制事务粒度与时长
        • ④ 合理选择事务隔离级别
        • ⑤ 加锁顺序与索引命中调试
      • 七、面试高频问题与答题模板
      • 八、总结


《死锁的本质:形成条件、检测机制与排查策略》


一、前言:什么是死锁

大家好,我是程序员卷卷狗。

在数据库并发控制中,锁是保护一致性的必要手段。
但当多个事务互相等待对方释放锁时,
就会进入一种永远无法继续执行的状态——这就是死锁(Deadlock)。

一句话概括:

死锁是“事务之间的相互等待”,没有任何一方能先释放资源。


二、死锁的形成条件

系统要发生死锁,必须同时满足以下四个条件

条件含义示例
① 互斥条件资源一次只能被一个事务占用行锁、排他锁
② 占有且等待持有部分锁的同时申请新锁事务 A 锁 id=1,再锁 id=2
③ 不可剥夺已获得的锁不能被强制释放InnoDB 不会强行回滚其他事务
④ 循环等待两个事务形成等待环A 等 B,B 等 A

只要破坏其中任意一个条件,就能避免死锁。
但数据库通常满足前三个条件,因此循环等待是死锁的根本原因。


三、死锁示例:经典案例

示例一:互相更新不同记录
-- 事务A
BEGIN;
UPDATE user SET age=age+1 WHERE id=1;-- 事务B
BEGIN;
UPDATE user SET age=age+1 WHERE id=2;-- 事务A 再次请求 id=2
UPDATE user SET age=age+1 WHERE id=2;-- 事务B 再次请求 id=1
UPDATE user SET age=age+1 WHERE id=1;

执行顺序如下

A 锁住 id=1
B 锁住 id=2
A 等待 B 释放 id=2
B 等待 A 释放 id=1
→ 死锁形成

InnoDB 检测到循环等待后,会回滚其中一个事务:

ERROR 1213 (40001): Deadlock found when trying to get lock

示例二:范围更新导致间隙锁死锁
-- 事务A
SELECT * FROM user WHERE age BETWEEN 10 AND 20 FOR UPDATE;-- 事务B
SELECT * FROM user WHERE age BETWEEN 15 AND 25 FOR UPDATE;

锁范围重叠 (15~20),
→ A、B 分别锁定一部分区间,彼此等待对方释放 → 死锁。


四、InnoDB 死锁检测机制

InnoDB 内部维护一张 等待图(Wait-for Graph)

  • 每个事务是一个节点;
  • 每个锁等待是一个有向边。

当出现环路时,即检测到死锁。

算法流程:

1. 事务 T1 等待 T2 → 建立边 T1 → T2
2. 事务 T2 等待 T3 → 建立边 T2 → T3
3. 若出现 T3 → T1,形成环路 → 死锁!
4. InnoDB 自动回滚代价最小的事务。

检测频率:实时检测(每次锁等待)
代价评估标准:

  • 锁数量最少;
  • 修改行数最少;
  • 事务时间最短。

五、死锁日志分析

查看命令:

SHOW ENGINE INNODB STATUS\G

输出示例:

LATEST DETECTED DEADLOCK
------------------------
*** (1) TRANSACTION:
TRANSACTION 145, ACTIVE 3 sec
UPDATE user SET age=30 WHERE id=1;*** (2) TRANSACTION:
TRANSACTION 146, ACTIVE 3 sec
UPDATE user SET age=30 WHERE id=2;*** WE ROLL BACK TRANSACTION (2)

分析要点:

  • 哪个事务先加锁;
  • 哪个事务被回滚;
  • 涉及的表、索引、SQL。

六、避免死锁的最佳实践

① 保持统一的加锁顺序

所有事务按相同的字段顺序访问资源。

-- 一致加锁顺序
UPDATE user SET age=age+1 WHERE id IN (1,2);
② 减少锁定范围

尽量使用主键或唯一索引精确定位行。

-- 好:单行锁
SELECT * FROM user WHERE id=1 FOR UPDATE;
-- 坏:范围锁,死锁概率大
SELECT * FROM user WHERE age>10 FOR UPDATE;
③ 控制事务粒度与时长
  • 拆小事务;
  • 尽快提交;
  • 避免长时间持锁操作(如网络等待、用户交互)。
④ 合理选择事务隔离级别
  • 在允许的场景下使用 READ COMMITTED;
  • 可减少间隙锁带来的死锁几率。
⑤ 加锁顺序与索引命中调试
  • 检查执行计划(EXPLAIN);
  • 确保条件使用索引,否则会退化为表锁。

七、面试高频问题与答题模板

问题答案要点
Q1:死锁的四个形成条件?互斥、占有且等待、不可剥夺、循环等待。
Q2:InnoDB 如何检测死锁?构建等待图,检测环路。
Q3:发现死锁后 MySQL 怎么处理?自动回滚代价最小的事务。
Q4:死锁常见场景?不同事务交叉更新、范围锁重叠。
Q5:如何避免死锁?统一加锁顺序、减小事务范围、索引命中、缩短事务时长。
Q6:如何排查死锁?使用 SHOW ENGINE INNODB STATUS\G 查看日志。

八、总结

死锁的本质是循环等待资源
它不是“异常错误”,而是并发控制中的自然现象。
真正重要的是——

设计出能快速检测、自动回滚、尽量规避的事务逻辑。

一句话记住:

锁太多不一定死,但乱锁一定死。

下一篇(第 15 篇),我将写——
《Explain 执行计划详解:SQL 性能瓶颈与索引命中分析》
讲清楚执行计划每一列(type、key、rows、Extra)的意义,
并教你如何用 Explain 定位慢查询瓶颈。

http://www.dtcms.com/a/601329.html

相关文章:

  • Winform控件:RichTextBox
  • 大疆影石掰手腕,智能影像“跨界”内卷
  • 建设一个网站平台一款app的开发成本
  • 吴江城乡和住房建设局网站商务网站建设 模板
  • sparksql远程服务thriftserver.sh启停脚本
  • 非模板匹配目标识别算法
  • NLP基础(一)_简介
  • Spring AI Alibaba 学习之最简单的快速入门
  • 网站的总体结构网站代理软件
  • 设计循环队列 | C语言实现
  • 可以做淘宝推广的网站有哪些内容微信公众平台可以导入wordpress
  • 5.1 路由选择算法
  • 十八、文本预处理与基础技术
  • 巨 椰 云手机突破物理限制
  • java基础-继承练习
  • 寻花问柳一家专门做男人的网站1534939978姐的微信德惠市
  • 做网站的毕业设计博客网站制作
  • Java应用中,CPU 使用率过高​问题排查(手动用top+jstack或阿里Arthas)
  • k8s的包管理工具(5)--读取文件内容
  • AXI-5.4 Protocol errors
  • 动易网站后台帮人做彩票网站有事吗
  • 购物网站php模板周口市网站建设
  • 装饰公司网站模板下载建设网站的内容及实现方式
  • Kubernetes 学习笔记
  • 【自然语言处理】基于统计基的句子边界检测算法
  • 数据智能开发三 数据架构设计
  • 数据治理进阶——解读数据平台数据治理与建设方案【附全文阅读】
  • 基于OpenAI与DashScope的AI知识面试模拟系统实现
  • 嘉兴市南湖区城乡规划建设局网站做年报的网站怎么登不上去了
  • IntelliJ IDEA 2025.2.4 安装 MybatisX 不生效问题记录