快速解“锁”MySQL,拿下这7把钥匙,便能撬倒面试官( 三 )


InnoDB 在查找和扫描表的时候,会将扫描到的记录都加上记录锁,记录锁有可能是共享锁或者是排他锁 。因此,行级锁实际上是索引记录锁 。
在间隙锁的两个例子中的第二个例子,它实际上就是 Next-Key 锁,因为每一个括号括起来的内存包括一个索引记录锁和一个间隙锁,而 这完美符合 Next-Key 的定义 。
在默认的 REPEATABLE READ 隔离级别下,InnoDB 在查找和扫描索引时,都会使用 Next-Key 锁,以此来防止幻读的发生 。
插入意向锁插入意向锁(简称为 II Gap)是一种特殊的间隙锁,只有在插入记录的时候才会使用,这个锁表示插入的意向 。它与上面说到的表级意向锁是完全不同的,插入意向锁是属于行级锁,并且互相之间是兼容的,互不冲突,所以多个事务可以同时获取到相同间隙的 II Gap 锁 。

官方示例:
假设有索引记录,其值分别为4和7,单独的事务分别尝试插入值5和6,在获得插入行的排他锁之前,每个事务都使用插入意图锁来锁定4和7之间的间隙,但不要互相阻塞,因为行是无冲突的 。
插入意向锁只会和间隙锁和 Next-Key 锁冲突 。因为间隙锁的主要作用是防止幻读的发生,而在插入操作执行前需要获取到插入意向锁,而插入意向锁和间隙锁之间是冲突的,可以阻塞插入操作,所以间隙锁可以防止幻读的发生 。
AUTO-INC 锁AUTO-INC 锁又称为自增锁(简称 AI 锁) 。它是特殊的表锁,在插入数据到具有 AUTO_INCREMENT 列的表时使用 。当插入数据的表中有自增列时,数据库需要自动生成自增值,在生成之前,它会先获取到相关表的 AUTO-INC 锁 。其他事务的插入操作将会被阻塞,这样可以保证自增值的唯一性 。
AUTO-INC 锁具有如下特点:
  • 每一张表都具有它自己的 AUTO-INC 锁,互相之间不兼容 。
  • 不遵循二段锁协议,它并不是在事务提交时释放,而是在 insert 语句执行完成之后就释放,提高了并发插入的性能 。
  • 自增值一旦分配了就会加一,即使回滚了,自增值也不会减一,而是继续使用下一个值,所以自增值有可能不是连续的 。
因为在插入时会使用到该表锁,所以必然会造成并发插入性能的下降 。因此 InooDB 提供了一个 innodb_autoinc_lock_mode 配置项用于控制自增锁的算法,该配置项可以使用户选择如何在可预测的自动增量值序列与插入操作的最大并发性之间进行权衡 。
该配置有三个可选项:
  • 0:使用传统的锁定模式,并发性能最差 。
  • 1:默认采用的模式 。
  • 2:并发性能最高,但是不能保证同一条 insert 语句内的自增值是连续的 。
想要了解更多关于此配置的内容可以查看 MySQL 的这篇文档 。
总结InnoDB 的四种行锁的兼容性,如下表所示:
快速解“锁”MySQL,拿下这7把钥匙,便能撬倒面试官

文章插图
 
note: 第一列表示已经持有的锁,第一行表示要获取的锁 。
从表中可以得出结论:
  • 插入意向锁不影响其他事务获取其他的锁 。
  • 插入意向锁会受到 Gap 锁和 Next-Key 锁的影响 。一个事务想要获取指定间隙的插入意向锁,那么该间隙中的 Gap 锁和 Next-Key 锁必须没有被其他事务持有,否则,将会被阻塞 。
如果,我们除去插入意向锁的影响,那么兼容性表格如下:
快速解“锁”MySQL,拿下这7把钥匙,便能撬倒面试官

文章插图
 
从表中我们可以得出以下结论:
  • 当两个事务的锁都涉及到记录锁,那么将会冲突 。
  • 间隙锁与其他锁(不包括插入意向锁)都不会产生冲突 。
作者:奋斗的小皇帝
原文:
https://juejin.im/post/5ef6d8355188252e5961a253




推荐阅读