加锁规则

2021-07-23 14:28:42 浏览数 (1)

加锁规则

间隙锁只有在可重复读的隔离级别下有效。

1. 两个原则

  • 加锁的单位是 next-key lock,这个区间是前开后闭。
  • 查找过程中访问的对象才会加锁。

2. 两个优化

  • 在索引上的等值查询(where ... = ...),如果加锁的对象是唯一索引,则next-key lock的将会退化为行锁。
  • 在索引上的等值查询,向右遍历的时候,如果最后一个值不满足条件的话,则next-key lock 会退化,变成间隙锁(前开后开区间)。

3. 一个Bug

唯一索引上的范围查询,会访问到第一个不满足条件的数据为止。

4. 举个例子

代码语言:javascript复制
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);

4.1 next-key 退化为行锁

  • session A 查找id=10的时候,本来的加锁范围是(0,10],根据原则1退化为行锁加锁范围变成行锁id=10。
  • session A向后查找的过程中的间隙锁为(10,15]
  • 综合来看sessionA的加锁范围为[10,15]
  • 因此 sessionB的insert into t values (8,8,8)不会锁住,而(13,13,13)会被锁住。

4.2 next-key 退化为间隙锁

  • session A 本来的加锁范围是(5,10]
  • 但是id=10是最后一个值,且不满足条件
  • session A的加锁范围变成了(5,10), 所以session B 被阻塞,而session C没有阻塞。

4.3 一个bug

  • session A锁住的范围其实是(10,20],因为唯一索引上的范围查询,会访问到第一个不满足条件的数据为止。
  • 因此session B 和 session C会被锁住。
  • 但是正确锁的范围是(10,15]

0 人点赞