在正式开始今天的讲解之前,我们先回顾一下死锁的相关知识
死锁是指两个或者两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而导致的一种阻塞的现象,如果没有外力,他们将一直等待下去。
就跟卡bug一样,比如说你去面试,面试官问你:MySQL为什么会死锁;你告诉面试官:你录用我我就告诉你,面试官说:你告诉我我就录用你,然后你两就一直这么你问我我问你,这就是死锁。
那么,什么时候会发生死锁呢?
这就不得不提死锁的四个必要条件:互斥、占有并等待、非抢占、循环等待
现在我们模拟一个死锁的场景,在此之前我们先创建一张团队表用于存储一个排球队的人员信息:
CREATE TABLE `team` ( `id` int NOT NULL AUTO_INCREMENT, `position_no` int DEFAULT NULL, `user_name` VARCHAR(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `index_position` (`position_no`) USING BTREE ) ENGINE=InnoDB ; 复制代码
并插入五行数据:
正在上传…重新上传取消
现如今球队招募一个二传手和一个副攻手,也就是position_no = 6 和 position_no = 7的人,但是在招募之前需要确认这个位置是否有人,球队的两个经理往表中插入数据的时候发生如下的事情,此时就会发生死锁的情况:
经理A(清水) | 经理B(谷地) |
---|---|
查询位置为6的人员是否存在 select * from team where position_no = 6 for update | |
查询位置为7的是否存在人员 select * from team where position_no = 7 for update | |
insert into team(position_no, user_name) values(6,研磨) | |
insert into team(position_no, user_name) values(7,列夫) |
首先解释一下为什么使用的是当前读,因为如果是快照读就会出现的情况为:两个经理都要插入位置为6的人员,并且查询的时候都发现位置存在,就都进行了插入,即:
经理A(清水) | 经理B(谷地) |
---|---|
查询位置为6的人员是否存在 select * from team where position_no = 6 for update | |
查询位置为7的是否存在人员 select * from team where position_no = 6 for update | |
insert into team(position_no, user_name) values(6,研磨) | |
insert into team(position_no, user_name) values(6,及川) |
此时就会发生两个人员都被加入进来了,出现了两个位置为6的记录,出现了幻读,因此在查询的时候需要加锁,也就是使用当前读
回到刚刚的场景,我们去实际环境试一下会得到的结果是:经理A插入位置为6的人员,经理B插入位置为7的人员的时候,这两句插入都阻塞了,也就是发生了死锁,在下面我们会分析为什么出现死锁:
其实有了昨天的知识储备,了解了查询的时候的加锁情况,我们其实不难分析出为什么会死锁:
select * from team where position_no = 6 for update语句属于非唯一索引的等值查询,会加上(6,+∞]的临键锁
select * from team where position_no = 7 for update语句属于非唯一索引的等值查询,会加上(7,+∞]的临键锁
两个事务都持有范围为(6,+∞]的临键锁,而接下来的插入操作会去获取插入意向锁,插入意向锁与临键锁互斥,因此获取插入意向锁需要对方的事务的临键锁释放,于是就出现了循环等待,也就是死锁
在数据库层面,MySQL给我们提供了两种策略来打破死锁:
在业务层面,我们在处理业务逻辑的时候,主动的去寻找死锁存在的可能性,从根源解决问题,并加以修正,比如如果是防止订单号重复,也就是防止查重,我们可以修改订单号的生成规则,以雪花算法或者Redis去生成订单号,或者说可以给订单号这个字段加上唯一的索引……
今天的文章只是带大家简单走了一遍MySQL的死锁情况,关于为什么会死锁,讲完昨天的文章,也就是对查询时的加锁情况的讲解,其实来分析这个死锁的情况并不是一件难事,最后也介绍了从数据库层面和业务层面如何去防止MySQL出现死锁的情况。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有