Mysql 死锁案例4-delete 相邻记录导致死锁

死锁复现 

CREATE TABLE `t` (`id` int(11) NOT NULL,`c` int(11) DEFAULT NULL,`d` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `c` (`c`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;/*Data for the table `t` */insert  into `t`(`id`,`c`,`d`) values (0,0,0),(5,5,5),(10,10,10),(15,15,15)
事务1事务2
T1

BEGIN;

DELETE FROM  t WHERE  id=4;

T2

BEGIN;

DELETE FROM  t WHERE  id=4;

T3INSERT INTO t VALUES(3, 3,3);(阻塞)
T4INSERT INTO t VALUES(3, 3,3);(死锁)

死锁分析
注意where条件的c是普通索引

  1. T1事务1加主键索引间隙锁(0,5)写锁成功,
  2. T2事务2加主键索引间隙锁(0,5)写锁成功
  3. T3事务1申请意向插入锁(0,5)与事务2间隙锁(0,5)冲突阻塞
  4. T3事务2申请意向插入锁(0,5)与事务1间隙锁(0,5)冲突阻塞,循环等待死锁

这里其实也是间隙锁和意向插入锁冲突死锁,delete与update加锁逻辑差不多。参考:

Mysql 死锁案例2-间隙锁与意向插入锁冲突

查看锁信息 SHOW ENGINE INNODB STATUS 

------------------------
LATEST DETECTED DEADLOCK
------------------------
2024-03-13 16:47:14 0x1ed8
*** (1) TRANSACTION:
TRANSACTION 488371, ACTIVE 63 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 6, OS thread handle 2368, query id 2676 localhost ::1 root update
INSERT INTO t VALUES(3, 3,3)
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 638 page no 3 n bits 80 index PRIMARY of table `test`.`t` trx id 488371 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 00: len 4; hex 80000005; asc     ;;1: len 6; hex 000000076d2c; asc     m,;;2: len 7; hex 69000001ba0495; asc i      ;;3: len 4; hex 80000005; asc     ;;4: len 4; hex 80000000; asc     ;;*** (2) TRANSACTION:
TRANSACTION 488372, ACTIVE 51 sec inserting
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s)
MySQL thread id 20, OS thread handle 7896, query id 2681 localhost ::1 root update
INSERT INTO t VALUES(3, 3,3)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 638 page no 3 n bits 80 index PRIMARY of table `test`.`t` trx id 488372 lock_mode X locks gap before rec
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 00: len 4; hex 80000005; asc     ;;1: len 6; hex 000000076d2c; asc     m,;;2: len 7; hex 69000001ba0495; asc i      ;;3: len 4; hex 80000005; asc     ;;4: len 4; hex 80000000; asc     ;;*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 638 page no 3 n bits 80 index PRIMARY of table `test`.`t` trx id 488372 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 00: len 4; hex 80000005; asc     ;;1: len 6; hex 000000076d2c; asc     m,;;2: len 7; hex 69000001ba0495; asc i      ;;3: len 4; hex 80000005; asc     ;;4: len 4; hex 80000000; asc     ;;*** WE ROLL BACK TRANSACTION (2)
------------
TRANSACTIONS

where语句等值匹配的delete语句加锁逻辑分主键索引和唯一索引和普通索引,规则参考:

MySQL行锁加锁规则之等值查询

普通索引删除的加锁案例:

DELETE FROM  t WHERE  c=5;
---TRANSACTION 488378, ACTIVE 6 sec
4 lock struct(s), heap size 1136, 3 row lock(s), undo log entries 1
MySQL thread id 6, OS thread handle 2368, query id 2744 localhost ::1 root
TABLE LOCK table `test`.`t` trx id 488378 lock mode IX
RECORD LOCKS space id 638 page no 4 n bits 80 index c of table `test`.`t` trx id 488378 lock_mode X
Record lock, heap no 3 PHYSICAL RECORD: n_fields 2; compact format; info bits 320: len 4; hex 80000005; asc     ;;1: len 4; hex 80000005; asc     ;;RECORD LOCKS space id 638 page no 3 n bits 80 index PRIMARY of table `test`.`t` trx id 488378 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 320: len 4; hex 80000005; asc     ;;1: len 6; hex 0000000773ba; asc     s ;;2: len 7; hex 25000001392ce4; asc %   9, ;;3: len 4; hex 80000005; asc     ;;4: len 4; hex 80000000; asc     ;;RECORD LOCKS space id 638 page no 4 n bits 80 index c of table `test`.`t` trx id 488378 lock_mode X locks gap before rec
Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 00: len 4; hex 8000000a; asc     ;;1: len 4; hex 8000000a; asc     ;;

加了3把锁,索引c间隙锁(5,10),主键索引记录锁id=5,索引c临键锁(0,5]

有兴趣的可以看下这篇文章:MySQL delete 相邻记录导致死锁

 死锁日志

------------------------
LATEST DETECTED DEADLOCK
------------------------
2017-09-09 22:34:13 7f78eab82700
*** (1) TRANSACTION:
TRANSACTION 462308399, ACTIVE 33 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 3525577, OS thread handle 0x7f896cc4b700, query id 780039657 localhost root updating
delete from ty where a=5
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308399 lock_mode X waiting
*** (2) TRANSACTION:
TRANSACTION 462308398, ACTIVE 61 sec inserting, thread declared inside InnoDB 5000
mysql tables in use 1, locked 1
5 lock struct(s), heap size 1184, 4 row lock(s), undo log entries 2
MySQL thread id 3525490, OS thread handle 0x7f78eab82700, query id 780039714 localhost root update
insert into ty(a,b) values(2,10)
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 219 page no 4 n bits 72 index `idxa` of table `test`.`ty` trx id 462308398 lock_mode X locks gap before rec insert intention waiting
*** WE ROLL BACK TRANSACTION (1)

分析死锁日志 

首先要理解的是 对同一个字段申请加锁是需要排队.  其次表ty中索引idxa为非唯一普通索引,我们根据事务执行的时间顺序来解释,这样比较好理解(MySQL 5.6 事务隔离级别为RR)。

  •  a. 根据死锁日志显示 事务2 也即sess1执行的事务,根据 HOLDS THE LOCK(S)显示    sess1 先执行 delete from ty where a=5 ,该事务持有索引a=5 的行锁lock_mode X ,因为是RR隔离级别,所以sess1 还持有两个gap锁[1,2]-[2,5], [2,5]-[3,6] 。
  • b. 事务1的日志也即sess2执行的事务,申请对 a=5 加锁,一个rec lock 和两个gap锁,因为sess1中delete还没释放,故sess2的事务1等待sess1的事务2释放a=5的锁资源。
  • c. 然后根据WAITING FOR THIS LOCK TO BE GRANTED,提示事务2 insert语句正在等待 lock_mode X locks gap before rec insert intention waiting, 因为insert语句 [4,2] 介于gap锁[1,2]-[2,5]之间,所以有了提示 "lock_mode X locks gap",insert语句必须等待前面 sess2中delete 获取锁并且释放锁。于是,sess2(delete) 等待sess1(delete) ,sess1(insert)等待sess2(delete),循环等待,造成死锁。 问题 如果sess1 执行 insert into ty(a,b) values(5,10); sess2会遇到死锁吗?

因为作者没贴具体的表结构和表数据,所以没看懂这个死锁, 也没复现出来(Mysql 5.7.12 事务隔离级别为RR)。

按对锁的理解,事务1事务2执行的第一个delete语句都能成功,只有一种可能,就是数据库没a=5这条记录,间隙锁与间隙锁不冲突。按这个设定执行,那么事务2的第二个delete语句就不会阻塞,所以也就不存在死锁。怎么复现这个死锁????

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/537265.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

easyrecovery破解版百度云(含Mac/Win版)以及EasyRecovery可以恢复哪些设备

软件介绍 当不小心将回收站的文件删除了怎么办?想找回但是不知道怎么找回需要的数据文件?别担心今天小编就为大家介绍一款非常专业的电脑数据文件恢复工具,easyrecovery14是由Ontrack专为电脑用户推出的一款专业的数据恢复软件&…

Go——数组

Golang Array和以往认知的数组有很大的。 数组是同一种数据类型的固定长度的序列。数组定义:var a[len] int,比如:var a [5]int,数组长度必须是常量,且类型的组成部分。一旦定义,长度不能变。长度是数组类…

ip广播智慧工地广播喊话号角 IP网络号角在塔吊中应用 通过寻呼话筒预案广播

ip广播智慧工地广播喊话号角 IP网络号角在塔吊中应用 通过寻呼话筒预案广播 SV-704XT是深圳锐科达电子有限公司的一款壁挂式网络有源号角,具有10/100M以太网接口,可将网络音源通过自带的功放和号角喇叭输出播放,可达到功率50W。SV-704XT内置有…

机器学习模型—随机森林

机器学习模型—随机森林 随机森林(Random Forest)是由斯坦福大学教授Tin Kam Ho在1995年提出的一种组合学习模型。它可以用于分类和回归任务,并在很多现实世界的问题中表现出优异的性能。 随机森林本质上是通过构建多颗决策树,然后将单个树的预测结果进行组合,从而获得更加准…

Cesium--基于材质旋转图片

材质部分的代码如下 // 自定义材质const customMaterial new Cesium.Material({translucent: true,fabric: {uniforms: {image:circle_img,speed:30.0,},source: czm_material czm_getMaterial(czm_materialInput materialInput){czm_material material czm_getDefaultMateri…

【软考高项】四、信息化发展之数字中国

1、数字经济 定义:从本质上看,数字经济是一种新的技术经济范式,它建立在信息与通信技术的重大突破的基础上,以数字技术与实体经济融合驱动的产业梯次转型和经济创新发展的主引擎,在基础设施、生产要素、产业结构和治理…

opencv-python连通域分割connectedComponents

文章目录 连通域简介绘图代码函数说明 连通域简介 所谓连通域,即Connected Component,是一组彼此相连的像素点的集合,这些像素点彼此之间可以假设一条互相链接的路径,路径上所有像素的灰度一致,或者符合某个特定的条件…

HCIP —— BGP 路径属性 (上)

目录 BGP 路径属性 1.优选Preferred-Value属性值最大的路由 2.优选Local-preference 属性数值大的路由 3.本地始发的BGP路由优先于其他对等体处学习到的路由。 4..优选AS_PATH属性值最短的路由 BGP 路径属性 BGP的路由选路是存在优选规则的,下图为华为官网提供…

腾讯云服务器“地域”这么选就对了!

腾讯云服务器地域怎么选择?不同地域之间有什么区别?腾讯云哪个地域好?地域选择遵循就近原则,访客距离地域越近网络延迟越低,速度越快。腾讯云百科txybk.com告诉大家关于地域的选择还有很多因素,地域节点选择…

【django framework】ModelSerializer+GenericAPIView,如何在提交前修改某些字段值

【django framework】ModelSerializerGenericAPIView,如何在提交前修改某些字段值 我们经常会遇到下面这种情况: 序列化器用的是ModelSerializer,写视图的时候继承的是generics.CreateAPIView。现在我想在正式提交到数据库(perform_create)之…

Python算法(列表排序)

一。冒泡排序: 列表每两个相邻的数,如果前面比后面大,则交换这两个数 一趟排序完成后,则无序区减少一个数,有序区增加一个数 时间复杂度:O(n*n) 优化后:已经排序好后立马停止,加快…

浅谈HTTP 和 HTTPS (中间人问题)

前言 由于之前的文章已经介绍过了HTTP , 这篇文章介绍 HTTPS 相对于 HTTP 做出的改进 开门见山: HTTPS 是对 HTTP 的加强版 主要是对一些关键信息 进行了加密 一.两种加密方式 1.对称加密 公钥 明文 密文 密文 公钥 明文 2.非对称加密 举个例子就好比 小区邮箱 提供一…