InnoDB 实现了两种标准的row-level locking——共享锁shared(S) locks 和 排他锁exclusive(X) locks.
如果事务 T1 在第r行数据上持有一个共享锁,当另一个事务T2来请求第r行数据上的锁时,会这样:
InnoDb支持多种粒度的锁,允许行级锁和表级锁共存。
意向锁是InnoDB中的表级锁,用于指示该表中某一行的某个事务需要哪种类型的锁(共享或排他)。
当一个事务请求锁时,只有和已存在的锁兼容,才能获取成功。否则事务会等待直到,已存在的冲突的锁被释放。如果事务最终无法获得锁,则可能是由于死锁deadlock
因此,意向锁不会阻止任何请求(除了全表的请求)。意向锁的主要目的是:展示有事务正在锁定一行,或者将要锁定一行。
记录锁是一个在索引记录上的锁,例如:SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;
会阻止其他事务插入、修改、删除那些t.c1等于10的行。
一个gap lock是锁在索引记录的一定范围。例如SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; 阻止其他事务插入t.c1在10~20之间的记录,无论t.c1是否已经有这样的值,因为间隙范围内所有存在的记录都被锁定了。
一个gap lock可能跨域一个或多个值,甚至为空。
gap lock是性能和并发性之间的交易,在一些事务隔离级别中使用。
对于使用唯一索引锁定行以搜索一行的语句,不需要使用间隙锁定。
这里也值得注意的是,不同的事务可以在gap上保持冲突的锁。例如,事务A可以在gap上保持共享的间隙锁(间隙S锁),而事务B在同一gap上保持独占间隙锁(间隙X锁)。允许冲突间隙锁定的原因是,如果从索引中清除记录,则必须合并由不同事务记录保持的间隙锁定。
在默认情况下,mysql的事务隔离级别是可重复读,这时默认采用next-key locks。所谓Next-Key Locks,就是Record lock和gap lock的结合。InnoDB以这样一种方式执行行级锁定,即当它搜索或扫描表索引时,它会在遇到的索引记录上设置共享锁或排它锁。
索引记录上的next-key locks也会影响该索引记录之前的“间隙”。
也就是说,next-key locks是一个索引记录锁,并在索引记录之前的间隙上加上一个gap锁。
如果一个会话对索引中的记录R具有共享或独占锁定,则另一个会话不能在索引顺序中的R之前的间隙中插入新的索引记录。
假设索引包含值10,11,13和20.此索引的可能Next-Key Locks涵盖以下区间,其中圆括号表示排除区间端点,方括号表示包含端点:
(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)
插入意向锁 Insert Intention Locks
insert intention lock是插入行之前设置的一种gap lock。这个锁发信号通知插入意图,以通知插入到相同gap中的多个事务,如果没有插入gap中相同位置时不需要等待对方。
假设有索引记录的值为4和7.分别尝试插入5和6的值的事务分别在获得对插入行的排它锁之前用插入意向锁来锁定4和7之间的间隔,但不要相互阻塞,因为行是非冲突的。
AUTO-INC锁是一个特殊的表级锁。在最简单的情况下,如果一个事务正在向表中插入值,则任何其他事务都必须等待自己插入到该表中,以便第一个事务插入的行接收连续的主键值。innodb_autoinc_lock_mode配置选项控制用于AUTO-INC的算法。