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

MySQL 死锁 怎么处理?

一、什么是死锁(Deadlock)

定义:

死锁是指两个或多个事务在执行过程中,互相占用资源且等待对方释放,导致事务都无法继续执行的状态。

简单例子:

事务A事务B
UPDATE t1 SET ... WHERE id=1; UPDATE t1 SET ... WHERE id=2;
(锁住 id=1) (锁住 id=2)
UPDATE t1 SET ... WHERE id=2; ← 被事务B锁住 UPDATE t1 SET ... WHERE id=1; ← 被事务A锁住

🔒 这样双方互相等待,InnoDB 检测到死锁后,会自动回滚其中一个事务(通常是锁占用资源少的),释放资源。


二、InnoDB 死锁原理

InnoDB 是 行级锁 + MVCC 的引擎,会使用不同类型的锁:

锁类型说明
共享锁 (S Lock) 允许读取,不允许写入
排他锁 (X Lock) 允许修改,不允许其他事务读/写
意向锁 (IS/IX Lock) 用于协调表锁和行锁
间隙锁 (Gap Lock) 用于防止幻读(在可重复读隔离级别下)

死锁的本质是:

事务之间的锁依赖图中形成了环。


三、死锁检测与分析

1️⃣ 自动检测

MySQL 会自动检测死锁并回滚其中一个事务,返回错误:

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

2️⃣ 查看死锁日志

执行:

 
SHOW ENGINE INNODB STATUS\G

在输出中查找:

 
LATEST DETECTED DEADLOCK ------------------------ *** (1) TRANSACTION: TRANSACTION 12345, ACTIVE 0 sec starting index read ... *** (2) TRANSACTION: TRANSACTION 12346, ACTIVE 0 sec starting index read ... *** WE ROLL BACK TRANSACTION (1)

你能看到:

  • 哪两个事务冲突;

  • 哪个 SQL 语句导致死锁;

  • 哪个事务被回滚。

👉 生产场景下,死锁分析一般就是从这个日志开始。


四、常见死锁场景

场景说明
1. 更新相同表的不同记录 事务A更新id=1再更新id=2,事务B反过来更新id=2再更新id=1。顺序不一致引发死锁。
2. 唯一索引冲突 + 插入 两个事务插入相同唯一键的记录,InnoDB 会隐式加锁。
3. 间隙锁冲突 可重复读隔离级别下,范围查询 + 插入导致 gap lock 竞争。
4. 外键约束 更新/删除父表、子表数据顺序不一致时,会触发隐式锁定。
5. 大事务 / 批量更新 一个事务锁住大量行,另一个事务锁少量行,可能产生循环等待。

五、死锁的危害

  • ❌ 部分事务会被强制回滚(数据未提交)。

  • ⚠️ 系统性能下降(大量事务等待 / 回滚重试)。

  • 🧨 高频死锁会导致应用报错、事务重试压力增大。

  • 🪣 如果应用层没有正确处理异常(例如直接吞掉异常),可能出现业务逻辑不一致


六、死锁的优化与避免策略

✅ 1. 保证加锁顺序一致

所有业务中操作相同表时,应固定访问顺序。

 
-- ❌ 不同事务顺序不一致 -- A: update t set ... where id=1; update t set ... where id=2; -- B: update t set ... where id=2; update t set ... where id=1; -- ✅ 改为统一顺序 id 从小到大

✅ 2. 尽量缩短事务执行时间

  • 事务只包含必要的 SQL;

  • 不要在事务中长时间等待外部资源(RPC、IO);

  • 提交要及时。

✅ 3. 为查询条件加合适索引

防止锁范围扩大(否则会锁整表或大量记录)。

✅ 4. 减少范围锁(Gap Lock)

  • 使用 READ COMMITTED 隔离级别(可减少间隙锁);

  • 或尽量使用主键/唯一索引精确查询。

✅ 5. 拆分大事务

批量更新、删除操作可以拆分为小批量提交。

✅ 6. 避免并发更新相同行

可以加版本号、状态字段等乐观锁机制(应用层控制)。

✅ 7. 捕获并重试

对死锁异常进行捕获与重试(常用于幂等事务逻辑):

 
int retry = 3; while (retry-- > 0) { try { // 执行事务逻辑 break; } catch (DeadlockLoserDataAccessException e) { if (retry == 0) throw e; } }

七、面试总结答案(标准化表达)

面试答法:

MySQL 死锁是多个事务之间互相持有并等待对方锁资源而无法继续执行的现象。
InnoDB 会自动检测死锁并回滚其中一个事务。
常见死锁场景包括不同顺序更新同一表、间隙锁冲突、外键约束等。
处理上我们可以通过:

  • 保证加锁顺序一致;

  • 缩短事务时间;

  • 为条件加索引;

  • 使用合适隔离级别(READ COMMITTED);

  • 拆分大事务;

  • 捕获异常并重试;

  • 通过 SHOW ENGINE INNODB STATUS 分析死锁日志。

死锁会导致事务回滚和性能下降,需要重点在设计阶段优化。


八、可执行的排查流程(生产建议)

 
# 查看死锁日志 SHOW ENGINE INNODB STATUS\G# 查看事务等待情况 SELECT * FROM information_schema.innodb_trx\G# 查看锁等待关系 SELECT * FROM performance_schema.data_locks; SELECT * FROM performance_schema.data_lock_waits;
http://www.hskmm.com/?act=detail&tid=35904

相关文章:

  • MyBatis 的 @SelectProvider 是一个强大的注解,用于动态生成 SQL 语句
  • 跨境客服系统如何保障国际数据传输安全?
  • 物联网短信收发速成:10分钟用SMS库上手实战
  • 2025年耳机插座厂家权威推荐榜:DC防水耳机插座,专业防水防尘设计,耐用稳定性能卓越之选
  • 2025年10月18日,工信部人才交流中心PostgreSQL认证考试完成!
  • 2025年CNC加工厂家权威推荐榜:CNC精密加工/加工中心CNC/cnc电脑锣加工/铝板cnc加工/精密CNC加工源头企业综合评测
  • Yolo11分类模型
  • 市面上的开源 AI 智能体平台使用体验
  • 简支梁在荷载作用下的变形计算
  • 2025年真空烧结炉厂家权威推荐榜单:高效节能、智能温控、工业窑炉设备优质供应商精选
  • 基于 tar.gz 的自定义 安装InfluxDB
  • 2025年移动泵车厂家推荐排行榜,防汛泵车,水泵机组,应急排水泵车,柴油机泵车公司精选
  • Oracle 触发器
  • 2025年铁氟龙高温线厂家推荐排行榜,铁氟龙/极细铁氟龙/UL10064铁氟龙/UL1332铁氟龙/UL1867铁氟龙公司推荐
  • Slope Trick
  • 阅读笔记二:高效编程的核心策略
  • OpenAI 发布 GPT-5 Instant:AI 有了 “情感温度计“ - 实践
  • 线性代数 SVD | 几何本质、求解方法与应用 - 教程
  • SG 函数
  • 2025 年铝包木阳光房生产厂家最新推荐榜:口碑至上的实力品牌甄选及选购指南
  • Oracle统计信息相关
  • 2025年栏杆护栏厂家权威推荐榜:不锈钢栏杆、桥梁防撞护栏、河道景观护栏,专业制造与工程应用深度解析
  • Consul 与 Prometheus 集成实战:服务自动发现与监控配置指南(含 ThinkPHP8 示例)
  • 2025年TYPE-C母座厂家权威推荐榜:防水/板上/沉板/立插/卧式/侧贴/贴片式/插件式全系列,5A大电流高速TID认证接口一站式供应
  • 题解:P1196 [NOI2002] 银河英雄传说
  • Oracle下查询数据库SQL ID
  • 进程管理专题(一)
  • 使用SemaphoreSlim控制并发数
  • 杂题简述
  • css网格布局