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

 更新时间:2026年06月03日 09:37:26   作者:码不停蹄的玄黓  
这段文章介绍了MySQL死锁的处理与预防策略,涵盖了自动自动处理、查看死锁日志、临时应急措施以及永久避免死锁的方法,通过优化事务逻辑、固定访问顺序和加索索引等措施,可以有效减少死锁的发生,需要的朋友可以参考下

引言

死锁是多个事务互相持有对方需要的锁,且都不释放,导致互相无限等待的现象,MySQL 会自动检测并终止其中一个事务(抛出死锁异常),让另一个正常执行。

你现在的核心需求分两步:

  1. 紧急处理:已经发生死锁,怎么快速恢复业务?
  2. 根治问题:怎么让死锁不再频繁出现?

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

1. 无需手动杀进程!MySQL 会自动处理

MySQL 内置死锁检测(默认开启),一旦检测到死锁:

  • 立即回滚代价最小的那个事务
  • 给应用抛出 Deadlock found when trying to get lock; try restarting transaction 异常
  • 另一个事务会自动继续执行,死锁瞬间解除

结论已发生的死锁不需要人工干预,MySQL 自己会秒级解决。

2. 查看死锁日志:找到根源(最重要)

死锁已经发生,必须查日志定位原因,执行命令:

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

在结果中找到 LATEST DETECTED DEADLOCK 段落,里面会告诉你:

  • 哪两个事务死锁了
  • 各自执行的 SQL
  • 各自持有什么锁、等待什么锁
  • 死锁发生的时间

这是解决死锁的唯一依据

3. 临时应急:卡住的事务不自动解除?

极少数情况(关闭了死锁检测),事务会一直卡住,执行以下命令手动处理:

-- 1. 查看正在运行的事务,找到卡住的 ID
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

-- 2. 杀掉卡住的事务
KILL 事务ID;

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

死锁无法100%杜绝,但99%的死锁都能通过规范避免

1. 事务保持短小,不要长事务

  • 死锁概率和事务执行时间成正比
  • 禁止在事务里嵌套:网络请求、文件IO、人工操作、sleep
  • 原则:快进快出,执行完立即提交/回滚

坏例子

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

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. 兜底:业务捕获死锁异常自动重试,用户无感知

到此这篇关于MySQL已产生死锁的解决方法及永久避免方案的文章就介绍到这了,更多相关MySQL已产生死锁解决与避免内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Linux下指定mysql数据库数据配置主主同步的实例

    Linux下指定mysql数据库数据配置主主同步的实例

    Linux下指定数据库数据配置主主同步的实例,有需要的朋友可以参考下
    2013-01-01
  • mysql日志文件之undo log和redo log

    mysql日志文件之undo log和redo log

    MySQL日志记录了MySQL数据库日常操作和错误信息,MySQL有不同类型的日志文件,下面这篇文章主要给大家介绍了关于mysql日志文件之undo log和redo log的相关资料,需要的朋友可以参考下
    2022-04-04
  • MySql用DATE_FORMAT截取DateTime字段的日期值

    MySql用DATE_FORMAT截取DateTime字段的日期值

    MySql截取DateTime字段的日期值可以使用DATE_FORMAT来格式化,使用方法如下
    2014-08-08
  • MySQL外键约束的删除和更新总结

    MySQL外键约束的删除和更新总结

    这篇文章主要给大家总结MySQL外键约束的删除和更新,文中通过代码示例和图文介绍的非常详细,对大家了解MySQL外键约束有一定的帮助,需要的朋友可以参考下
    2024-02-02
  • MySQL中有哪些情况下数据库索引会失效详析

    MySQL中有哪些情况下数据库索引会失效详析

    这篇文章主要给大家介绍了关于MySQL中有哪些情况下数据库索引会失效的相关资料,文中通过图文介绍的非常详细,对大家学习或者使用mysql具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07
  • Mysql使用索引的正确方法及索引原理详解

    Mysql使用索引的正确方法及索引原理详解

    这篇文章主要给大家介绍了关于Mysql使用索引的正确方法及索引原理的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用mysql具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-05-05
  • MySQL之join查询优化方式

    MySQL之join查询优化方式

    这篇文章主要介绍了MySQL之join查询优化方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • 使用MySQL Workbench构建ER图的详细教程

    使用MySQL Workbench构建ER图的详细教程

    ER图又称实体-联系图(Entity Relationship Diagram),提供了表示实体类型、属性和联系的方法,用来描述现实世界的概念模型,MySQL Workbench是一个强大的数据库设计工具,提供了便捷的数据导入导出功能,本文介绍了使用MySQL Workbench构建ER图的详细教程
    2024-06-06
  • 浅谈MySql 视图、触发器以及存储过程

    浅谈MySql 视图、触发器以及存储过程

    这篇文章主要介绍了MySql 视图、触发器以及存储过程的的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • MySQL可以使用斜线来当字段的名字

    MySQL可以使用斜线来当字段的名字

    无意中发现MySQL可以使用斜线来当字段的名字,下面有个示例,需要的朋友可以参考下
    2014-03-03

最新评论