type
status
date
slug
summary
tags
category
icon
password
MySQL锁的种类

全局锁
表级锁
表锁并不是直接以锁定整个表的方式实现的,而是通过对表中的各个数据页(或者记录)加锁的方式来间接实现的。因此,数据库必须在锁定表时检查每一行或每一数据页,以确保没有其他事务对这些行或数据页加了排它锁(独占锁)。
意向锁
作用:意向锁的目的是为了快速判断表里是否有记录被加锁
意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁和独占表锁发生冲突。
行级锁
Record Lock(记录锁)
Record Lock 称为记录锁,锁住的是一条记录。而且记录锁是有读锁和写锁之分的:
Gap Lock(间隙锁)
Gap Lock 称为间隙锁,只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象
Next-Key Lock(临键锁)
Next-Key Lock 称为临键锁,是 Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身
什么SQL会加行级锁
普通的select不会加锁,使用的是MVCC
除了上面这两条锁定读语句会加行级锁之外,update 和 delete 操作都会加行级锁,且锁的类型都是独占锁(X型锁)
MySQL是怎么加行级锁的
加锁的对象是索引,加锁的基本单位是 next-key lock,在能使用记录锁或者间隙锁就能避免幻读现象的场景下,next-key lock 就会退化成记录锁或间隙锁
锁退化的关键在于是否能解决幻读的情况
唯一等值查询
当查询的记录是「存在」的,索引中的 next-key lock会退化成「记录锁」
当查询的记录是「不存在」的,在索引树找到第一条大于该查询记录的记录后,将该记录的索引中的 next-key lock 会退化成「间隙锁」
本篇文章的「唯一索引」是用「主键索引」作为案例说明的,加锁只加在主键索引项上
然后,很多同学误以为如果是二级索引的「唯一索引」,加锁也是只加在二级索引项上
其实这是不对的,如果是用二级索引(不管是不是非唯一索引,还是唯一索引)进行锁定读查询的时候,除了会对二级索引项加行级锁(如果是唯一索引的二级索引,加锁规则和主键索引的案例相同),而且还会对查询到的记录的主键索引项上加「记录锁」
在文章的「非唯一索引」的案例中,我就是用二级索引作为例子,对二级索引进行锁定读查询的时候,因为存在两个索引(二级索引和主键索引),所以两个索引都会加锁
唯一索引范围查询
每一个扫描到的索引加 next-key,如果遇到下面情况会退化为记录锁或者间隙锁
- 情况一:针对「大于等于」的范围查询因为存在等值查询的条件,那么如果等值查询的记录是存在于表中,那么该记录的索引中的 next-key 锁会退化成记录锁
例:

- 情况二:针对「小于或者小于等于」的范围查询,要看条件值的记录是否存在于表中
- 当条件值的记录不在表中,那么不管是「小于」还是「小于等于」条件的范围查询,扫描到终止范围查询的记录时,该记录的索引的 next-key 锁会退化成间隙锁,其他扫描到的记录,都是在这些记录的索引上加 next-key 锁
- 当条件值的记录在表中
- 如果是「小于」条件的范围查询,扫描到终止范围查询的记录时,该记录的索引的 next-key 锁会退化成间隙锁其他扫描到的记录,都是在这些记录的索引上加 next-key锁
- 如果「小于等于」条件的范围查询,扫描到终止范围查询的记录时,该记录的索引 next-key 锁不会退化成间隙锁。其他扫描到的记录,都是在这些记录的索引上加 next-key 锁
例:

例:

例:

非唯一索引等值查询
当我们用非唯一索引进行等值查询的时候,因为存在两个索引,一个是主键索引,一个是非唯一索引(二级索引),所以在加锁时,同时会对这两个索引都加锁,但是对主键索引加锁的时候,只有满足查询条件的记录才会对它们的主键索引加锁
- 当查询的记录「存在」时,由于不是唯一索引,所以肯定存在索引值相同的记录,于是非唯一索引等值查询的过程是一个扫描的过程,直到扫描到第一个不符合条件的二级索引记录就停止扫描,然后在扫描的过程中,对扫描到的二级索引记录加的是 next-key 锁,而对于第一个不符合条件的二级索引记录,该二级索引的 next-key 锁会退化成间隙锁,在符合查询条件的记录的主键索引上加记录锁
例:


- 当查询的记录「不存在」时 扫描到第一条不符合条件的二级索引记录,该二级索引的 next-key 锁会退化成间隙锁。因为不存在满足查询条件的记录,所以不会对主键索引加锁
例:

当有一个事务持有二级索引的间隙锁 (22, 39) 时插入 age = 22 或者 age = 39 记录的语句是否可以执行成功关键还要考虑插入记录的主键值因为「二级索引值(age列)+主键值(id列)」才可以确定插入的位置插入位置后看插入的位置的下一条记录是否有间隙锁有间隙锁发生阻塞
age=22&id=3成功 age=22&age=12失败
非唯一索引范围查询
非唯一索引范围查询,索引的 nextKey lock 不会有退化为间隙锁和记录锁的情况
例:
