当你碰到了MySQL中的死锁,你了解这些机制吗?

深入MySQL锁机制:原理、死锁解决及Java防范技巧 表级锁(Table Lock)行级锁(Row Lock)页级锁(Page Lock) 阅读详情

MySQL死锁怎么来的?

当两个及以上的事务,双方都在等待对方释放已经持有的锁或因为加锁顺序不一致造成循环等待锁资源,就会出现“死锁”。

总结一下生产死锁的4个条件:

  1. 两个或者两个以上事务

  2. 每个事务都已经持有锁并且申请新的锁

  3. 锁资源同时只能被同一个事务持有或者不兼容

  4. 事务之间因为持有锁和申请锁导致彼此循环等待

举个例子:用户表,id是主键

事务1

事务2

begin;update user set username = '旭阳' where id = 10;

begin;update user set username = 'alvin' where id = 20;

update user set username = 'alvin' where id = 20;

update user set username = '旭阳' where id = 10;

  • 事务1优先获得了id=10的记录锁

  • 事务2其次获得了id=20的记录锁

  • 然后事务1现在请求id=20的记录锁资源,发现已经被占用了,阻塞等待其他事务释放

  • 同理,事务2请求id=10的记录锁资源,却被事务1占用了

  • 由于事务1和事务2都没有提交,所以他们不会释放锁,导致死锁,得到下面的报错:

​死锁的关键在于:两个(或以上)的事务加锁的顺序不一致。如果上面的事务2也是先锁id=10的记录,再锁id=20的记录,就不会出现死锁。

但是这很难达成,因为我们不同的业务,会有不同的逻辑处理,肯定会出现加锁顺序不一样的情况,特别是在高并发的场景下。

MySQL遇到死锁怎么办?

MySQL发生了死锁,总不能一直让事务现场等在那里,多蠢啊,那它采用什么策略解决死锁问题呢?

  1. 等待,直到超时

即当两个事务互相等待时,当一个事务等待时间超过设置的阈值时,就将其回滚,另外事务继续进行。innoDB存储引擎中,通过innodb_lock_wait_timeout配置设置超时时间,默认50秒。

优点:

  • 简单有效

缺点:

  • 如果真的发生死锁,等待50s这么久一般难以接受,设置太短比如1s, 2s,有可能误触发正常的锁等待。

  1. 使用死锁检测处理死锁程序

由于上面等待的方式太过被动,那有没有可以主动检测出是否存在死锁的方式呢?

MySQL提供了一种主动的死锁检测机制, 相当于将锁等待的信息保存下来,绘制出一个等待的有向图,如下:

​如果检测到存在环,说明有死锁,那么InnoDB存储引擎会选择回滚undo量最小的事务,让其他事务继续执行。

这种机制通过配置 innodb_deadlock_detect控制,默认打开。

​优点:

  • 主动检测,时效性低

缺点: 并发越高,图形越庞大,检测越耗时。每个新的被阻塞的线程,都要判断是不是由于自己的加入导致了死锁,这个操作时间复杂度是O(n)。如果100个并发线程同时更新同一行,意味着要检测100*100=1万次,1万个线程就会有1千万次检测。

上面两种方式并不冲突,默认情况下,MySQL都处于开启状态。

死锁日志怎么看?

虽然MySQL提供了默认的死锁处理机制,更重要的还是我们需要去从业务逻辑代码层面分析发生死锁的根本原因,然后去合理的规避死锁。那为了能够快速定位到死锁相关的业务代码,我们还需要会分析死锁日志。

死锁日志在哪呢?

  1. 通过show engine innodb status命令可以查看最近一次发生死锁的日志。

  2. 通过命令set global innodb_print_all_deadlocks = 1;开启死锁日志记录到MySQL错误日志中,默认情况是不开启的。

​死锁例子超详细解读

我们以上面的用户表为例,解读下死锁日志。

执行命令show engine innodb status获取死锁日志如下图所示:

​LATEST DETECTED DEADLOCK表示InnoDB引擎上次发生的死锁。死锁是至少需要有两个事务参与的,所以在其内部包含了发生死锁的具体两个事务。

  1. 第一个事务 (1) TRANSACTION

  • TRANSACTION 2415258889, ACTIVE 31 sec starting index read

说明: 事务号为2415258889,活跃 31秒,starting index read 表示事务状态为根据索引读取数据。注意删除和更新InnoDB内部也是要进行读操作的。

  • mysql tables in use 1, locked 1

说明: 说明当前的事务使用一个表,并且有一个表锁,DML操作会对表施加意向锁,本例是IX。

  • LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s)

说明: LOCK WAIT 表示正在等待锁,3 lock struct(s)表示 trx->trx_locks 锁链表的长度为3,每个链表节点代表该事务持有的一个锁结构,包括表锁,记录锁以及自增锁等。2 row lock(s)表示当前事务持有的行记录锁/ gap 锁的个数。

  • MySQL thread id 4576535

说明: 表示执行事务的线程id是4576535,即 show processlist; 展示的 ID。

  • update user set username = 'alvin' where id = 20

说明: 表示事务执行正在阻塞的SQL,注意不会显示事务全部执行的SQL

  • (1) WAITING FOR THIS LOCK TO BE GRANTED:

​说明: 这行信息表示等待的锁是一个record lock,空间id是221580,页编号为3,大概位置在页的80位处,锁发生在表user的主键索引上,是一个X锁,但是不是gap lock,waiting表示正在等待锁

  1. 第二个事务 (2) TRANSACTION

第二个事务基本上和第一个事务分析是一样的,我们挑选重要的和不一样的点:

  • (2) HOLDS THE LOCK(S)

​说明: 表明了事务二持有的锁正是事务1想要获取的锁。

  1. WE ROLL BACK TRANSACTION (2)

由于发生了死锁,最终回滚事务2。

我们可以借助死锁日志分析死锁发生可能的原因,但是由于死锁日志只记录发生阻塞的SQL,所以仅仅根据日志也很难以分析死锁的问题的根本原因,但是可以有一定的帮助。

怎么尽量避免死锁?

我们在平时的开发设计有没有一些准则可以帮助我们避免死锁发生?

  1. 合理的设计索引,区分度高的列放到组合索引前面,使业务 SQL 尽可能通过索引定位更少的行,减少锁竞争。

  2. 调整业务逻辑 SQL 执行顺序, 避免 update/delete 长时间持有锁的 SQL 在事务前面。

  3. 避免大事务,尽量将大事务拆成多个小事务来处理,小事务发生锁冲突的几率也更小。

  4. 以固定的顺序访问表和行。比如两个更新数据的事务,事务 A 更新数据的顺序为 1,2;事务 B 更新数据的顺序为 2,1。这样更可能会造成死锁。

  5. 在并发比较高的系统中,不要显式加锁,特别是是在事务里显式加锁。如 select … for update 语句,如果是在事务里(运行了 start transaction 或设置了autocommit 等于0),那么就会锁定所查找到的记录。

  6. 尽量按主键/索引去查找记录,范围查找增加了锁冲突的可能性。

  7. 降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁。

总结一下: 也就是在业务允许的情况下,尽量缩短一个事务持有锁的时间、减小锁的粒度以及锁的数量。

总结

本文讲解了MySQL中死锁发生的原因,以及如何通过日志排查死锁,最后给了一些平时开发过程中避免死锁的建议。虽然MySQL会自动解除死锁,但是这个死锁问题以后绝对会再次出现,一定要记住去排除业务SQL的执行逻辑,找到产生死锁的业务,然后调整业务SQL的执行顺序,这样才能从根源上避免死锁产生。

如果本文对你有帮助的话,请留下一个赞吧

MySQL死锁 预防分析解决死锁 ​本篇文章根据官网文档的例子,学习死锁是如何发生的,以及如何预防和解决死锁。 死锁发生的例子 MySQL的死锁检测 降低和处理死锁 阅读详情

相关推荐

MySQL死锁与死锁检测

MySQL中死锁是指两个或多个事务在互相等待对方释放资源,导致无法继续执行的情况。

u012002125的博客 1788

mysql 死锁详细分析(三)

mysql死锁详细分析

zht245648124的博客 3041

MySQL中的死锁:探究与解决之道

本文将深入探讨MySQL中的死锁问题,包括死锁的成因、检测方法、避免策略、解决方法以及优化策略与最佳实践。死锁是指在并发环境中,两个或多个事务相互等待对方释放资源而无法继续执行的情况。这种情况下,系统无法进一步进行,需要手动干预或自动重试。

博客 1918

中秋遇到mysql死锁怎么办

中秋放假期间遇见mysql死锁问题怎么办,莫慌莫慌,今天老万教你遇到了mysql死锁应该怎么办。

弹指天下 7047

MySql死锁怎么排查

排查死锁时,通过日志和工具分析根因是关键;预防死锁需要合理设计事务和 SQL;解决死锁则可以通过重试、调整操作顺序、分离事务和优化锁的范围等方式。根据具体场景选择合适的手段,才能有效避免和解决死锁问题。

u014109358的博客 5149

MySql--死锁

接着,事务B也尝试更新第一行记录,但是由于事务A还未提交,第一行记录被锁住。当发生死锁时,MySQL会自动选择其中一个事务作为死锁的牺牲者,回滚该事务,并释放锁定的资源,从而解除死锁。MySQL会检测到死锁的情况,并自动选择一个事务作为死锁的牺牲者,将其回滚以解决死锁问题。MySQL死锁是指多个事务同时持有不同的资源,并且互相请求对方的资源,导致无法继续进行下去的情况。重试机制:当捕捉到死锁错误时,可以在代码中添加重试机制,即重新执行被阻塞的事务,直到没有死锁发生为止。一、什么是mysql死锁?

宁zz的博客 1368

MySQL是怎么处理死锁的?

MySQL是怎么处理死锁的?

做点有意思的事情 738

Mysql锁机制简单了解一下

一 锁分类(按照锁的粒度分类) Mysql为了解决并发、数据安全的问题,使用了锁机制。 可以按照锁的粒度把数据库锁分为表级锁和行级锁。 表级锁: Mysql中锁定 粒度最大 的一种锁,对当前操作的整张表加锁,实现简单 ,资源消耗也比较少,加锁快,不会出现死锁 。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM和 InnoDB引擎都支持表级锁。 行级锁 Mysql中锁定 粒...

JavaGuide 4万+

Mysql锁机制之行锁、表锁、死锁

乐观锁用的最多的就是数据的版本记录来体现 version ,其实就是一个标识。 例如:update test set a=a-1 where id=100 and a> 0; 对应的version就是a字段,并不一定非得要求有一个字段叫做version,要求的是有这个字段,同时当满足这个条件的时候才会触发

点滴记忆,分享成长之路 4274

/lib//libclntsh.so: file format not recognized; treating as linker script

centos7.7+oracle19.3 建库过程报错:预检查都是通过的 /oracle/product/19.3.0/db_1/lib/libasmperl19.a -Wl,--no-whole-archive -lclntsh -lclntshcore -lasmclntsh19 -lhasgen19 -lskgxp19 -locr19 -lcell19 -lirc INFO: /usr/bin/ld:/home/app/oracle/product/19.3.0/db_1/li...

sqlora的专栏 9914

微信小程序后台定位与实时位置更新的实战指南

本文提供了微信小程序实现后台定位与实时位置更新的完整实战指南。针对小程序退到后台后位置更新中断的痛点,详细解析了基于`startLocationUpdateBackground`API的后台定位解决方案。内容涵盖从隐私协议配置、项目权限声明,到授权、启动、监听、停止的核心代码流程,并分享了真机调试、性能优化及权限引导等关键避坑经验,帮助开发者构建稳定可靠的后台位置服务。

weixin_29008055的博客 468

面试:什么是死锁,如何避免或解决死锁;MySQL中的死锁现象,MySQL死锁如何解决

面试:什么是死锁,死锁产生的四个必要条件,如何避免或解决死锁;数据库锁,锁分类,控制事务;MySQL中的死锁现象,MySQL死锁如何解决

qq_44700578的博客 1453

Kettle安装与使用

Pentaho Data Integration作为一个端对端的数据集成平台,可以对多种数据源进行抽取(Extraction)、加载(Loading)、数据落湖(Data Lake Injection)、对数据进行各种清洗(Cleasing)、转换(Transformation)、混合(Blending),并支持多维联机分析处理(OLAP)和数据挖掘(Data mining)。勺子(spoon.bat/spoon.sh):是一个图形化的界面,可以让我们用图形化的方式开发转换和作业。

jnrjian的博客 1万+

MySQL死锁检测机制

在高并发环境下,是数据库开发中无法回避的问题。本文将深入剖析 MySQL InnoDB 存储引擎是如何处理死锁的:它如何检测死锁?是否会自动处理?又是如何“挑选”牺牲者来终止?以及我们如何在业务开发中避免死锁的发生?

大西瓜的博客 787

文献阅读:SAR像素偏移的性能改进An Improvement of the Performance of SAR Offset Tracking Approach

像素偏移追踪POT文献阅读

weixin_56301271的博客 342

微信小程序导航栏滑动一定距离后固定到顶部

接上一篇文章的内容,通常在一个页面中部会有一个导航栏查看不同的内容,这篇文章旨在实现在页面下滑的过程中导航栏自动固定到顶部以便我们阅读过程中的切换。 下滑一段距离后自动固定到顶部 首先,思考这个功能应该是怎么实现的: 在页面下滑的过程中,我们希望系统应当能识别下滑了多少距离,当原本的导航栏逐渐被遮住以后(遮住意味着下滑了特定距离),触发这个功能,执行另一种样式,将导航栏固定在页面顶端,同时如果我们将页面往上滑,系统能识别到原来的导航栏能露出来了(即距离顶端的高度小于一个特定的值),这时候又执行最初的样式

Oblivision_Geek的博客 4031

【MySQL】MySQL中的死锁

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。 死锁是必然发生在多操作者(M>=2 个)情况下,争夺多个资源(N>=2 个,且N<=M)才会发生这种情况。很明显,单线程自然不会有死锁;单资源只会产生激烈竞争,也不会产生死锁。同时,死锁还有几个要求: 争夺资源的顺序不对,如果争夺资源的顺序是一样的,也不会产生死锁; 争夺者拿到资源不放手。 死锁学术化的定义 死锁的发

morris 1万+

红薯游客小眼睛接口分析与Python脚本实现

小眼睛接口与请求流程分析,使用Python实现小眼睛+1

吴秋霖的博客 2614

MySQL死锁了怎么办(死锁的产生及解决方案),死锁的案例,死锁的排查,死锁的解决,如何避免死锁的发生

死锁是指2+的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

weixin_44797327的博客 1万+

【数据分析】比较SparCC、Pearson和Spearman相关性估计方法在合成组学数据上的表现

【数据分析】比较SparCC、Pearson和Spearman相关性估计方法在合成组学数据上的表现

专注生信领域 659

最新Python爬虫实战(入门爬虫篇)——案例20:某股票数据采集(详细爬虫思路截图+抓包动图演示+完整爬虫代码+详细注释)

本次案例针对某股票行情网的静态HTML页面,实现了全市场股票数据的全自动化爬取,覆盖了从抓包分析、请求模拟、数据解析到数据存储的完整爬虫流程,非常适合入门学习者巩固基础,核心知识点和实现要点总结如下:首先是页面分析的核心逻辑,静态HTML页面的数据爬取,核心在于通过浏览器开发者工具,完成完整的抓包分析和标签结构定位。我们不需要像动态页面那样找隐藏的API接口,只需要确认数据在主文档的HTML源码中,然后通过元素选择器,精准找到每个字段对应的标签,总结出统一的标签结构规律,就能实现批量数据提取。

努力让自己发光,对的人才能迎着光而来 19万+

MySQL中的锁以及死锁问题

利用它的唯一性来保证订单表不会出现重复的订单,不过有一点不好的地方就是在我们插入一个已经存在的订单记录时就会抛出异常。:Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。,这样在备份数据库期间,不会因为数据的更新,而出现备份文件的数据与预期的不一样。,直到拥有间隙锁的那个事务提交为止(释放间隙锁的时刻),在此期间会生成一个。,表明有事务想在某个区间插入新记录,但是现在处于等待状态。:一个事务在插入一条记录的时候,需要判断插入位置。:锁定一个范围,但是不包含记录本身;

qq_70186387的博客 1697

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

mysql死锁介绍以及解决

众所周知,数据库的连接资源是很珍贵的,如果一个连接因为事务阻塞长时间不释放,那么后面新的请求要执行的sql也会排队等待,越积越多,最终会拖垮整个应用。一旦你的应用部署在微服务体系中而又没有做熔断处理,由于整个链路被阻断,那么就会引发雪崩效应,导致很严重的生产事故。

qq_37436172的博客 1万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

如何优化MySQL中的锁机制?如何避免死锁?

优化MySQL中的锁机制以及避免死锁是提高数据库并发处理能力和系统稳定性的关键。

长风破浪会有时的博客 768

MySQL死锁成因及解决方案

在 MySQL 的并发事务处理中,虽然完全避免死锁不现实,但可以通过优化设计和合理操作,大幅降低死锁发生的概率。在上面死锁图中的示例中,如果事务1和事务2按照相同的顺序获取锁,死锁就不会发生。死锁是数据库并发事务处理中常见的问题,通过合理的设计和优化,可以有效降低死锁发生的概率。通过这个命令,可以查看死锁的原因、涉及的事务、被锁住的行和死锁的图形化表现等。这种行为也由隐式锁实现。InnoDB 的隐式锁由存储引擎在后台完成,用户看不到这些锁的具体表现形式,通常它的加锁过程伴随事务语句的执行自动发生。

m0_53926113的博客 5713

MySQL 死锁

数据库的死锁是指在数据库事务处理过程中,两个或多个事务因互相等待对方持有的锁而无法继续执行的现象。这种情况下,事务会无限期地等待,直到外部干预才能恢复正常。

ZPJ优快云的博客 1231
上一篇: 想过为什么家里的IP是192.168开头的吗?
下一篇: 这样加密SpringBoot 配置文件,更加安全!
Java_LingFeng
博客等级 码龄4年 505粉丝 259原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值