说说 InnoDB 里的行锁实现?

InnoDB的行级锁实现主要包括以下三种类型:

  • 记录锁(Record Lock):直接锁定单行记录。当使用唯一性索引(包括唯一索引和聚簇索引)进行精确匹配的等值查询时,会直接锁定该行记录。例如,执行select * from t where id = 6 for update;会锁定id=6的记录。
  • 间隙锁(Gap Lock):锁定两个记录之间的逻辑空隙,即左开右开的间隔。当进行等值查询或范围查询时,没有命中任何记录时,会锁定对应的间隙区间。例如,执行select * from t where id = 3 for update;或者select * from t where id > 1 and id < 6 for update;会锁定区间(1,6)。
  • 临键锁(Next-key Lock):结合了记录锁和间隙锁,锁定记录本身以及索引之间的间隙。当进行范围查询并命中部分记录时,会锁定临键区间。需要注意的是,临键锁会包含最后一个记录右边的临键区间。例如,执行select * from t where id > 5 and id <= 7 for update;会锁定区间(4,7]和(7,+∞)。InnoDB的默认行锁类型就是临键锁(Next-Key Locks)。当使用唯一性索引进行等值查询时,临键锁会退化为记录锁;当没有命中任何记录时,会退化为间隙锁。

此外,在行级锁中还存在插入意向锁(Insert Intention Lock)。

  • 插入意向锁(Insert Intention Lock):当一个事务要插入一条记录时,需要判断插入位置是否被其他事务加了意向锁。如果有,则插入操作需要等待,直到拥有该间隙锁的事务提交。等待期间,事务需要在内存中生成一个锁结构,表示有事务想在某个间隙中插入新记录,但是正在等待。这种类型的锁称为插入意向锁(Insert Intention Locks)。

举例来说,如果事务T1给区间(1,6)加了意向锁,现在事务T2要插入一条id为4的数据,它会获取(1,6)区间的插入意向锁。同样,事务T3想要插入一条id为3的数据,它也会获取(1,6)区间的插入意向锁。然而,这两个插入意向锁之间并不会互斥。

需要注意的是,在已提交读(READ COMMITTED)隔离级别下,间隙锁(Gap Locks)和临键锁(Next-Key Locks)都会失效,不起作用。

标签: java, Java面试题, MySQL, Java问题合集, MySQL面试题, Java编程, Java问题精选, Java常见问题