游乐游手机版
首页/数据库/文章详情

MySQL死锁解决方法与永久避免方案

时间:2026-08-06 06:33
MySQL自动检测死锁并回滚代价最小的事务,无需人工干预。通过SHOWENGINEINNODBSTATUS查看死锁日志定位根源。永久避免需保持短事务、固定表访问顺序、加索引,并在业务代码中捕获死锁异常自动重试。

说到MySQL里的死锁,其实用一个场景就能说清楚:多个事务像是在十字路口互相抢路,谁都不肯让步,结果全部堵在路中间动弹不得。而在MySQL的底层设计里,系统会迅速察觉到这个僵局——它会主动选一个代价最小的事务“拖出去”,直接中断该事务并抛出一个死锁异常,另一个事务则顺利通行。这就是为什么我们在实际开发中,经常会收到类似“Deadlock found when trying to get lock”这样的报错信息。

这篇内容主要解决两个实际痛点:

  1. 已经发生死锁怎么办:也就是业务被死锁卡住时,如何快速恢复?
  2. 如何从根源上预防:让这种“交通堵塞”不再反复出现。

MySQL已产生死锁的解决方法及永久避免方案

一、已经产生死锁:3步快速解决与排查

1. 无需手动杀进程!MySQL 内置死锁检测会自动处理

MySQL引擎内部自带一套死锁检测机制,默认处于开启状态。一旦监测到死锁:

  • 它会立即回滚代价最小的那个事务
  • 然后向应用层抛出一个 Deadlock found when trying to get lock; try restarting transaction 异常
  • 而另一边,另一个事务完全不受影响,继续正常执行——死锁瞬间被解除

所以第一件需要明确的事情是:死锁一旦发生,无需人工手动干预,MySQL自身就能在毫秒级把问题解决掉。

2. 查看死锁日志:精准定位根源(最关键的一步)

虽然MySQL帮你把堵住的车拖走了,但你绝不能忽略“到底是怎么堵的”这个核心问题。这才是真正需要重视的事情。定位死锁原因只需一条命令:

-- 查看最近一次死锁的详细信息SHOW ENGINE INNODB STATUS;

在返回的结果中,找到 LATEST DETECTED DEADLOCK 这一部分,它会清晰告诉你:

  • 是哪两个事务纠缠在一起
  • 各自执行的SQL语句是什么
  • 各自持有哪些锁、又在等待哪些锁
  • 死锁发生的具体时间

一句话总结:这是后续所有调优工作的唯一可靠依据。

3. 临时应急:如果事务卡住不自动解除怎么办?

有一种比较少见的情况,就是如果你手动关闭了死锁检测,事务就会一直挂在那里无法推进。此时你可以通过下面两个命令手动处理:

-- 1. 查看当前正在运行的事务,找到卡住的 IDSELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;-- 2. 强制杀掉卡住的事务KILL 事务ID;

二、永久避免死锁:4个核心方案(必做)

说实话,死锁在技术层面确实无法做到100%杜绝,但通过规范化的设计和良好的编码习惯,99%的死锁其实完全可以被有效控制。

1. 事务保持短小精悍,避免长事务

  • 死锁发生的概率与事务执行时间成正比,这是一个很难绕过的规律
  • 严禁在事务内部嵌套:网络请求、文件IO、人工操作或sleep等待
  • 基本原则:快进快出,执行完毕立即提交或回滚

典型的反面案例:

BEGIN;UPDATE 表 SET ...;-- 这里调用了外部接口,耗时3秒,锁一直持有,极易引发死锁COMMIT;

3秒的耗时,在数据库世界里已经属于“长事务”了。

2. 所有表固定访问顺序(最有效的策略)

死锁的本质说起来并不复杂:访问顺序冲突

  • 事务A:先锁订单 → 再锁库存
  • 事务B:先锁库存 → 再锁订单

→ 结果就是瞬间死锁。

解决方案也很直接:在业务代码层,所有表和行的访问顺序必须统一约定。比如所有人一律“先操作库存,再操作订单”,永不例外。

3. 给查询条件加索引

没有索引的情况下,行锁会升级成表锁,死锁的概率会暴增好几个数量级。

-- 错误:无索引,会锁全表UPDATE user SET money=100 WHERE name='张三'; -- 正确:name 有索引,只锁单行UPDATE user SET money=100 WHERE name='张三'; 

如果查看死锁日志时发现里面有 LOCK_MODE: X, REC_NOT_GAP: nil,基本可以断定就是缺少索引引起的。

4. 业务代码捕获死锁异常,自动重试

死锁说到底是一个偶发异常,重试一次就能解决,这是整个方案里最稳妥的兜底措施。

以Java为例:

try {    // 执行数据库操作} catch (SQLTransactionRollbackException e) {    if (e.getMessage().contains("Deadlock")) {        // 死锁异常,重试1-2次        retry();    }}

三、快速排查死锁 Checklist

  1. 执行 SHOW ENGINE INNODB STATUS; 查看死锁详情
  2. 检查两个事务是否访问表或行的顺序相反
  3. 检查更新语句是否缺少索引
  4. 检查是否存在长事务
  5. 业务代码是否没有实现重试机制

总结

  1. 已产生的死锁:MySQL会自动回滚一个事务,无需人工介入
  2. 查找死锁原因:使用 SHOW ENGINE INNODB STATUS; 命令
  3. 根治死锁:固定访问顺序 + 合理加索引 + 短事务 + 代码重试
  4. 兜底方案:业务层捕获死锁异常并自动重试,用户几乎无感知
来源:https://www.jb51.net/database/365087cs5.htm
上一篇MySQL前缀索引原理与使用详解 下一篇MySQL DDL操作从入门到精通核心知识与技巧解析
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
Redis是什么:核心特性、架构与应用场景解析
数据库 · 2026-09-01

Redis是什么:核心特性、架构与应用场景解析

Redis是一款基于内存的键值型NoSQL数据库,以超高读写速度和丰富的数据结构著称。本文系统梳理Redis的核心特性、架构组成、性能优势及典型应用场景,并通过与Memcached、MySQL、MongoDB的对比,帮助开发者快速判断Redis是否适合当前业务需求。

Windows 安装 MongoDB 完整图文教程
数据库 · 2026-09-01

Windows 安装 MongoDB 完整图文教程

本文详细介绍在 Windows 系统上安装 MongoDB 的完整流程。从官网下载 MSI 安装包开始,逐步演示自定义安装路径、配置 Windows 服务、跳过 MongoDB Compass 等关键选项,并提供通过系统服务列表验证安装是否成功的方法,帮助开发者快速搭建本地 MongoDB 环境。

Linux 安装 MongoDB 完整指南:依赖配置、环境变量与服务启动
数据库 · 2026-09-01

Linux 安装 MongoDB 完整指南:依赖配置、环境变量与服务启动

本文详解在 Linux 系统下安装 MongoDB 的完整流程,涵盖依赖包安装、二进制包下载解压、环境变量配置、数据与日志目录创建及服务启动验证。通过标准化命令与路径说明,帮助开发者快速完成部署并确认服务状态。

MacOS安装MongoDB完整教程
数据库 · 2026-09-01

MacOS安装MongoDB完整教程

本文介绍在MacOS系统下安装MongoDB的完整流程,涵盖下载、解压、目录配置、环境变量设置及服务启动。通过明确的命令与参数说明,帮助开发者快速完成环境搭建并验证安装结果。

Ubuntu系统安装与配置Redis完整指南
数据库 · 2026-09-01

Ubuntu系统安装与配置Redis完整指南

本文详解在Ubuntu系统中安装Redis的两种主流方式:apt在线安装与源码编译安装。涵盖版本选择逻辑、服务启停与状态检查、连接验证方法,以及在线练习工具与桌面GUI客户端的对比与使用建议,帮助开发者快速搭建并验证Redis运行环境。