前言
今天看到了这篇文章 ——了解常见锁类型看到了许多自己不了解或没见过的锁,特此记录一下。
意向锁
使用场景/诞生背景
在innodb引擎下,我们已经在一个表的某行上加上了行锁,此时又需要对该表加表锁。这时引擎会挨个遍历表中的每一行,判断是否有行锁,若有则加锁失败。
这样效率显然比较低下,于事意向锁就诞生了。
意向锁特点
- 意向锁分为读意向锁(IS锁)与写意向锁(IX锁) 且均为表级锁
- 当某个事务要加行锁时,会先在整个表上加意向锁,这样就解决了加表锁时要遍历全表的问题,大大提高了性能。
- 意向锁直接按,意向锁与行锁之间均不互斥。
自增锁
自增锁(AI锁) 简单来说就是用在自增列上的锁,主要针对插入语句,当一个语句要向表中插入数据时,会先加上一个自增锁,阻塞其他的插入语句
自增锁特点
- 自增锁互不兼容,同一张表只有一个自增锁
- 自增锁不遵守两阶段协议,当插入语句成功时,这个自增锁自动释放
- 即使事务回滚了,自增锁的值也不会减少回去
自增锁的几个策略
传统的自增策略对插入语句的并发度影响非常大,所以MySQL对其进行了优化,引入了轻量级的机制mutex来代替自增锁。
通过参数innodb_automic_lock_mode指定
- innodb_automic_lock_mode = 0 表示使用传统的自增锁。
- innodb_automic_lock_mode=1 表示一种折中的办法,依据具体情况,极可能使用传统自增锁,也可能是用mutex轻量级的自增锁。具体情况如下
1.simple insert 当执行引擎通过分析语句可以明确知道要插入的数量的insert语句就是simple insert。此时会用mutex
2. bulk insert 通过分析语句无法知道插入了多少行(例:INSERT INTO t VALUES SELECT * FROM t1)的插入语句是bulk insert。此时会使用传统insert
3. mixed insert 不确定是否需要分配子增值的列(例 INSERT INTO table VALUES(1,‘a’), (NULL,‘b’), (5, ‘C’), (NULL, ‘d’) ),这时会获取最坏情况下的插入量进行分配,使用mutex。 - innodb_automic_lock_mode=2 全部使用mutex
行锁相关
记录锁
就是我们通常理解的行锁
记录锁特点
- 当我们对二级索引加锁时,也会 在对应的聚簇索引上加锁
- 当无法使用索引时,会进行全表扫描,对扫描过的所有的行进行加锁。由于两阶段协议,这些锁只会在事务提交时释放,显然会极大地影响并发度。于是MySQL对这一机制进行了优化,当扫描过的行被server层判断为不符合条件后,会立即释放改行的锁。(这显然破坏了两阶段协议)
间隙锁 (gap lock)
是一种加载两个索引之间的锁,加入当前标一共有15行记录,要操作的语句覆盖了所有的记录,那么它的间隙锁可以加在(-∞,0)(0,5)(5,10)(10,15)(15,superNum) superNum是innodb自动为每个表加上的最大值。
Next-Key lock
间隙锁与记录锁的组合叫做next-key,依旧是之前的情景,此时锁的记录就变成了(-∞,0](0,5](5,10](10,15](15,superNum] 。每个锁的区间都是前开后闭的,避免了重复加锁与漏加锁。
间隙锁.Next-key lock 特点
- 间隙锁与间隙锁之间不冲突
- 间隙锁只与对这个区间内插入语句冲突。
插入意向锁
插入意向锁是一种特殊的间隙锁,只有在INSERT语句时才会有这种锁
Insert Intention Lock signals the intent to insert in such a way that multiple transactions inserting into the same index gap need not wait for each other if they are not inserting at the same position within the gap.
多个事务,在同一个索引,同一个范围区间插入记录时,如果插入的位置不冲突,不会阻塞彼此。