0

0

mysql如何排查死锁

P粉602998670

P粉602998670

发布时间:2025-09-18 14:15:02

|

777人浏览过

|

来源于php中文网

原创

答案是通过SHOW ENGINE INNODB STATUS命令查看LATEST DETECTED DEADLOCK部分,结合INNODB_TRX等表分析事务状态,定位死锁涉及的事务、SQL语句及锁等待关系,进而从索引优化、事务拆分、操作顺序一致等方面进行优化。

mysql如何排查死锁

排查MySQL死锁,核心在于快速定位死锁发生的现场,并理解其根源,从而找到解决的突破口。这不仅仅是看一眼日志那么简单,更像是一场侦探游戏,需要你从蛛丝马迹中还原真相。

解决方案

当MySQL发生死锁时,首先要做的是捕获死锁信息。最直接、最有效的方式就是通过

SHOW ENGINE INNODB STATUS
命令来查看最新的死锁报告。这个报告会详细记录死锁涉及的事务、它们持有的锁、请求的锁以及导致死锁的具体SQL语句。

通常,在

LATEST DETECTED DEADLOCK
部分,你会看到两个事务的详细信息,一个被标记为“LATEST DETECTED DEADLOCK”,另一个是“*** (2) WAITING FOR THIS LOCK TO BE GRANTED:”。前者是被选为死锁牺牲品(ROLLBACK)的事务,后者则是导致死锁发生的另一个关键事务。仔细分析这两个事务的SQL语句、它们正在操作的表和索引,以及它们各自持有的锁和正在等待的锁,就能基本还原死锁发生的场景。

SHOW ENGINE INNODB STATUS;

这个命令的输出内容非常庞大,但大部分时候,我们只需要聚焦在

LATEST DETECTED DEADLOCK
这一小节。如果死锁频繁发生,可以考虑开启
innodb_print_all_deadlocks
参数,让所有死锁信息都打印到MySQL错误日志中,方便后续分析。

如何快速识别并捕获MySQL死锁信息?

识别死锁,很多时候是业务系统抛出异常,提示“Deadlock found when trying to get lock; try restarting transaction”时才察觉。但作为DBA或开发者,我们不能仅仅被动等待。除了前面提到的

SHOW ENGINE INNODB STATUS
,还有一些主动或辅助的手段。

比如,通过查询

information_schema
数据库中的
INNODB_TRX
INNODB_LOCKS
INNODB_LOCK_WAITS
这几个表,可以实时查看当前正在运行的事务、它们持有的锁以及等待的锁。虽然这些表不会直接告诉你“死锁发生了”,但它们能帮你描绘出事务和锁的实时状态图。当发现某个事务长时间处于等待状态,并且等待的锁被另一个事务持有,而那个事务又在等待这个事务持有的锁时,死锁的苗头就已经很明显了。

TapNow
TapNow

新一代AI视觉创作引擎

下载

我个人习惯是,一旦怀疑有死锁,除了

SHOW ENGINE INNODB STATUS
,还会迅速扫一眼
INNODB_TRX
,看看有没有长时间运行的事务,或者那些状态看起来有点“僵住”的事务。这个过程有点像医生问诊,除了看病历(死锁日志),还要摸脉(实时事务状态)。

SELECT
    t.trx_id,
    t.trx_state,
    t.trx_started,
    t.trx_mysql_thread_id,
    t.trx_query
FROM
    information_schema.innodb_trx t
WHERE
    t.trx_state = 'LOCK WAIT'; -- 查找正在等待锁的事务

解读死锁日志:事务、锁与SQL语句的关联分析

解读死锁日志,其实就是要把

LATEST DETECTED DEADLOCK
报告中的碎片信息拼凑起来,形成一个完整的死锁故事。这里面有几个关键点:

  1. 识别死锁受害者 (VICTIM) 和死锁发起者 (ROLLBACK)。 日志通常会明确指出哪个事务被回滚了。理解这一点很重要,因为我们后续的优化往往是围绕如何避免这个事务成为受害者,或者如何打破这种循环依赖。
  2. 分析事务持有的锁和请求的锁。 报告会列出每个事务当前持有的锁(
    HOLDS THE LOCK(S)
    )和它正在等待的锁(
    WAITING FOR THIS LOCK TO BE GRANTED
    )。核心就是找到那个循环:事务A持有X,请求Y;事务B持有Y,请求X。
  3. 关联SQL语句。 最重要的就是把这些锁的请求和持有,与具体的SQL语句对应起来。日志中会直接给出导致死锁的SQL语句。很多时候,你会发现问题出在不恰当的事务隔离级别、没有使用索引的更新/删除操作,或者事务中操作数据顺序不一致。

举个例子,你可能会看到两个事务都在更新同一张表,但一个事务先更新了ID=100的记录,然后尝试更新ID=200;另一个事务却反过来,先更新ID=200,再尝试更新ID=100。如果这两个操作都带有排他锁,那么死锁就不可避免了。这种场景下,SQL语句的顺序,以及它们背后对资源的争抢,才是我们要深挖的。

从死锁根源出发:常见的死锁场景与优化策略

死锁的发生,往往不是偶然,背后总有其逻辑。理解这些常见的死锁场景,能帮助我们更好地预防和优化。

  1. 更新/删除操作顺序不一致: 这是最经典的死锁场景。两个事务以不同的顺序更新相同的多行数据。
    • 优化策略: 确保所有涉及多行更新的事务,都以一致的顺序(例如,按主键ID升序)来操作数据。这是一种非常有效的预防措施。
  2. 索引缺失或不当: 当更新或删除操作没有命中索引时,InnoDB可能会锁定整张表或大范围的行,而不是精确的行,从而增加死锁的概率。
    • 优化策略: 检查
      WHERE
      子句是否使用了合适的索引。
      EXPLAIN
      是你的好朋友,用来分析SQL语句的执行计划,确保它能高效地使用索引。
  3. 长事务与大事务: 事务持续时间过长,或者一次性操作大量数据,都会增加锁的持有时间,从而提高与其他事务发生冲突的风险。
    • 优化策略: 尽量将大事务拆分成小事务,减少事务的持续时间。优化业务逻辑,避免不必要的锁持有。
  4. 不恰当的事务隔离级别: 比如
    SERIALIZABLE
    隔离级别虽然能提供最高的数据一致性,但也会引入更多的锁,增加死锁的可能性。
    • 优化策略: 大多数情况下,
      READ COMMITTED
      REPEATABLE READ
      已经足够。根据业务需求权衡隔离级别,避免过度锁定。
  5. 隐式锁定与外键约束: 外键约束在执行
    INSERT
    UPDATE
    DELETE
    时,可能会隐式地对关联表加锁,尤其是在没有为外键列创建索引时,这种风险更高。
    • 优化策略: 确保所有外键列都有对应的索引。

解决死锁,很多时候是一个迭代的过程。你可能需要调整SQL语句、优化索引、修改业务逻辑,甚至调整数据库配置。关键在于,每次死锁发生,都要把它当成一次学习的机会,深入分析,找到症结,然后应用合适的策略去解决。这不光是技术的挑战,更是一种对系统和业务逻辑的深刻理解。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

679

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

320

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

346

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1095

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

357

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

675

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

573

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

415

2024.04.29

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

9

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.8万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 793人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号