MySQL-Innodb锁
表锁
InnoDB的表级别锁包含五种锁模式:LOCK_IS、LOCK_IX、LOCK_X、LOCK_S以及LOCK_AUTO_INC锁,锁之间的相容性遵循数组lock_compatibility_matrix中的定义。
http://mysql.taobao.org//monthly/2016/01/01/
自增锁的场景
https://time.geekbang.org/column/article/80531
行锁
image.pnghttp://mysql.taobao.org//monthly/2016/01/01/
锁冲突矩阵
image.pnghttps://mp.weixin.qq.com/s?__biz=MzU2NzgwMTg0MA==&mid=2247484177&idx=1&sn=03916542bbfd8262811142c1db39a5b7&chksm=fc96e18ecbe168983b4c1fd3807948905d38429065dd3d7c112e0bbad329bcc3710c38d1ecc9&scene=21%23wechat_redirect
- gap lock会阻塞insert intention lock。事实上,gap lock的存在只是为了阻塞insert intention lock。(解决幻读问题)
- gap lock相互不会阻塞
- insert intention lock相互不会阻塞
- insert intention lock也不会阻塞gap lock
https://www.itcodemonkey.com/article/13003.html
插入意向锁与隐式锁
INSERT 语句加锁分析
而 INSERT 语句是插入一条新的纪录,这条记录表中本来就没有,那是不是就不需要加锁了?显然不是,至少有两个原因可以说明 INSERT 加了锁:
1. 为了防止幻读,如果记录之间加有 GAP 锁,此时不能 INSERT; 2.如果 INSERT 的记录和已有记录造成唯一键冲突,此时不能 INSERT;
要解决这两个问题,都是靠锁来解决的(第一个加插入意向锁,第二个加 S 锁进行当前读),只是在 INSERT 的时候如果没有出现这两种情况,那么锁就是隐式的,只是我们看不到而已。这里我们不得不提一个概念叫 隐式锁(Implicit Lock),它对我们分析 INSERT 语句的加锁过程至关重要。
https://www.aneasystone.com/archives/2017/12/solving-dead-locks-three.html
隐式锁是采用乐观锁的方式,降低insert或者update、delete时的加锁开销。
隐式锁介绍
https://blog.csdn.net/sun_ashe/article/details/82683296
– 隐式锁的特点
A. 只有在很可能发生冲突时才加锁,减少了锁的数量。
B. 隐式锁是针对被修改的B+Tree记录,因此都是Record类型的锁。不可能是Gap或Next-Key类型。
– 隐式锁的使用
A. INSERT操作只加隐式锁,不需要显示加锁。
B. UPDATE,DELETE在查询时,直接对查询用的Index和主键使用显示锁,其他索引上使用隐式锁。
理论上说,可以对主键使用隐式锁的。提前使用显示锁应该是为了减少死锁的可能性。
INSERT,UPDATE,DELETE对B+Tree们的操作都是从主键的B+Tree开始,因此对主键加锁可以有效的阻止死锁。
– Secondary Index上的隐式锁
前边说了, trx_id只存在于主键上,那么辅助索引上如何来实现隐式索引呢?
显然是要通过辅助索引中的主键值,在主键B+Tree上进行二次查找。这个开销是很大的。
InnoDB对这个过程有一个优化:
A. 每个页上有一个MAX_TRX_ID,每次修改辅助索引的记录时,都会更新这个最大事务ID。
B. 当判断是否要将隐式锁变为显式锁时,先将页面的max_trx_id和事务列表的最小trx_id比较。如果max_trx_id比事务列表的最小trx_id还小,那么就不需要转换为显示锁了。
http://www.uml.org.cn/sjjm/201205302.asp