MySQL 在 REPEATABLE READ 隔离级别下是可以解决幻读问题的,解决方案有两种,可以使用 MVCC 方案解决,也可以采用加锁方案解决。但是在使用加锁方案解决时有问题,就是事务在第一次执行读取操作时,那些幻影记录尚不存在,我们无法给这些幻影记录加上记录锁。InnoDB 提出了一种称之为 Gap Locks 的锁,官方的类型名称为:LOCK_GAP,我们也可以简称为 gap 锁。
间隙锁实质上是对索引前后的间隙上锁,不对索引本身上锁。

  • Gap在read commited或者更低级别的事务下是没有的,所以read commited 与read uncommited无法避免幻读。
  • 锁定一个范围,但不包含该记录本身。
  • **Gap是左开右闭的

**

1.Gap锁用在主键索引或者唯一索引的情况

  • 如果where条件全部命中, 则不会用Gap锁, 只会加行锁

image.png

  • 如果where条件部分命中或者全不命中, 则会加Gap锁

2.Gap锁会用在非唯一索引(普通索引)或者不走索引的当前读中

1.非唯一索引的情况

image.png

2.不走索引的情况

会对所有gap全部上锁
image.png