读mysql45讲-netx-key lock相关

加锁规则

  1. 加锁的基本单位是next-key lock,是前开后闭区间。
  2. 查找过程中访问到的对象才会被加锁。
  3. 索引上的等值查询,给唯一索引加锁的时候,next-key lock退化为行锁
  4. 索引上的等值查询,向右遍历时且最后一个值不符合等值条件的时候,next-key lock退化为间隙锁
  5. 唯一索引的范围查询会访问到不满足条件的第一个值为止。

建表语句:

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;

初始化数据:

insert into t values(0,0,0),(5,5,5), (10,10,10),(15,15,15),(20,20,20),(25,25,25);
唯一索引等值查询间隙锁

等值查询间隙锁

sessionA加锁分析:
加上next-key lock锁,锁的是(5,10];
虽然是给唯一索引加锁,但是因为id=7不存在,所以不会退化为行锁;
依据原则4,索引上的等值查询,向右遍历直到最后一个不满足条件的时候退化为间隙锁,所以id的锁范围变为(5,10)
sessionB被锁住,sessionC因为id=10不在区间内,所以不会被锁住

非唯一索引等值查询间隙锁

非唯一索引等值查询间隙锁

分析一下sessionA的加锁:
sessionA给c=5这一行加上读锁,next-key lock给索引c加锁范围是(5,10],不是唯一索引所以不会退化为行锁,等值查询最后一个值不满足条件,退化为间隙锁,索引c的next-key lock锁范围变为(5,10),但是因为select中的字段是id,所以是覆盖索引,不会访问到主键,因此不会对主键的[5,10)加上锁;sessionB中id=5可以正常执行,sessionC中的字段c在区间中,所以阻塞。

需要注意,在这个例子中,lock in share mode只锁覆盖索引,但是如果是for update就不一样 了。 执行 for update时,系统会认为你接下来要更新数据,因此会顺便给主键索引上满足条件的行加上行锁。

如果要在lock in share mode 的基础上防止通过id更新数据的话,可以在select字段中加上一个没有索引的字段,这样就不会用到覆盖索引了。

唯一索引范围查询

唯一索引范围查询

sessionA中找到第一个id=10的行,原本应该是(5,10],因为这个时候还是走的id=10等值查询,所以根据原则3,因为id是唯一索引,所以退化为行锁,也就给id=10加了行锁;
开始走范围查询,依据原则5,继续找下一个不满足条件的值,(初始化数据)在数据库中【第一个】不满足条件的值就是(15,15,15);
所以next-key lock给id加的锁范围是(10,15]。
sessionB中插入的(8,8,8)不在区间内,可以执行;但是(13,13,13)在区间内,执行被阻塞;sessionC中id=15是在区间内的,被阻塞;

但是我实际操作的时候发现sessionC的sql是可以执行的,有点费解。不知道是不是版本原因。

非唯一索引范围查询

非唯一索引范围查询

这次session A用字段c来判断,加锁规则跟案例三唯一的不同是:在第一次用c=10定位记录的时 候,索引c上加了(5,10]这个next-key lock后,由于索引c是非唯一索引,没有优化规则,也就是 说不会蜕变为行锁,因此最终sesion A加的锁是,索引c上的(5,10] 和(10,15] 这两个next-key lock。

上面是直接复制的,因为不太理解其中说的 “在第一次用c=10定位记录的时 候,索引c上加了(5,10]”,为啥加的是(5,10]不是(10,15];
而且(10,15]这个区间也没能理解,c >10和c < 11就应该是(10,15)。 这个地方也给困住了。

唯一索引范围锁

唯一索引范围锁

sessionA中先给id=15等值查询加锁,再退化为行锁;再做范围查询锁,next-key lock给id加锁范围应该是(10,15},再依据原则5,唯一索引范围查询会一直访问到第一个不满条件的值,也就是id=20;所以实际加的锁范围是(10,20]。

但是我实际操作的时候发现,sessionB并不会阻塞,而且sessionC也没有被阻塞,我试了下给id=15做更新,再想插入(14,14,14),或者插入(11,11,11),都被阻塞了,更新 id=10是可以的所以实际锁的范围是(10,15]。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值