首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

瞎回答一个粉丝的死锁问题!

作者:孤独烟

引言

刚起床,本来想去看看电视,结果手抖看到了某个粉丝的留言,于是有了此文。本问题出自某粉丝给我的留言,如下图所示

为啥说是瞎回答呢?

没贴死锁日志

没具体过程

所以,我就靠经验来猜测一下!

正文

先说一个东西

这个语句大家都知道是什么意思了,但是你不要以为只有A表加锁,B表也是加锁的。而且加锁方法还是有讲究的。

老规矩假设B表结构如下,pId为主键,name上无索引

按主键插入

把该粉丝的SQL简化一下,变成

这里虽然是in语句,但是字段为主键。因此,此时索引是会生效的,而且是会逐步锁pId =1,2,7的聚簇索引。也就是说,你可以这么理解,mysql按如下顺序执行的

因此是逐步锁pId =1,2,7的聚簇索引。

说一个特殊情况,如果你执行的是

注意了pId = 8 这一列,在B表是不存在。那么此时存在间隙锁,锁住的是(7,11)这个间隙。

考虑到在这篇文章里要想将insert的加锁机制讲清楚篇幅太小,改天有时间细说。这里大家先这么记

会在索引为pId=13位置加上锁,并在(11,+∞)的位置加上插入意向锁。插入意向锁、间隙锁和行锁的兼容性如下

表注:横向是已经持有的锁,纵向是正在请求的锁。

好了。。现在可以重现死锁的场景了。如下图所示

如图所示

(1) Session 1 在(11,+∞)的位置加上插入意向锁,并获得pId=13记录锁。

(2) Session 2 意图获得(13,+∞)的间隙锁,根据上方的兼容性表。此时存在插入意向锁,因此间隙锁可以获得。

(3) Session 1 意图获得(14,+∞)的插入意向锁,根据上方的兼容性表。此时存在间隙锁,因此无法获得插入意向锁,等待Session2释放锁

(4) Session 2 又想获得得pId=13记录锁,因此等待Session 1 释放锁。

于是,死锁形成!

注意了,因为这里都是我的猜测。我假设执行的SQL是

也就是说里头的元素是无规律的。为什么呢,如果Session 2执行的SQL是这样递增的,永远无法请求Session 1所获得的锁。所以,我后台询问了一下他

证实了我的猜测!

如何解决

so easy!把隔离级别改成RC就行!RR隔离级别下insert A select B where B.COL=**,innodb层会对B表满足条件的数据进行加锁,但是RC模式下B表记录不会加任何innodb层的锁

总结

嗯,希望我说的该粉丝能懂吧!

●编号464,输入编号直达本文

●输入m获取文章目录

推荐↓↓↓

运维

更多推荐《25个技术类微信公众号》

涵盖:程序人生、算法与数据结构、黑客技术与网络安全、大数据技术、前端开发、Java、Python、Web开发、安卓开发、iOS开发、C/C++、.NET、Linux、数据库、运维等。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181205B0N36S00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券