1.什么是间隙锁

当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(Next -Key锁)。

2.间隙锁演示

我们这有一张很简单的表user,其中id为自增主键:

mysql 间隙锁的实现 mysql间隙锁详解_键值

mysql 间隙锁的实现 mysql间隙锁详解_数据_02

user表中只有3条条记录,其id的值分别是1,2,3,存储引擎使用的是默认的InnoDB,下面的

SQL:

Select * from user where id > 2 for update;

是一个范围条件的检索,InnoDB不仅会对符合条件的id值为3的记录加一个行级锁,也会对id大于3(这些记录并不存在)的“间隙”加锁。InnoDB使用间隙锁的目的,一方面是为了防止幻读,以满足相关隔离级别的要求,对于上面的例子,要是不使用间隙锁,如果其他事务插入了id大于2的任何记录,那么本事务如果再次执行上述语句,就会发生幻读;另外一方面,是为了满足其恢复和复制的需要。在使用范围条件检索并锁定记录时,InnoDB 这种加锁机制会阻塞符合条件范围内键值的并发插入,这往往会造成严重的锁等待。

很显然,在使用范围条件检索并锁定记录时,InnoDB这种加锁机制会阻塞符合条件范围内键值的并发插入,这往往会造成严重的锁等待。因此 ,在实际应用开发中,尤其是并发插入比较多的应用,我们要尽量优化业务逻辑,尽量使用相等条件来访问更新数据,避免使用范围条件。还要特别说明的是,InnoDB除了通过范围条件加锁时使用间隙锁外,如果使用相等条件请求给一个不存在的记录加锁,InnoDB也会使用间隙锁!

Select * from user where id = 4 for update;

我们对id=4的记录加上了共享锁,但是id=4的记录是不存在的,那么mysql也会出现锁等待的情况,当你另外添加一条新的记录的时候便会阻塞。