select * from t5 where id>=10 and id<11 for update;按顺序执行事务会话A、B、C,如下:
文章插图
执行结果如下:

文章插图
发现事务会话B中,插入12,即insert into t5 values(12,12,12);时,阻塞了,而插入6,insert into t5 values(6,6,6);却可以顺利执行 。同时事务C中,Update t5 set d=d+1 where id =15;也会阻塞,为什么呢?
事务会话A执行时,要找到第一个id=10的行:
- 根据加锁原则1:加锁单位是next-key lock,因此会加上next-key lock(5,10] 。
- 又因为id是主键,也就是唯一值,因此根据优化1:索引上的等值查询,给唯一索引加锁时,next-key lock退化为行锁(Record lock) 。所以只加了id=10这个行锁 。
- 范围查找就往后继续找,找到id=15这一行停下来,因此还需要加next-key lock(10,15] 。
4.4 案例四:非唯一索引范围锁如果是普通索引,范围查询又加什么锁呢?按顺序执行事务会话A、B、C,如下:

文章插图
执行结果如下:

文章插图
发现事务会话B和事务会话C的执行SQL都被阻塞了 。
这是因为,事务会话A执行时,要找到第一个c=10的行:
- 根据加锁原则1:加锁单位是next-key lock,因此会加上next-key lock(5,10] 。
因此事务B和事务C插入的insert into t5 values(6,6,6);和Update t5 set d=d+1 where c =15; 都会阻塞 。
4.5 案例五:唯一索引范围锁 bug前面四种方案中,加锁的两个原则和两个优化都已经用上啦,那个唯一索引范围bug是如何触发的呢?
按顺序执行事务会话A、B、C,如下:

文章插图
执行结果如下:

文章插图
发现事务B的更新语句Update t5 set d=d+1 where id =20; 和事务Cinsert into t5 values(18,18,18);的插入语句均已阻塞了 。
这是因为,事务会话A执行时,要找到第一个id=15的行,根据加锁原则1:加锁单位是next-key lock,因此会加上next-key lock(10,15] 。因为id是主键,即唯一的,因此循环判断到 id=15 这一行就应该停止了 。但是实现上,InnoDB 会往前扫描到第一个不满足条件的行为止,直到扫描到id=20 。而且由于这是个范围扫描,因此索引id上的(15,20]这个 next-key lock 也会被锁上 。
所以,事务B要更新 id=20 这一行时,会阻塞锁住 。同样地事务会话C要插入id=16的一行,也会被锁住 。
4.6 案例六:普通索引上存在"等值"的例子如果查询条件列是普通索引,且存在相等的值,加锁又是怎样的呢?
在原来t5表的数据基础上,插入:
insert into t5 values(28,10,66);则c索引树如下:
文章插图
c索引值有相等的,但是它们对应的主键是有间隙的 。比如(c=10,id=10)和(c=10,id=28)之间 。
我们来看个例子,按顺序执行事务会话A、B、C,如下:

文章插图
执行结果如下:
推荐阅读
- C语言入门算法丨冒泡排序算法详解!绝不摆烂
- 适合中国家庭的国产两厢推荐
- 如何把红茶泡好喝,咖啡红茶怎么泡
- 职业教育|职业教育想要振兴,需要改变两大关键因素
- 滇红茶耐泡,凤庆滇红茶泡法
- 卧室有两个窗户对风水有利吗?
- 卧室有两个门对我们有什么影响
- 两个动作看透你 准确率达99%!
- Windows操作系统|Win11大更新就绪:微软详解重要新功能 CPU效率暴增、全新任务管理器
- 脂肪怎么排出,教你两招懒人方法
