转载:MySQL数据库锁:Record Lock, Gap Lock 和 Next-Key Lock
InnoDB引擎 在 共享锁和排他锁 文章中,我们详细分析了共享锁和排他锁在MySQL
中是如何工作的,今天,我们接着分析InnoDB
引擎的 3种行锁。
在MySQL
的InnoDB
引擎的行锁主要有三类:
Record Lock
:记录锁,是在索引记录上加锁;Gap Lock
:间隙锁,锁定一个范围,但不包含记录;Next-key Lock
:Next-key Lock = Gap Lock + Record Lock
,它锁定了一个范围(Gap Lock实现),并且锁定记录本身(Record Lock实现);
Record Lock
什么是 Record Lock?
Record Lock
,记录锁,它是针对索引记录的锁,锁定的总是索引记录。在多用户数据库系统中,多个事务可能会同时尝试读取或修改同一条记录,Record Lock
确保只有一个事务能在某一时刻修改该记录,其他事务只能读取,或者在写锁释放后再进行修改。
举例说明
为了更好的说明Record Lock
,我们以下面的顺序执行流来进行验证:

示例执行结果如下图:

通过上面的示例可以看出:
- 事务A(sessionA)对
id=1
加排他锁之后产生了记录锁 - 事务B(sessionB)对
id=1
的update
操作被阻塞了 - 事务C(sessionC)可以查看到
Record Lock
Gap Lock
什么是Gap Lock?
Gap Lock
,间隙锁,它是一种行级锁,锁住两个索引记录之间的间隙
,而不是实际的数据记录,由InnoDB
隐式添加。
如下图:(1,3) 表示锁住记录1 和记录3 之间的间隙,这样记录2 就无法插入,间隙可能跨越单个索引值、多个索引值,甚至是空。

举例说明
为了更好的说明Gap Lock
间隙锁,我们以下面的顺序执行流来进行验证:

示例执行结果如下图:

通过上面的示例执行结果可以看出:
- 事务A(sessionA)在加共享锁的时候产生了间隙锁(Gap Lock)
- 事务B(sessionB)对间隙中进行
insert/update
操作,需要先获取排他锁(X),导致阻塞 - 事务C(sessionC)通过
show engine innodb status\G
指令可以查看到间隙锁的存在。
需要说明,间隙锁只是锁住间隙内部的范围,在间隙外的insert/update
操作不会受影响。
Next-Key Lock
什么是Next-Key Lock?
Next-Key Lock
,称为临键锁,它是Record Lock + Gap Lock
的组合,用来锁定一个范围,并且锁定记录本身锁,它是一种左开右闭的范围,可以用符号表示为:(a,b]。如下图:

举例说明
为了更好的说明Next-Key Lock
,我们以下面的顺序执行流来进行验证:

示例执行结果如下图:

通过上面的示例执行结果可以看出:
- 事务A(sessionA)在加共享锁的时候产生了间隙锁(Gap Lock)
- 事务B(sessionB)对间隙中进行
insert
操作,需要先获取排他锁(X),导致阻塞。 - 事务C(sessionC)对间隙中进行
update
操作,需要先获取排他锁(X),导致阻塞。 - 事务D(sessionD)通过
show engine innodb status\G
指令可以查看到间隙锁的存在。需要说明的,间隙锁只是锁住间隙内部的范围,在间隙外的insert/update
操作不会受影响。
总结
Record Lock
,Gap Lock
和Gap Lock
3种锁是存在MySQL
的InnoDB
引擎的行锁,MyISAM引擎没有:
Record Lock
:记录锁,是在索引记录上加锁;Gap Lock
:间隙锁,锁定一个范围,但不包含记录,即(A,B)
;Next-key Lock
:Next-key Lock = Gap Lock + Record Lock
,它锁定了一个范围(Gap Lock实现),并且锁定记录本身(Record Lock实现),即(A,B]
;;
这 3种锁都是InnoDB
引擎隐式添加的,目的是为了解决可重复读隔离级别下幻读的现象。