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

数据库在什么情况下会发生数据库死锁

1. 什么是死锁

死锁(Deadlock) 是指两个或多个事务在执行过程中,互相持有对方需要的锁,并且都在等待对方释放锁,从而导致它们都无法继续执行。

简单来说:

你等我释放锁,我等你释放锁,结果谁也不释放 → 永远卡住。


2. 死锁发生的必要条件

死锁通常满足以下四个条件(同时成立才会发生):

  1. 互斥条件:锁资源一次只能被一个事务占用。
  2. 请求与保持条件:事务已经持有锁,同时又请求新的锁。
  3. 不可剥夺条件:锁不能被强制释放,只能由持有它的事务主动释放。
  4. 循环等待条件:事务之间形成一个循环等待锁的关系。

3. MySQL InnoDB 中常见死锁场景

场景 1:不同事务锁定资源顺序不同

-- 事务A
BEGIN;
UPDATE table1 SET col = 1 WHERE id = 1;  -- 锁住 table1 的 id=1
UPDATE table2 SET col = 1 WHERE id = 2;  -- 等待 table2 的 id=2-- 事务B
BEGIN;
UPDATE table2 SET col = 1 WHERE id = 2;  -- 锁住 table2 的 id=2
UPDATE table1 SET col = 1 WHERE id = 1;  -- 等待 table1 的 id=1

场景 2:间隙锁(Gap Lock)导致死锁

REPEATABLE READ 隔离级别下,InnoDB 会使用 间隙锁 来防止幻读。
如果两个事务在范围查询时加了间隙锁,并且互相等待对方释放,就可能死锁。

-- 事务A
SELECT * FROM orders WHERE amount BETWEEN 100 AND 200 FOR UPDATE;-- 事务B
SELECT * FROM orders WHERE amount BETWEEN 150 AND 250 FOR UPDATE;

两个事务锁定的范围有重叠,可能导致互相等待。


场景 3:外键约束导致死锁

当更新或删除带有外键约束的表时,InnoDB 会对父表和子表加锁,如果两个事务操作顺序不同,也可能死锁。


场景 4:索引选择不当

如果查询条件没有用到索引,InnoDB 会锁住更多行(甚至全表锁),增加死锁概率。


4. MySQL 如何处理死锁

  • InnoDB 有死锁检测机制innodb_deadlock_detect 默认开启)。
  • 一旦检测到死锁,InnoDB 会回滚其中一个事务,让另一个事务继续执行。
  • 回滚的事务会收到错误:
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

5. 避免死锁的建议

  1. 统一加锁顺序:所有事务访问表和行的顺序保持一致。
  2. 减少锁持有时间:尽量缩短事务执行时间,及时提交。
  3. 合理使用索引:避免全表扫描加锁。
  4. 减少范围锁:能用精确匹配就不要用范围查询。
  5. 分解大事务:将大事务拆成多个小事务,降低锁冲突概率。

关键记忆

  • 死锁本质是循环等待锁资源
  • 常见原因:加锁顺序不一致间隙锁冲突外键锁冲突索引不当导致锁范围过大
  • InnoDB 会自动检测并回滚一个事务,但最好在设计时避免死锁。

MySQL 发生死锁后的处理方法,并给你一个实际案例,让你清楚怎么发现、分析和解决死锁问题

1. 死锁发生时 MySQL 的处理机制

  • InnoDB 存储引擎会自动检测死锁(innodb_deadlock_detect=ON 默认开启)。
  • 一旦检测到死锁,InnoDB 会主动回滚其中一个事务(通常是回滚代价最小的那个),让另一个事务继续执行。
  • 被回滚的事务会收到错误:

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

2. 死锁处理步骤

步骤 1:捕获死锁错误

应用层要捕获 ERROR 1213 错误,并重试事务

try {// 执行事务逻辑
} catch (SQLException e) {if (e.getErrorCode() == 1213) {// 死锁,重试事务}
}

步骤 2:分析死锁原因

MySQL 提供了命令查看最近一次死锁信息:

SHOW ENGINE INNODB STATUS\G

在输出中找到 LATEST DETECTED DEADLOCK 部分,可以看到:

  • 哪些事务参与了死锁
  • 每个事务持有的锁
  • 每个事务等待的锁
  • 最终哪个事务被回滚

步骤 3:优化 SQL / 事务逻辑

常见优化方法:

  1. 统一加锁顺序(避免循环等待)
  2. 减少锁范围(使用合适的索引,避免全表锁)
  3. 缩短事务时间(减少锁持有时间)
  4. 分解大事务(降低锁冲突概率)
  5. 避免不必要的范围锁(减少间隙锁的使用)

3. 死锁案例

表结构

CREATE TABLE account (id INT PRIMARY KEY,balance DECIMAL(10,2)
) ENGINE=InnoDB;INSERT INTO account VALUES (1, 1000), (2, 1000);

事务执行过程

-- 事务A
BEGIN;
UPDATE account SET balance = balance - 100 WHERE id = 1;  -- 锁住 id=1
UPDATE account SET balance = balance + 100 WHERE id = 2;  -- 等待 id=2-- 事务B
BEGIN;
UPDATE account SET balance = balance - 100 WHERE id = 2;  -- 锁住 id=2
UPDATE account SET balance = balance + 100 WHERE id = 1;  -- 等待 id=1

此时:

  • 事务A 持有 id=1 锁,等待 id=2
  • 事务B 持有 id=2 锁,等待 id=1
  • 循环等待 → 死锁

死锁检测结果

执行:

SHOW ENGINE INNODB STATUS\G

可能看到:

LATEST DETECTED DEADLOCK
------------------------
*** (1) TRANSACTION:
TRANSACTION 12345, ACTIVE 5 sec updating
...
*** (2) TRANSACTION:
TRANSACTION 12346, ACTIVE 5 sec updating
...
*** WE ROLL BACK TRANSACTION (2)

表示事务 12346 被回滚。


解决方法

  1. 统一加锁顺序
    • 所有事务先更新 id=1 再更新 id=2,避免循环等待。
  2. 应用层重试
    • 捕获 ERROR 1213,重新执行事务。

总结

  • 发生死锁时:InnoDB 会自动回滚一个事务 → 应用层要捕获错误并重试。
  • 分析死锁:用 SHOW ENGINE INNODB STATUS\G 查看死锁详情。
  • 避免死锁:统一加锁顺序、减少锁范围、缩短事务时间、分解大事务。
http://www.dtcms.com/a/528120.html

相关文章:

  • 如何将Word文档精确转换为图片型PDF?
  • Auto CAD二次开发——封装事务处理函数并绘制直线函数
  • C4D域力场重要概念之点对象、粒子对象和通道转换
  • 车载诊断架构 ---关于Service 29证书认证与整车时间同步的问题带来的深思
  • 做蛋糕需要建议网站不wordpress跳转移动端模板
  • html5培训网站模板兴国电商网站建设
  • 【JUnit实战3_13】第八章:mock 对象模拟技术在细粒度测试中的应用(上)
  • STM32项目分享:简易自动门设计
  • 小白怎样建设公司网站奔奔网站建设
  • YouTube评论情感分析项目84%正确率:基于BERT的实战复现与原理解析
  • 【Shell】Shell变量
  • 华为OD机考:计算正方形数量(Python C/C++ JAVA JS GO)
  • 基于 STM32 的语音识别智能垃圾桶设计与实现
  • 【基础复习3】决策树
  • 网站设计公司驻马店市住房和城乡建设局网站首页
  • Microsoft AI Genius | 用智能 Microsoft Copilot 副驾驶® 构建高韧性 DevOps 流程
  • wordpress网站布置电子商务网站建设的心得
  • nicegui 无框模式最小化关闭例子
  • 【气动技术】气动控制元件及其选型计算
  • LCL滤波器传递函数及波特图绘制
  • 银河麒麟v10 sp1更改data目录挂载
  • 在安卓中基于OpenGL ES实现随风飘荡3D动画效果
  • Java坐标转换技术详解
  • AWS Systems Manager:批量服务器管理的隐藏利器
  • 如何分析对手网站关键词网页版游戏平台
  • 招聘网站建设初衷远程数据库 wordpress
  • 驱动隔离芯片:电子系统的安全与效能守护者
  • 【经验】Word/WPS|用邮件合并批量填写表格或教案,单个Word导出成多个文件
  • Git工作流
  • 简单企业网站青岛天元建设集团网站