MySQL锁类型
两种行级锁(row-level locking)
- 共享锁(S):事务执行read时,可以持有这个锁
- 排它锁(X):事务执行update或delete时,可以持有这个锁
当事务1持有某一行数据的S锁,其他事务就只能申请这一行数据的S锁,不能申请X锁。
当事务1持有某一行数据的X锁,其他事务不能申请这一行的S和X锁。
意向锁(Intention Locks)
InnoDB支持多个粒度锁定,允许行锁和表锁共存。比如,LOCK TABLES ... WRITE语句会获取某一个表的X锁。
在对记录加S锁或者X锁时,必须保证其在相同的表上有对应的意向锁或者锁强度更高的表级锁。
InnoDB使用意向锁在多个粒度级别实现锁定,意向锁是表级别锁,它表明事务在之后会申请表中某一行的X或S锁,有两种类型的意向锁:
- IS(intention shared lock):表明事务之后要申请表中特定行的S锁
- IX(intention exclusive lock):表明事务之后要申请表中特定行的X锁
SELECT ... FOR SHARE使用了IS锁,SELECT ... FOR UPDATE使用IX锁
意向锁的作用
https://blog.csdn.net/dreamvyps/article/details/84500543
意向锁协议规则
在事务申请S锁之前,它必须申请表的IS锁或更强的锁
在事务申请X锁之前,它必须申请表的IX锁
锁兼容性
当存在一个锁时,一个事务能够再申请其他锁,则这两个锁是兼容的,否则是冲突的,申请锁的事务会等待锁释放。
记录锁(Record Locks)
记录锁用于锁定索引记录,比如SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE,该语句防止其他事务插入、更新、删除t.c1=10的记录。记录锁总是会锁住索引记录,即使当表没有定义索引时,InnoDB也会创建一个隐藏的聚簇索引用于记录锁(见https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html)。
每一个InnoDB都一个特殊的聚簇索引,该索引存储行记录的内容,通常它就是主键的代名词。
- 当你创建主键时,InnoDB就使用它作为聚簇索引
- 当没有主键时,InnoDB寻找第一个非空的唯一索引列作为聚簇索引
- 当没有主键或非空唯一索引时,InnoDB内部会生成一个叫做GEN_CLUST_INDEX的索引,该索引作用在一个包含行ID的合成列上,表上的行按这个ID列排序,该ID是一个6字节随着数据插入单调递增的字段。
间隙锁(Gap Locks)
间隙锁用于锁定索引记录之间的数据,或者锁住第一个索引之前的记录或最后一个索引之后的记录。比如SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE,该语句会防止其他事务插入c1=15的记录,即时当前数据库并没有c1=15的记录,因为间隙锁会锁住10到20之间的记录。
间隙可能跨越单个索引值,多个索引值,甚至可能为空。
使用唯一索引搜索唯一行的语句不需要间隙锁定,比如SELECT * FROM child WHERE id = 100,如果id字段具有唯一索引,该语句只会使用记录锁,而不是间隙锁。
同一个间隙上的gap X锁和gap S锁可以同时被不同事务持有,因为当从索引中清除记录,则必须合并由不同事务保留在记录上的间隙锁。
间隙锁的唯一目的是防止其他事务插入间隙,间隙锁可以共存,一个事务占用的间隙锁定不会阻止另一个事务在同一个间隙上进行间隙锁定。共享和独占间隙锁之间没有区别。它们彼此不冲突,它们执行相同的功能。
可以明确禁用间隙锁定。如果将事务隔离级别更改为READ COMMITTED,则会发生这种情况,在这些情况下,对于搜索和索引扫描禁用间隙锁定,并且仅用于外键约束检查和重复键检查。
Next-Key Locks
Next-Key锁是某个索引记录的记录锁和该索引记录之前间隙的间隙锁的组合
假设一个索引包含值10, 11, 13, 和 20,那在该索引上可能的Next-Key锁包含以下几个
(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)
默认情况下,InnoDB在REPEATABLE READ事务隔离级别运行。在这种情况下,InnoDB使用Next-Key锁进行搜索和索引扫描,从而防止幻读。
插入意向锁(Insert Intention Locks)
插入意向锁定是在行插入之前由INSERT操作设置的一种间隙锁定,该锁定表示:如果插入到相同索引间隙中的多个事务,他们不插入间隙内的相同位置,则不需要等待彼此。
比如有两个索引记录4和7,两个事务分别插入5和6两条记录,在他们获取5和6的排他锁之前(插入数据之后获取的),他们都会获取4到7之间的插入意向锁,但他们不会互相阻塞,因为他们插入了不同的位置。
自增长键锁(AUTO-INC Locks)
自增长键锁是一个特殊的表锁,当事务插入自增长列时需要获取该锁
innodb_autoinc_lock_mode配置选项配置用于自动增量锁定的算法,它允许您选择如何在可预测的自动增量值序列和插入操作的最大并发之间进行权衡。