mysql可重复读隔离级别加锁分析

在MySQL可重复读隔离级别下,更新不存在数据可能导致插入操作阻塞。由于二阶段锁协议,未结束的事务持有锁。分析显示,更新时锁定的是id索引的next-key lock,造成插入意向锁与间隙锁冲突。解决方案包括更改隔离级别为读提交或缩短事务执行时间以减少锁等待。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

myql可重复读隔离级别下可能会导致插入阻塞,问题复现如下

表中有3列都是int类型 

其索引情况如下:

id为主索引,c,d为普通索引

现在开始制作问题:

在这里我分别开启两个事务:第一个事务中执行一个update 语句更新一个不存在的数据,这里没有执行commit也就事务未结束,根据二阶段锁协议,锁的释放是在事务结束后。

现在另一个窗口中执行insert操作,这里它一直在阻塞中。等待上面事务commit或者超时

过一段事务出现下面提示,出现无法获取锁的错误

 

想看详细信息,可以执行show engine innodb  status \G;

上面告诉我们插入意向等待获取主键id上面的锁

 

原因分析:

1.锁是加在索引上面的,上面更新时用到的锁是id

2.根据可重复读加载锁规则为next-key lock,上面id的锁 是 (0,1],(1,5],(5,15],(15,20],(20,25],(25,supernum]

最后的sumpernum是很大的数字可以认为是无穷大

 

我们执行执行 update t_test set c = 100 where id =100;由于id在最后一个范围中所以它持有的间隙锁是(25,supernum),间隙锁和间隙锁不会有冲突,但和插入意向锁存在冲突。所以上面会阻塞住

 

如何解决:

由于间隙锁只存在可重复读隔离级别下,可以修改数据库的隔离级别为读提交

第二种就是减少其锁的时间,可以通过减少事务执行时间,减少锁等待时间

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值