MySQL中基于InnoDB引擎的锁

共享锁和排他锁

InnoDB实现了标准的行级锁,共享锁和排他锁。

  • 共享锁允许持有锁的事务读取一行。
  • 排他锁允许持有锁的事务更新或者删除一行。

如果一个事务T1持有对第r行的共享锁,那么对于其他不同事务T2对第r行的锁请求处理方法如下:

  • T2对于共享锁的请求能过被立即批准。此时,T1和T2同时持有对于第r行的共享锁。
  • T2对于排他锁的请求不能被立即批准。

如果事务T1在第r行上拥有排他锁,则不能立即批准某个不同事务T2对第r行上任一类型的锁请求。相反,事务T2必须等待事务T1释放对第r行的锁。

意向锁

InnoDB支持多种粒度锁定,允许行锁和表锁并存。例如,对于语句LOCK TABLES ... WRITE对于一个特定的表使用了排他锁。为了使锁可以在多个粒度级别使用,InnoDB使用了意向锁。意向锁是表级锁,指示事务稍后对表中的行需要使用哪种类型的锁(共享锁或排他锁)。有两种类型的意向锁:

  • 意向共享锁代表了一个事务试图去在表的单个行上设置共享锁。
  • 意向排他锁代表了一个事务试图去在表的单个行上设置排他锁。

例如,SELECT ... FOR SHARE设置了一个意向共享锁,SELECT ... FOR UPDATE设置了一个意向排他锁。

意向锁协议如下:

  • 在一个事务获取表中某行的共享锁之前,它必须首先获取该表中的意向共享锁或更强的锁。
  • 在一个事务获取表中某行的排它锁之前,它必须首先获取该表中的意向排他锁。

表级锁的兼容性如下图所示:

 排他锁意向排他锁共享锁意向共享锁
排他锁冲突冲突冲突冲突
意向排他锁冲突兼容冲突兼容
共享锁冲突冲突兼容兼容
意向共享锁冲突兼容兼容兼容

如果一个事务请求的锁与现有锁兼容,则将其授予给此事务,但如果与现有锁冲突,则不授予该锁。事务等待直到现有的冲突的锁被释放。如果锁请求与现有锁发生冲突,并且由于可能导致死锁而无法被授予,则会发生错误。

意向锁除了全表请求外不阻止任何其他操作。意向锁的主要目的是表明有人正在锁定表中的行,或者打算锁定表中的行。

记录锁

记录锁定是对索引记录的锁定。例如,SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE,阻止其他事务进行插入,更新或者删除t.c1 = 10的行。

记录锁经常锁定索引记录,即使一个表中没有定义索引。对于这种情况,InnoDB创建一个隐藏的聚簇索引,并将该索引用于记录锁。

间隙锁

间隙锁是对索引记录之间的间隙的锁定,或者是对第一个索引记录之前或最后一个索引记录之后的间隙的锁定。例如,SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE,阻止了其他事务插入一个15的值到t.c1列,不管这一列中是否已经存在这样的值,因为该范围内所有现有值之间的间隙是锁定的。

间隙可能跨越单个索引值,多个索引值,甚至为空。

间隙锁是性能和并发性之间权衡的一部分,并且在某些事务隔离级别中使用。

对于使用唯一索引来锁定唯一行的语句,不需要间隙锁。例如,第id列有唯一的索引,以下语句仅对id值为100的行使用索引记录锁,其他会话是否在前面的间隙中插入行并不重要:SELECT * FROM child WHERE id = 100。

如果id未建立索引或索引不唯一,则该语句会锁定前面的间隙。

在这里还值得注意的是,可以通过不同的事务将冲突的锁保持在间隙上。例如,事务A在一个间隙上持有共享间隙锁,而事务B在相同的间隙上持有排他间隙锁。允许间隙锁冲突的原因是,如果从索引中清除记录,则必须合并由不同事务保留在记录上的间隙锁。

InnoDB中的间隙锁时“完全抑制的”,这意味着它们的唯一目的是防止其他事务插入这个间隙。间隙锁可以共存,一个事务持有的间隙锁不会阻止另一事务对相同的间隙进行锁定。共享间隙锁和排他间隙锁之间没有区别。它们彼此不冲突,并且执行相同的功能。

间隙锁定可以被显式地禁用。如果你将事务隔离级别更改为READ COMMITTED。这种情况下,将禁用间隙锁来进行搜索和索引扫描,并且间隙锁仅用于外键约束检查和重复键检查。

使用READ COMMITTED隔离级别也会产生一些其他的影响。MySQL在评估WHERE的条件后,将释放不匹配行的记录锁。对于UPDATE语句,InnoDB进行“半一致”读取,以便将最新的提交版本返回给MySQL,从而MySQL可以确定该行是否与UPDATE的WHERE条件匹配。

Next-Key Lock

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

InnoDB执行行级锁的方式是,当它搜索或扫描表索引时,会在遇到的索引记录上设置共享锁或排他锁。因此,行级锁实际上是索引记录锁。索引记录上的Next-Key Lock也会影响该索引记录之前的间隙。即Next-Key Lock是索引记录锁加上索引记录之前的间隙上的间隙锁。如果一个会话在索引中的记录R上具有共享锁或排他锁,则另一会话不能按照索引顺序在R之前的间隙中插入新的索引记录。

InnoDB默认使用REPEATABLE READ事务隔离级别。在这种情况下,InnoDB使用Next-Key Lock进行搜索和索引扫描,从而防止幻行。

插入意向锁

插入意向锁是一种在行插入之前通过INSERT操作设置的间隙锁。此锁发出插入意向的信号是,如果多个事务要插入相同的索引间隙,但不是间隙中相同的位置,则无需互相等待。假设有索引记录,值为4和7。分别尝试插入值5和6的不同事务在获得所插入行的排他锁之前,分别使用插入意向锁来锁定4和7之间的间隙,但不会相互阻塞,因为行是不冲突的。

AUTO-INC Locks

AUTO-INC锁是一种特殊的表级锁,由事务插入具有AUTO_INCREMENT列的表中获得。在最简单的情况下,如果一个事务正在向表中插入值,则任何其他事务都必须等待自己在该表中进行的插入,以便第一个事务插入的行接收连续的主键值。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值