type
status
date
slug
summary
tags
category
icon
password
整理定义
间隙锁(Gap Lock)
间隙锁是对索引记录之间的间隙的锁定,或者是对第一个索引记录之前或最后一个索引记录之后的间隙的锁定。例如,语句
SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;
阻止其他事务在列 t.c1 中插入值 15,无论该列中是否已经存在该值,因为锁定了范围内所有现有值之间的间隙。间隙可能跨越单个索引值、多个索引值,甚至可能是空的。
复述展开
间隙锁是性能和并发之间权衡的一部分,在某些事务隔离级别中使用,在其他级别中则不使用。
对于使用唯一索引搜索唯一行的语句,不需要间隙锁定。(这不包括搜索条件仅包含多列唯一索引中的一些列的情况;在这种情况下,会发生间隙锁定。)例如,如果 id 列有唯一索引,以下语句仅对具有 id 值 100 的行使用索引记录锁,并且不关心其他会话是否在前面的间隙中插入行:
如果 id 没有索引或有非唯一索引,该语句确实会锁定前面的间隙。
此外,不同的事务可以在同一个间隙上持有冲突的锁。例如,事务 A 可以在一个间隙上持有共享间隙锁(gap S-lock),而事务 B 在同一个间隙上持有排他间隙锁(gap X-lock)。允许冲突的间隙锁存在的原因是,如果一个记录从索引中清除,不同事务在该记录上持有的间隙锁必须合并。
InnoDB 中的间隙锁是“纯粹抑制性的”,这意味着它们的唯一目的是防止其他事务向间隙中插入。间隙锁可以共存。一个事务持有的间隙锁不会阻止另一个事务在同一个间隙上持有间隙锁。共享和排他间隙锁之间没有区别。它们不会相互冲突,并且它们执行相同的功能。
可以显式地禁用间隙锁。如果你将事务隔离级别更改为 READ COMMITTED,就会发生这种情况。在这种情况下,间隙锁对搜索和索引扫描被禁用,仅用于外键约束检查和重复键检查。
使用 READ COMMITTED 隔离级别还有其他一些效果。MySQL 在评估 WHERE 条件后会释放非匹配行的记录锁。对于 UPDATE 语句,InnoDB 执行“半一致性”读取,这样它就会返回最新的提交版本给 MySQL,以便 MySQL 可以确定行是否与 UPDATE 的 WHERE 条件匹配。
总结
间隙锁是数据库中用于管理并发和维护数据一致性的一种锁机制。它们主要用于防止事务在索引记录之间的间隙中插入数据,从而可能影响其他事务的查询或更新操作。间隙锁对于保持数据的隔离性和一致性至关重要,尤其是在可重复读(REPEATABLE READ)隔离级别下。
在唯一索引的情况下,间隙锁通常不是必需的,因为唯一性保证了不会有重复的值插入。然而,如果索引不是唯一的,或者查询条件不包括所有的唯一索引列,间隙锁可能会被使用。
间隙锁可以是共享的或排他的,但在 InnoDB 中,这两种类型的间隙锁实际上是相同的,因为它们都是为了防止数据插入到间隙中。不同事务可以在同一个间隙上持有间隙锁,而不会相互冲突。
在 READ COMMITTED 隔离级别下,间隙锁的使用被限制,仅在特定情况下(如外键检查和重复键检查)才会使用。此外,这个隔离级别还允许在确定行不匹配 WHERE 条件后立即释放记录锁,以及在 UPDATE 操作中使用半一致性读取,这些都有助于提高并发性能,但可能会牺牲一定程度的数据一致性。
快速跳转链接
【概念解析】启动
【概念解析】Day 1 - 10
【概念解析】Day 11 - 20
【概念解析】Day 21 - 30
【概念解析】Day 31 - 40
【概念解析】Day 41 - 50
【概念解析】Day 51 - 60
【概念解析】Day 61 - 70
【概念解析】Day 71 - 80
【概念解析】Day 81 - 90
- 作者:eachenkuang
- 链接:https://kuangyichen.com/article/industry-day77
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。