MySQL死锁类deadlock问题排查

 更新时间:2026年03月11日 09:16:34   作者:长路 ㅤ  
本文主要介绍了MySQL死锁类deadlock问题排查,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

认识常用命令

SHOW ENGINE INNODB STATUS;

介绍

SHOW ENGINE INNODB STATUS; 是 InnoDB 存储引擎提供的一个诊断工具,它会输出一份非常详细的报告,包含 InnoDB 内部多个维度的状态信息。这份报告主要包含以下几个部分:

  1. BACKGROUND THREAD: 后台主线程(如刷新脏页)的活动信息。
  2. SEMAPHORES: 信号量信息,用于诊断线程间争用和锁等待。如果系统存在大量锁等待,这里会有体现。
  3. LATEST DETECTED DEADLOCK: 这是你最关心的部分。它记录了最近一次发生的死锁的详细信息,包括:
    • 导致死锁的事务:涉及死锁的多个事务的线程ID、正在执行的SQL语句(可能不是完整的业务SQL,而是锁等待相关的内部SQL)。
    • 事务持有的锁和等待的锁:清晰展示了每个事务已经持有什么锁,以及它正在尝试获取什么锁。
    • 回滚的事务:InnoDB 选择哪个事务作为“牺牲品”来回滚以打破死锁。
  1. TRANSACTIONS: 当前活跃的事务信息。
  2. FILE I/O: I/O 相关线程信息。
  3. BUFFER POOL AND MEMORY: 缓冲池和内存的使用统计。
  4. ROW OPERATIONS: 行操作相关的统计信息。

为什么没查到你的死锁信息?

核心原因:**LATEST DETECTED DEADLOCK** 只记录最近一次死锁。

想象一下,它是一个只能容纳一条记录的“死锁日志表”。当发生一个新的死锁时,旧的记录就会被覆盖。

所以,可能的情况是:

  1. 在你的程序报错和你在数据库执行 SHOW ENGINE INNODB STATUS; 之间的这段时间内,系统又发生了新的死锁,把你遇到的那个死锁信息给覆盖掉了。
  2. 数据库可能在你查询之前重启过,因为这份报告是存储在内存中的,重启后会清空。

方式汇总

方式一:执行SHOW ENGINE INNODB STATUS;命令

直接执行该命令查看最近的一次死锁日志记录:

SHOW ENGINE INNODB STATUS;

方式二:死锁日志记录

初始化

步骤一:开启并配置永久的死锁日志记录

这是最重要的一步,能让你在死锁发生后从容地分析。

1、开启 InnoDB 死锁日志打印到错误日志:

确保你的 MySQL 配置文件中(如 my.cnfmy.ini)有以下配置:

[mysqld]
innodb_print_all_deadlocks = ON

这个配置会让 InnoDB 将每一次死锁的详细信息都记录到 MySQL 的错误日志(Error Log)中,而不是仅仅在 SHOW ENGINE INNODB STATUS; 中保留最近一次。

修改后需要重启 MySQL 服务,或者动态设置(需要有权限):

SET GLOBAL innodb_print_all_deadlocks = ON;

2、配置并监控错误日志
找到你的 MySQL 错误日志文件路径(可以通过 SHOW VARIABLES LIKE 'log_error'; 查看)。
之后,每当发生死锁,你都可以去这个日志文件里搜索 "DEADLOCK" 关键字,找到完整的死锁报告。

步骤二:捕获并分析死锁现场

当你的应用程序(例如,日志中、监控系统)报告死锁错误时(MySQL 通常会返回 Error 1213),立即去检查错误日志。

你会看到类似这样的报告(这是一个简化示例):

*** (1) TRANSACTION:
TRANSACTION 123456, ACTIVE 10 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 100, OS thread handle 0x..., query id 1000 ... updating
DELETE FROM t1 WHERE a = 1

*** (1) HOLDS THE LOCK(S): -- 事务1持有的锁
RECORD LOCKS space id 100 page no 10 n bits 80 index PRIMARY of table `test`.`t1` trx id 123456 lock_mode X locks rec but not gap
Record lock, heap no 5 PHYSICAL RECORD: ...

*** (1) WAITING FOR THIS LOCK TO BE GRANTED: -- 事务1在等待的锁
RECORD LOCKS space id 100 page no 11 n bits 80 index sec_idx of table `test`.`t1` trx id 123456 lock_mode X locks rec but not gap waiting
Record lock, heap no 6 PHYSICAL RECORD: ...

*** (2) TRANSACTION:
TRANSACTION 123457, ACTIVE 15 sec starting index read
mysql tables in use 1, locked 1
4 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 101, OS thread handle 0x..., query id 1001 ... updating
DELETE FROM t1 WHERE a = 2

*** (2) HOLDS THE LOCK(S): -- 事务2持有的锁
RECORD LOCKS space id 100 page no 11 n bits 80 index sec_idx of table `test`.`t1` trx id 123457 lock_mode X locks rec but not gap
Record lock, heap no 6 PHYSICAL RECORD: ...

*** (2) WAITING FOR THIS LOCK TO BE GRANTED: -- 事务2在等待的锁
RECORD LOCKS space id 100 page no 10 n bits 80 index PRIMARY of table `test`.`t1` trx id 123457 lock_mode X locks rec but not gap waiting
Record lock, heap no 5 PHYSICAL RECORD: ...

*** WE ROLL BACK TRANSACTION (2) -- 数据库选择回滚了事务2

步骤三:解读死锁报告并定位业务代码

分析上面的报告,关键是找到:

涉及的事务:两个(或多个)事务分别在执行什么 SQL?

示例中,两个事务都在执行 DELETE,但条件不同 (a=1a=2)。

  1. 锁的持有和等待关系
    • 事务1:持有了 PRIMARY 索引上某行的 X 锁,正在等待 sec_idx 索引上某行的 X 锁。
    • 事务2:持有了 sec_idx 索引上某行的 X 锁,正在等待 PRIMARY 索引上某行的 X 锁。
  1. 死锁成因
    这就形成了一个典型的“循环等待”:事务1等事务2,事务2又在等事务1。数据库为了打破僵局,选择回滚其中一个(这里是事务2)。

排查过程

1、立即捕获死锁现场

# 1. 立即查询最新死锁信息(趁还没被覆盖)
SHOW ENGINE INNODB STATUS\G

# 2. 检查死锁记录是否已开启
SHOW VARIABLES LIKE 'innodb_print_all_deadlocks';

# 3. 如果未开启,立即开启(避免后续死锁丢失)
SET GLOBAL innodb_print_all_deadlocks = ON;

2、定位日志中的死锁情况

# 1. 找到错误日志位置
mysql -e "SHOW VARIABLES LIKE 'log_error';"

# 2. 实时监控错误日志中的死锁(推荐)
tail -f /var/log/mysql/error.log | grep -A 50 -B 5 "DEADLOCK"

# 3. 或者搜索历史死锁记录
grep -A 50 "DEADLOCK" /var/log/mysql/error.log

3、快速分析核心问题

在死锁日志中,重点关注以下4个部分:

text
LATEST DETECTED DEADLOCK
------------------------
*** (1) TRANSACTION:     [关键点1:事务1信息]
TRANSACTION 1234, ACTIVE 10 sec updating
mysql tables in use 1, locked 1
[看这里→] UPDATE table_x SET ... WHERE id = 1  [关键SQL1]

*** (1) HOLDS THE LOCK(S):    [关键点2:事务1持有的锁]
RECORD LOCKS index `idx_name` of table `db`.`table` trx id 1234 lock_mode X

*** (1) WAITING FOR THIS LOCK(S): [关键点3:事务1等待的锁]
RECORD LOCKS index `primary` of table `db`.`table` trx id 1234 lock_mode X waiting

*** (2) TRANSACTION:     [关键点4:事务2信息]
TRANSACTION 1235, ACTIVE 8 sec updating
[看这里→] UPDATE table_x SET ... WHERE id = 2  [关键SQL2]

4、快速诊断模板

对照这个模板分析:

检查项要问的问题常见原因
死锁类型不同索引冲突还是相同资源争用?跨索引死锁常见
SQL语句两个事务执行的具体SQL是什么?UPDATE/DELETE 容易死锁
资源顺序事务访问资源的顺序是否一致顺序不一致是主因
事务大小事务中是否包含多个SQL大事务容易死锁
索引使用WHERE条件是否走了合适索引无索引导致锁表

紧急应对策略:

-- 1. 查看当前锁等待情况(辅助分析)
SELECT * FROM information_schema.INNODB_LOCKS;
SELECT * FROM information_schema.INNODB_LOCK_WAITS;

-- 2. 查看当前活跃事务
SELECT * FROM information_schema.INNODB_TRX ORDER BY trx_started DESC;

死锁解决方案

1、分析是否事务过大导致。

2、有无涉及到两段代码为:

A B

B A

的过程

相关排查思路文章

[1]. Mysql死锁日志分析:事务逻辑冲突的排查技巧 

[2]. MySQL 故障案例分析:从死锁到数据丢失的全面诊断指南

到此这篇关于MySQL死锁类deadlock问题排查的文章就介绍到这了,更多相关MySQL死锁类deadlock排查内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL联合索引的使用解读

    MySQL联合索引的使用解读

    这篇文章主要介绍了MySQL联合索引的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-06-06
  • SQL分页查询存储过程代码分享

    SQL分页查询存储过程代码分享

    本文主要分享了SQL分页查询存储过程的具体实例代码,具有一定的参考价值,需要的朋友一起来看下吧
    2016-12-12
  • MySQL8.0窗口函数入门实践及总结

    MySQL8.0窗口函数入门实践及总结

    这篇文章主要给大家介绍了关于MySQL8.0窗口函数入门实践及总结的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用MySQL8.0具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-06-06
  • MySQL主机因多次连接数据库错误而被阻塞的解决方案

    MySQL主机因多次连接数据库错误而被阻塞的解决方案

    文章讲述了MySQL数据库连接失败导致主机被阻塞的问题,分析了原因,并提供了两种解决方法:调整max_connect_errors参数和执行FLUSH HOSTS命令
    2025-12-12
  • MySQL Cluster集群的初级部署教程

    MySQL Cluster集群的初级部署教程

    这篇文章主要介绍了MySQL Cluster集群的初级部署教程, MySql Cluster可以利用充分利用节点服务器的多进程做到高可用,需要的朋友可以参考下
    2016-02-02
  • 绿色版mysql注册卸载服务方法

    绿色版mysql注册卸载服务方法

    如果直接用绿色版的mysql,则下载后解压,只需对目录下的my.ini文件的basedir(mysql的基本目录)和datadir(mysql数据目录)指定就可以,如下所示。
    2013-06-06
  • Mysql数据库的一些命令

    Mysql数据库的一些命令

    如果你习惯用 windows 的数据库,也就是在 图形界面上操作数据库的话,那么当你在命令上 操作 mysql 将会感到陌生,其实只要你掌握了一些基本命令,还有经常使用,熟练起来了, 将会相当方便,而且很快速
    2013-11-11
  • MYSQL事务回滚的2个问题分析

    MYSQL事务回滚的2个问题分析

    在事务中,每个正确的原子操作都会被顺序执行,直到遇到错误的原子操作,此时事务会将之前的操作进行回滚。回滚的意思是如果之前是插入操作,那么会执行删 除插入的记录,如果之前是update操作,也会执行update操作将之前的记录还原
    2014-05-05
  • mysql 8.0.12 winx64详细安装教程

    mysql 8.0.12 winx64详细安装教程

    这篇文章主要为大家详细介绍了mysql 8.0.12 winx64详细安装配置图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • MySQL 5.7安装后默认登录密码的查看方法

    MySQL 5.7安装后默认登录密码的查看方法

    许多朋友安装MySQL 5.7之后不知道默认登录密码在哪里查看,本文小编将通过代码示例和图文结合的方式给大家介绍MySQL 5.7安装后默认登录密码的查看方法,需要的朋友可以参考下
    2023-12-12

最新评论