谈谈你对间隙锁的理解

tech2022-12-07  104

文章目录

间隙锁简介原则通过案例解释上面的原则数据介绍案例案例1:间隙锁简单案例案例2:间隙锁死锁问题案例3:等值查询--唯一索引案例4:等值查询--普通索引

间隙锁

简介

间隙锁是对数据库表一定范围上的加锁,它能和行锁组成next-key lock解决在可重复读事务隔离级别下产生的幻读问题。幻读就是一个事务在进行范围查询的时候,前后查询的结果不一样。

原则

来记录下MySQL在可重复读事务隔离级别下加锁的规则:

加锁的基本单位是next-key lock,它是前开后闭的原则。查询过程中访问的对象会增加锁索引上的等值查询–给唯一索引加锁的时候,next-key lock会升级为行锁索引上的等值查询–向右遍历时,最后一个值不满足查询要求的话,会将next-key lock退化为间隙锁唯一索引在范围查询时会访问到不满足条件的第一个值为止

通过案例解释上面的原则

先声明一下,下面的这些案例都是基于可重复读事务隔离级别的

数据介绍

假设现在我有几条数据:

步骤id(唯一索引)c(普通索引)d(无索引)1111255531010104151515

以上数据为了解决幻读的问题,更新的时候,不只是对上述的每行数据都加行锁,并且对于中间的取值范围也加了锁,这个锁就是我们所说的间隙锁。这样以来,行锁+间隙锁组成next-key lock,这个锁的信息就是:(-°,1],(1,5],(5,10],(10,15],(15,+supernum],(其中,supernum是MySQL数据库维护的最大的值,来保证next-key lock是左开右闭的原则)

案例

案例1:间隙锁简单案例

步骤事务A事务B1begin;select * from table where id = 3 for update2-insert into tabble value(4,4,4) block;3commit;-

这个就是一个简单的案例,我们来分析下他的流程:

当有上面这两个事务时,事务A的操作会对数据库增加一个(1,5]范围的锁,这时候事务B是不能进行插入数据的,处于阻塞状态

案例2:间隙锁死锁问题

步骤事务A事务B1begin;select * from table where id = 3 for update2-begin;select * from table where id = 4 for update3-insert into table value(2,2,2) block;3nsert into table value(2,2,2) block;-

不同于写锁是互斥的,间隙锁不是互斥的,两个事务都能获取到这个间隙锁,但是获得这个间隙锁之后,是不允许其他事务对这个间隙锁进行DDL操作的,所以两者就进入到死锁状态

案例3:等值查询–唯一索引

步骤事务A事务B事务C1begin; update table set d=d+1 where id = 7--2-insert into table value(8,8,8)block;-3--update table set d=d+1 where id=10

1、先来看看MySQL会给数据库生成什么范围的锁:(5,10] 2、我们根据上面的原则四,我们看到这个范围最后一个值10与我们要查的id=7不相等,就会将这个next-key lock退化为间隙锁(5,10); 3、所以就可以解释事务B进行的插入操作是阻塞的,而事务C的操作是不阻塞的了。

案例4:等值查询–普通索引

步骤事务A事务B事务C1begin; select id from table where c=5 lock in share mode--2-update table set d=d+1 where id=5-3--insert into table values(7,7,7)block;

1、先来看看MySQL会给数据库生成什么范围的锁:(0,5],(5,10] 2、由于查询是等值查询,并且最后一个值不满足查询要求,故退化为间隙锁(5,10) 3、事务B能正常执行不阻塞的原因就是,事务A走的是覆盖索引并没有对主键索引加锁,所以B能正常执行 4、事务C插入的信息是7,在(5,10)之间,故会阻塞。

最新回复(0)