面试连环炮系列(33):MySQL支持哪几种锁

面试连环炮系列(33):MySQL支持哪几种锁

1.MySQL有哪几种锁?

MySQL数据库存在多种数据存储引擎,每种存储引擎的锁定机制也有较大区别。各存储引擎使用了三种类型的锁定机制:表级锁定,行级锁定和页级锁定。以Innodb引擎为例子,它有7种锁:

  • 1)共享锁和排他锁 Shared and Exclusive Locks

Innodb实现了标准的行级锁,其中有两种类型:
共享锁:允许持有共享锁的事务读取该行记录。
排他锁:允许持有排他锁的事务更新或者删除该行记录。

如果事务T1持有某行数据的共享锁,那么另一个事务T1想获取该行数据的锁时:
共享锁:T2会马上获得一个共享锁,此时T1、T2都有该行数据的共享锁。
排他锁:T2不能马上获得排他锁。

如果事务T1持有某行数据的排他锁,那么其他事务都不能立刻获得该行数据的共享锁或排他锁。其他事务需要等待T1释放它所持有的该行数据的排他锁。

  • 2)意向锁 Intention Locks

Innodb支持多粒度锁,允许行锁和表锁共存。为了实现多粒度级别的锁,innodb使用了意图锁。意图锁是表级别的锁,它指示事务稍后需要表中的一行使用哪种类型的锁(共享或排他)。

以下是两种类型的意向锁:

共享意向锁:表明该事务计划对某行数据设置一个共享锁。
排他意向锁:表明该事务计划对某行数据设置一个排他锁。

例如,select …. for share就设置了一个共享意向锁,select …. for update就设置了一个排他意向锁。

意向锁的形为:

在一个事务获取到某行锁的共享锁之前,它必须先获得一个共享意向锁或者更高级别的锁(也就是排他意向锁啦)。
在一个事务获取到某行锁的排他锁之前,它必须先获得一个排他意向锁。

事务可以获得与已经存在的锁兼容的锁,不能获得与已经存在的锁冲突的锁。在有冲突的锁被释放之前,事务会一直等待。如果一个锁的请求与已存在的锁冲突并且因为有可能产生死锁而不能被获得,那么就会产生一个错误。除了全表请求(如,lock table … write)之外,意向锁不会阻塞任何事物。意向锁的主要目的就是表面有人正在对某行进行加锁,或者正要锁住表内某行。

  • 3)记录锁 Record Locks

记录锁是对索引进行记录的锁。例如,select c1 from t where c1 = 10 for update 禁止了任何其他事务对c1 = 10的数据行进行插入,更新或者删除。

记录锁总是对索引进行加锁,即使该表没有定义索引。如果表没有自己定义索引,那么innodb就会定义一个隐式的聚集索引(hidden clustered index)并且对这个索引进行加锁。

  • 4)间隙锁 Gap Locks

间隙锁是对一个索引间隙加锁的锁。如果索引间隙的范围为(index1,index2),那么就锁住index1到index2之间的间隙,如果索引只有一个index,那么根据innoddb底层的B+树的结构,假设index前面最近的一个索引为index1,后面最近一个索引为index2,那么就会锁住index1到index2之间的间隙。

例如,select c1 from t where c1 between 10 and 20 for update 禁止了其他任何事物插入一行c1=15的数据行,无论是不是已经有了一行c1=15的数据行,因为10-20这个间隙的值都被锁上了间隙锁。间隙可能会包含单个索引值或者多个索引值,甚至有可能是空的。

  • 5)临键锁 Next-key Locks

Next-Key Lock是索引上的记录锁和锁住该索引前面的间隙的间隙锁的组合。

innodb通过对搜索和扫描索引时得到的索引加共享锁或排他锁来实现行级锁。因此,行级锁实际上是索引记录锁。索引记录上的next-key锁也会影响该索引记录之前的间隙。也就是说,next-key锁是由索引记录锁加上对索引之前的间隙加锁的间隙锁组成的。如果一个会话对索引中的记录R有一个共享锁或排他锁,那么另一个会话不能再紧挨着索引顺序的R之前的间隙插入一个新的索引记录。

默认情况下,innodb引擎采取REPEATABLE READ事务隔离级别,此时,innodb使用next-key lock来防止幻读。

  • 6)插入意向锁

插入意向锁时一种由insert操作在行插入之前的间隙锁类型。这个锁表面了插入的意图,如果插入到同一个索引间隙中的多个事务没有插入到间隙中的相同位置,那么它们就不需要互相等待。假设有值为4和7的索引,有两个事务分别像插入5和6,那么他们在插入数据之前都会锁住4和7之间的间隙,但此时他们不会互相阻塞,而他们随后会获得5和6的排他锁,因为是行锁,所有依旧不会互相阻塞。

  • 7)自增锁

AUTO-INC是一种特殊的表锁,当事务想插入一条自增行的时候使用。

例如,如果一个事务正在插入数据,任何其他事务如果也要插入,那么他们都必须等待当前事务插入完毕,这样才能保证那个自增字段是连续的。

  • 8)Predicate Locks for Spatial Indexes

InnoDB支持包含空间数据的列的空间索引。为了处理想要锁住空间索引的锁,next-key锁无法实现REPEATABLE READ 或 SERIALIZABLE事务隔离级别的要求。多维数据没有绝对的排序概念,因此不知道哪一个是下一个索引,也就无法获得间隙锁。

为了支持具有空间索引的表的隔离级别,InnoDB使用Predicate Locks。一个Predicate锁包含每个维度的边界,每次就锁住这些边界就可以了。

2.UPDATE、DELETE、INSERT语句执行时有锁吗,是什么锁?

UPDATE、DELETE、INSERT语句都会自动给涉及到的数据加上排他锁。

3.简单的SELECT语句执行时有锁吗?

SELECT语句默认不加锁,都是快照读,不受其他事务锁的限制。

4.SELECT 语句怎么加锁呢?

SELECT ** WHERE xx FOR UPDATE 可以实现排他锁。

5.SELECT ** WHERE xx FOR UPDATE是行锁还是表锁?

如何WHERE子句匹配的条件字段带有索引时,使用行级锁;不带有索引时,使用的是表级锁。

6.SELECT ** WHERE xx LOCK IN SHARE MODE的作用是什么

加共享锁,意义是读取最新已提交的数据但不准备修改,防止在读取的过程中,其他事务修改。

参考(摘抄的文字版权属于原作者)
https://blog.csdn.net/weixin_45714229/article/details/123986073

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注