MySQL InnoDB 支持行级锁,具体可划分为以下几类
- Record Lock:记录锁,也就是仅仅把一条记录锁上
- Gap Lock:间隙锁,锁定一个范围,但是不包含记录本身
- Next-key Lock:Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身
普通的 select 查询是不会加行锁的,如果需要,可以采用以下方式。
// 对读取的记录加共享锁
select ... lock in share mode;
// 对读取的记录加独占锁
select ... for update;
Next-key Lock 锁由记录锁和间隙锁组合而成,同时 Next-key Lock 是左开右闭区间,而间隙锁是左开右开区间。
Next-key Lock 在一些场景下会退化成记录锁或间隙锁。
以下是在 MySQL 8.0 版本,在可重复读隔离级别之下,唯一索引和非唯一索引的行级锁的加锁规则。
唯一索引等值查询
- 当查询的记录是存在的,在索引树上定位到这一条记录后,该记录的索引中的 Next-key Lock 会退化成记录锁
- 当查询的记录是不存在的,在索引树找到第一条大于该查询记录的记录后,该记录的索引中的 Next-key Lock 会退化成间隙锁
非唯一索引等值查询
- 当查询的记录存在时,由于不是唯一索引,所以肯定存在索引值相同的记录,于是非唯一索引等值查询的过程是一个扫描的过程,直到扫描到第一个不符合条件的二级索引记录就停止扫描,然后在扫描的过程中,对扫描到的二级索引记录加的是 Next-key 锁,而对于第一个不符合条件的二级索引记录,该二级索引的 Next-key 锁会退化成间隙锁。同时,在符合查询条件的记录的主键索引上加记录锁
- 当查询的记录不存在时,扫描到第一条不符合条件的二级索引记录,该二级索引的 Next-key 锁会退化成间隙锁。因为不存在满足查询条件的记录,所以不会对主键索引加锁
非唯一索引和主键索引的范围查询的加锁规则的不同之处
- 唯一索引在满足一些条件的时候,索引的 Next-key Lock 会退化为间隙锁或者记录锁
- 非唯一索引范围查询,索引的 Next-key Lock 不会退化为间隙锁和记录锁