面经整理--简单梳理MySQL中锁的概念

161 阅读4分钟

1.MySQL锁的分类

在MySQL中,根据加锁的范围不同,可以分为全局锁、表级锁、行级锁。

其中表级锁又有:表锁、元数据锁(MDL)、意向锁、AUTO-INC 锁

行级锁又有:记录锁、间隙锁、临键锁、插入意向锁。注意,InnoDB 引擎支持行级锁,而 MyISAM 引擎不支持

2.锁的作用

2.1 全局锁

  • 功能:加全局锁,使MySQL数据库处于只读状态,其他线程想要执行增删查改、改变表的结构的操作均会被阻塞。
  • 应用场景:全库逻辑备份,但是备份期间无法进行其他操作,导致业务停滞,解决方法是,如果数据库支持可重复读隔离级别,在备份前开启事务,这样即使其他线程改变了数据,也不会影响备份前创建的Read View。备份的数据一直是开启事务时的数据。

2.2 表级锁

2.2.1 表锁

表锁分为表级别的共享锁(读锁)、互斥锁(写锁)。锁定粒度大,一般不建议使用。 读锁:不会阻塞其他线程对同一表的读请求,但是会阻塞所有的写请求(包括本线程的)。 写锁:阻塞其他线程的读、写请求。

2.2.2 元数据锁(MDL)

MDL锁保证任一用户在对数据库进行操作时,不会有其他用户改变表结构(元数据信息)的操作在同时进行。

即两种情况: 1.用户对表进行CRUD操作时,加MDL读锁。不允许任何用户更改表的结构(申请MDL写锁) 2.用户更改表的结构时,加MDL写锁,不允许任何其他用户进行CRUD(申请MDL读锁)

MDL不需要显示调用,在事务执行期间是一直持有的,事务提交后就会被释放。

2.2.3 意向锁

意向锁的作用是快速判断表中记录有没有被加锁

1、表级锁和行级锁会发生冲突,具体表现为读读共享、读写互斥、写写互斥。

2、设想没有意向锁的情况下,如果要给一张表加表锁,就需要遍历表中每一条记录,防止某一条记录被加了行锁,产生冲突,这样效率是很低下的。

3、因此引入意向锁,在对表中记录加锁之前,先加上一个表级的意向锁。那么再加表锁时,通过判断有没有意向锁就可以知道表中有没有记录被加锁,具体表现为:

  • 在使用 InnoDB 引擎的表里对某些记录加上共享锁之前,需要先在表级别加上一个意向共享锁
  • 在使用 InnoDB 引擎的表里对某些记录加上独占锁之前,需要先在表级别加上一个意向独占锁
2.2.4 AUTO-INC锁

AUTO-INC锁实现了数据库表主键的自增,即在插入数据时,可以不指定主键的值,数据库会自动给主键赋值递增的值。

2.3 行级锁

2.3.1 记录锁

Record Lock 称为记录锁,锁住的是一条记录。而且记录锁是有 S 锁(共享锁)和 X 锁(独占锁)之分的 S锁: 读读共享、读写互斥 X锁: 读写互斥、写写互斥

2.3.2 间隙锁

Gap Lock 称为间隙锁,只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。

间隙锁虽然存在 X 型间隙锁和 S 型间隙锁,但是间隙锁之间是兼容的。

两个事务可以同时持有包含共同间隙范围的间隙锁,并不存在互斥关系,因为间隙锁的目的是防止插入幻影记录而提出的。

2.3.3 临键锁

Next-Key Lock 称为临键锁,是 Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。即其他事务不能修改加了记录锁的记录、也不能在间隙锁锁住的范围内插入新的记录

如果一个事务获取了 X 型的 next-key lock,那么另外一个事务在获取相同范围的 X 型的 next-key lock 时,是会被阻塞的

原因是 next-key lock 是包含间隙锁+记录锁的,虽然相同范围的间隙锁是兼容的,但是要考虑S型记录锁和X型记录锁之间的关系。

2.3.4 插入意向锁

一个事务在插入记录时,需要判断记录所在位置是否被其他事务加了间隙锁。

如果该位置被加了间隙锁,那么这个事务就会生成一个插入意向锁,锁状态是等待状态,此时该事务并没有获取到插入意向锁

生成插入意向锁后该事务会阻塞等待,直到加间隙锁的事务提交

该事务获得了之前生成的插入意向锁,插入记录

注意:

1.插入意向锁并不是意向锁,而是一种间隙锁。

2.尽管插入意向锁是一种间隙锁,但是不允许存在两个事务,其中一个持有某一区间范围的间隙锁,另一个持有该范围内的插入意向锁。