MySQL之死锁问题及其解决方案

 更新时间:2023年12月11日 08:33:39   作者:王廷云的博客  
数据库死锁问题是我们老生常谈的问题了,在我们实际开发过程中经常会遇到,本文主要介绍了MySQL之死锁问题及其解决方案,具有一定的参考价值,感兴趣的可以了解一下

前言

数据库死锁问题是我们老生常谈的问题了,在我们实际开发过程中经常会遇到,为了尽量避免出现死锁,我们需要了解出现死锁的场景。同时,如果线上出现了死锁之后怎么去分析、排查和解决,下面我就这两点介绍一下。

一、数据库死锁介绍

1、什么是数据库死锁?

数据库的死锁是指:不同的事务在获取资源时相互等待,导致无法继续执行的一种情况。当发生死锁时,数据库系统会自动中断其中一个事务,以解除死锁。在数据库中,事务可以分为读事务和写事务。读事务只需要获取读锁,而写事务需要获取写锁。当多个事务同时操作同一组数据时,可能会引发死锁的出现。

2、MySQL 发生死锁的场景

2-1、事务同时更新多个表

当一个事务同时更新多个表并且使用了不同的顺序,可能会导致死锁的发生。例如,事务 A 首先更新表 X,此时获取到了 X 表的锁,并在未释放该锁的情况下尝试更新表 Y;而事务 B 首先更新表Y,此时获取到了 Y 表的锁,并在未释放锁的情况下尝试更新表 X。这种情况下,两个事务会相互等待对方的锁释放,从而形成死锁。

2-2、事务嵌套

当一个事务内部开启了另一个事务,并在内层事务中更新了某个表,而外层事务也需要更新该表的同一行记录时,就有可能发生死锁。因为外层事务需要等待内层事务释放锁,而内层事务需要等待外层事务释放锁。

2-3、索引顺序不一致

当多个事务按照不同的顺序访问相同的数据行,并且使用了不同的索引时,可能会发生死锁。例如,事务 A 按照索引 1 的顺序访问数据行,事务 B 按照索引 2 的顺序访问同一组数据行,这样两个事务之间就会产生死锁。

2-4、不同事务同时更新相同的索引

当多个事务同时更新相同的索引时,可能会导致死锁。这是因为事务在更新索引时会获取对应的锁,并在未释放锁的情况下尝试更新其他数据,从而形成死锁。

二、解决死锁问题

如果线上发生了死锁,我们应该采取以下步骤进行处理:

1、 监控死锁

正常情况下我们都会建立死锁监控机制,以便及时掌握死锁情况;同时设置相应的预警机制,以便在死锁发生时能够及时处理。

通过数据库的监控工具或命令可以查看是否存在死锁情况,如果出现则了解死锁的具体情况,包括死锁的事务和死锁的资源。

2、终止死锁事务

根据监控结果,找到造成死锁的事务,并手动选择其中一个事务终止。可以根据事务的执行时间、影响行数、优先级等因素进行终止决策。可以通过 select * from information_schema.innodb_trx 语句查看死锁情况。

在 innodb 中,有三张表可以帮助我们更好去分析死锁信息:

  • information_schema.innodb_trx:事务信息表。
  • information_schema.innodb_locks:事务锁的信息表。
  • information_schema.innodb_lock_waits:锁等待关系表。

系统自动解除死锁:

正常情况下,当发生死锁时,MySQL 系统会自动解除死锁,至于解除哪个事务的锁,需要亏了一个代价,在解除死锁方面,会选择回滚事务产生影响最小的一个进行回滚。

这里就要提一下两个概念了,一个是事务的权重(trx_weight),另外一个是事务的调度权重(trx_schedule_weight):

  • 事务的权重:与回滚事务的选择有关。具体与事务 undo 版本链的长度有关,回滚的 undo 记录越多,产生的影响就会越大,MySQL 就不会选择这样的事务,倘若事务权重一样,会选择事务等待队列等待时间短的事务进行回滚。
  • 事务的调度权重:与事务获取资源的先后有关。MySQL8.0.20 之前在等待锁的事务优先级排序采取 FIFO 算法,之后采取 CATS 算法。该算法通过分配调度权限对等待的事务进行优先级排序,该权重是根据事务阻塞的事务数量计算的。例如,两个事务正在等待同一对象上的锁,那么阻塞最多事务的事务将被分配更大的调度权重,如果权重相等,则优先考虑等待时间最长的事务分配资源。

3、重试事务

终止死锁事务后,需要重新执行被终止的事务。这可能需要一些逻辑处理,例如对数据进行回滚或者重新执行一些操作。

4、分析死锁原因

通过数据库的日志和监控信息,分析死锁的原因。下面是查看死锁日志的命令语句:

show engine innodb status;

分析死锁日志然后根据死锁原因对数据库的设计和代码进行优化,以尽量减少死锁的发生。

同时也可以根据分析结果,针对性地进行数据库结构调整、索引优化、事务隔离级别调整等措施,以降低死锁的概率。

5、避免死锁建议

  • 事务尽可能小,不要将复杂逻辑放进一个事务里。
  • 涉及多行记录时,约定不同事务以相同顺序访问。
  • 业务中要及时提交或者回滚事务,可减少死锁产生的概率。
  • 表要有合适的索引。
  • 可尝试将隔离级别改为 ReadCommit 。

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

相关文章

  • mysql 索引的基础操作汇总(四)

    mysql 索引的基础操作汇总(四)

    这篇文章主要为大家详细介绍了mysql 索引的基础操作汇总,涵盖了创建和查看索引、删除索引等操作,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • 安装MySQL时在Initializing database步骤出错问题及解决过程

    安装MySQL时在Initializing database步骤出错问题及解决过程

    安装MySQL时初始化数据库步骤出错,原因是计算机名和计算机组名不是全英文,解决办法卸载已安装的MySQL,修改计算机名和计算机组名为全英文,最后重新安装MySQL
    2026-04-04
  • MySQL深分页问题解决思路

    MySQL深分页问题解决思路

    这篇文章主要介绍了优雅地解决mysql深分页问题,本文将会讨论当mysql表大数据量的情况,如何优化深分页问题,并附上最近的优化慢sql问题的案例伪代码,需要的朋友可以参考下
    2022-12-12
  • 详细讲一讲MySQL中Select语句的执行顺序

    详细讲一讲MySQL中Select语句的执行顺序

    SQL和MySQL的语句执行顺序是数据库操作中的关键概念,理解这一顺序有助于编写更高效、更精确的查询,这篇文章主要介绍了MySQL中Select语句执行顺序的相关资料,需要的朋友可以参考下
    2026-01-01
  • MySQL 调优的实战思路

    MySQL 调优的实战思路

    文章总结了MySQL调优的过程,包括从确认问题到解决的步骤,首先,需要度量问题,然后从SQL、索引、配置和系统等方面进行排查和优化,文章强调了SQL和索引的重要性,并提供了具体的优化方法,最后,文章提供了一个实战调优流程,以及一些监控和排查工具清单,感兴趣的朋友一起看看吧
    2025-12-12
  • MYSQL 的10大经典优化案例场景实战

    MYSQL 的10大经典优化案例场景实战

    在应用开发的早期,数据量少,开发人员开发功能时更重视功能上的实现,随着生产数据的增长,很多SQL语句开始暴露出性能问题,对生产的影响也越来越大,有时可能这些有问题的SQL就是整个系统性能的瓶颈。本文我们就聊聊MYSQL的优化
    2021-09-09
  • Mysql启动报错Error1045(28000)的原因分析及解决

    Mysql启动报错Error1045(28000)的原因分析及解决

    这篇文章主要介绍了Mysql启动报错Error1045(28000)的原因分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • Mysql join连接查询的语法与示例

    Mysql join连接查询的语法与示例

    这篇文章主要给大家介绍了关于Mysql join连接查询的相关资料,文中介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • MySQL用户账户分类的使用

    MySQL用户账户分类的使用

    MySQL 8.0.16引入用户账户分类机制,通过SYSTEM_USER权限区分系统用户和普通用户,下面就来详细的介绍一下如何使用,感兴趣的可以了解一下
    2025-11-11
  • mysql如何去掉某个字段中的第一个出现的字符串

    mysql如何去掉某个字段中的第一个出现的字符串

    这篇文章主要介绍了mysql如何去掉某个字段中的第一个出现的字符串问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07

最新评论