谁还没阅历过死锁呢

  • 电脑网络维修
  • 2024-11-15

大家好,我是小林。

说个很早之前自己遇到过数据库死锁疑问。

有个业务关键逻辑就是新增订单、修正订单、查问订单等操作。而后由于订单是不能重复的,所以事先在新增订单的时刻做了幂等性校验,做法就是在新增订单记载之前,先经过select ... for update 语句查问订单能否存在,假设不存在才拔出订单记载。

而正是由于这样的操作,当业务量很大的时刻,就或者会出现死锁。

接上去跟大家聊下为什么会出现死锁,以及怎样防止死锁。

死锁的出现

本次案例经常使用存储引擎 Innodb,隔离级别无法重复读(RR)。

接上去,我用实战的形式来带大家看看死锁是怎样出现的。

我建了一张订单表,其中 id 字段为主键索引,order_no 字段个别索引,也就是非惟一索引:

`id``order_no``create_date`datetime

而后,先 t_order 表里如今曾经有了 6 条记载:

假定这时有两事务,一个事务要拔出订单 1007 ,另外一个事务要拔出订单1008,由于须要对订单做幂等性校验,所以两个事务先要查问该订单能否存在,不存在才拔出记载,环节如下:

可以看到,两个事务都堕入了等候形态(前提没有关上死锁检测),也就是出现了死锁,由于都在相互等候对方监禁锁。

这里在查问记载能否存在的时刻,经常使用了 select ... for update语句,目标为了防止事务口头的环节中,有其余事务拔出了记载,而出现幻读的疑问。

假设没有经常使用 select ... for update 语句,而经常使用了单纯的 select语句,假设是两个订单号一样的恳求同时出去,就会出现两个重复的订单,有或者出现幻读,如下图:

为什么会发生死锁?

可重复读隔离级别下,是存在幻读的疑问。

Innodb 引擎为了处置「可重复读」隔离级别下的幻读疑问,就引出了 next-key 锁,它是记载锁和间隙锁的组合。

个别的 select 语句是不会对记载加锁的,由于它是经过 MVCC 的机制成功的快照读,假设要在查问时对记载加行锁,可以经常使用上方这两个形式:

//对读取的记载加共享锁//对读取的记载加排他锁

行锁的监禁机遇是在事务提交(commit)后,锁就会被监禁,并不是一条语句口头完就监禁行锁。

比如,上方事务 A 查问语句会锁住(2, +∞]范畴的记载,然前时期假设有其余事务在这个锁住的范畴拔出数据就会被阻塞。

next-key 锁的加锁规定其实挺复杂的,在一些场景下会退步成记载锁或间隙锁,我之前也写一篇加锁规定,具体可以看这篇「我做了一天的试验!」

须要留意的是,next-key lock 锁的是索引,而不是数据自身,所以假设 update 语句的 where条件没有用到索引列,那么就会全表扫描,在一行行扫描的环节中,不只给行加上了行锁,还给行两头的空隙也加上了间隙锁,相当于锁住整个表,而后直到事务完结才会监禁锁。

所以在线上千万不要口头没有带索引条件的 update语句,不然会形成业务停滞,我有个读者就由于干了这个事情,而后被老板教育了一波,具体可以看这篇「完蛋,公司被一条 update 语句干趴了!」

回到前面死锁的例子,在口头上方这条语句的时刻:

由于 order_no 不是惟一索引,所以行锁的类型是间隙锁,于是间隙锁的范畴是(1006, +∞)。那么,当事务 B 往间隙锁里拔出 id = 1008的记载就会被锁住。

由于当咱们口头以下拔出语句时,会在拔出间隙上再次失掉拔出动向锁。

拔出动向锁与间隙锁是抵触的,所以当其它事务持有该间隙的间隙锁时,须要等候其它事务监禁间隙锁之后,才干失掉到拔出动向锁。而间隙锁与间隙锁之间是兼容的,所以所以两个事务中select ... for update 语句并不会相互影响。

案例中的事务 A 和事务 B 在口头完后 select ... for update语句后都持有范畴为(1006,+∞)的间隙锁,而接上去的拔出操作为了失掉到拔出动向锁,都在等候对方事务的间隙锁监禁,于是就形成了循环等候,造成死锁。

如何防止死锁?

死锁的四个必要条件:互斥、占有且等候、无法侵占用、循环等候。只需系统出现死锁,这些条件肯定成立,然而只需破坏恣意一个条件就死锁就不会成立。

在数据库层面,有两种战略经过「冲破循环等候条件」来解除死锁形态:

当出现超时后,就出现上方这个揭示:

当检测到死锁后,就会出现上方这个揭示:

上方这个两种战略是「当有死锁出现时」的防止形式。

咱们可以回归业务的角度来预防死锁,对订单做幂等性校验的目标是为了保障不会出现重复的订单,那咱们可以间接将 order_no字段设置为惟一索引列,应用它的惟一上去保障订单表不会出现重复的订单,不过有一点不好的中央就是在咱们拔出一个曾经存在的订单记载时就会抛出意外。

  • 关注微信

本网站的文章部分内容可能来源于网络和网友发布,仅供大家学习与参考,如有侵权,请联系站长进行删除处理,不代表本网站立场,转载联系作者并注明出处:https://duobeib.com/diannaowangluoweixiu/9236.html

猜你喜欢

热门标签

洗手盆如何疏浚梗塞 洗手盆为何梗塞 iPhone提价霸占4G市场等于原价8折 明码箱怎样设置明码锁 苏泊尔电饭锅保修多久 长城画龙G8253YN彩电输入指令画面变暗疑问检修 彩星彩电解除童锁方法大全 三星笔记本培修点上海 液晶显示器花屏培修视频 燃气热水器不热水要素 热水器不上班经常出现3种处置方法 无氟空调跟有氟空调有什么区别 norltz燃气热水器售后电话 大连站和大连北站哪个离周水子机场近 热水器显示屏亮显示温度不加热 铁猫牌保险箱高效开锁技巧 科技助力安保无忧 创维8R80 汽修 a1265和c3182是什么管 为什么电热水器不能即热 标致空调为什么不冷 神舟培修笔记本培修 dell1420内存更新 青岛自来水公司培修热线电话 包头美的洗衣机全国各市售后服务预定热线号码2024年修缮点降级 创维42k08rd更新 空调为什么运转异响 热水器为何会漏水 该如何处置 什么是可以自己处置的 重庆华帝售后电话 波轮洗衣机荡涤价格 鼎新热水器 留意了!不是水平疑问! 马桶产生了这5个现象 方便 极速 邢台空调移机电话上门服务 扬子空调缺点代码e4是什么疑问 宏基4736zG可以装置W11吗 奥克斯空调培修官方 为什么突然空调滴水很多 乐视s40air刷机包 未联络视的提高方向 官网培修 格力空调售后电话 皇明太阳能电话 看尚X55液晶电视进入工厂形式和软件更新方法 燃气热水器缺点代码

热门资讯

关注我们

微信公众号