image.png
    范围查询和等值查询的加锁规则是不同的。
    举个例子,下面这两条查询语句,查询的结果虽然是一样的,但是加锁的范围是不一样的。
    select from t_test where id=8 for update;
    select
    from t_test where id>=8 and id<9 for update;

    做个实验就知道了。
    唯一索引范围查询 - 图2
    会话 1 加锁变化过程如下:

    1. 最开始要找的第一行是 id = 8,因此 next-key lock(4,8],但是由于 id 是唯一索引,且该记录是存在的,因此会退化成记录锁,也就是只会对 id = 8 这一行加锁;
    2. 由于是范围查找,就会继续往后找存在的记录,也就是会找到 id = 16 这一行停下来,然后加 next-key lock (8, 16],但由于 id = 16 不满足 id < 9,所以会退化成间隙锁,加锁范围变为 (8, 16)。

    所以,会话 1 这时候主键索引的锁是记录锁 id=8 和间隙锁(8, 16)。
    会话 2 由于往间隙锁里插入了 id = 9 的记录,所以会被锁住了,而 id = 8 是被加锁的,因此会话 3 的语句也会被阻塞。
    由于 id = 16 并没有加锁,所以会话 4 是可以正常被执行。