MySQL 记录锁+间隙锁防幻读方案

1. 什么是幻读?

定义
        幻读是指在事务过程中,一个事务执行了某些查询操作后,另一事务插入、删除或更新了满足查询条件的新数据,当第一个事务再次执行相同的查询操作时,结果集出现了“幻觉”,即读取到(或缺少)先前查询中不存在的数据。

幻读与脏读、不可重复读的区别

  1. 脏读:事务读取了另一个事务未提交的数据,可能会读到错误结果。
  2. 不可重复读:事务在两次读取中,读到的数据被其他事务修改了,数据值不同。
  3. 幻读:事务在两次读取中,结果集的记录条数或范围变化了,比如多了新记录或少了某些记录。

举例说明
假设有一个数据库表 employees,内容如下:

id name salary
1 Alice 5000
2 Bob 4000
3 Charlie 3000

场景
事务A执行如下查询:

SELECT * FROM employees WHERE salary > 3000;

结果为:

id name salary
1 Alice 5000
2 Bob 4000

这时,事务B插入了一条新记录:

INSERT INTO employees (id, name, salary) VALUES (4, 'David', 4500);

如果事务A再次执行相同的查询操作,结果会变为:

id name salary
### MySQL 中的间隙锁(Gap Lock)工作原理 在 InnoDB 存储引擎中,间隙锁是一种重要的锁定机制,它主要作用于索引记录之间的“间隙”,以及第一条记录之前和最后一条记录之后的位置[^3]。这种锁的存在是为了止其他事务在这些位置插入新的数据行,从而避免发生现象。 #### 1. **间隙锁的作用** 间隙锁的主要目的是为了支持更高的事务隔离级别——可重复(Repeatable Read)。在这种隔离级别下,通过使用间隙锁可以阻止其他事务向当前事务正在扫描的数据范围中插入新记录,进而有效预的发生[^4]。 #### 2. **间隙锁的工作方式** 当一个事务执行某些特定类型的查询语句时,如果启用了间隙锁,则会自动对符合条件的索引区间施加该种锁模式。具体来说,在 SELECT ... FOR UPDATE 或者 SELECT ... LOCK IN SHARE MODE 这样的操作过程中,除了会对具体的记录加上行级锁外,还会对其周围的空白区域应用间隙锁。 例如考虑如下场景: 假设表 `t` 的主键列上有这样的几条记录:(1, 'a'), (4, 'b') 和 (7, 'c') 并且我们运行了一个带有条件 WHERE id BETWEEN 0 AND 5 的更新命令。此时不仅会对已存在的记录 `(1,'a')`, `(4,'b')` 加上 X 锁(X表示独占),而且也会对该范围内不存在但可能被插入的新值比如 `id=2`,`id=3` 所处的空间即所谓的 “gap” 施加 Gap Locks. ```sql -- 此SQL会在满足WHERE子句的结果集上的每行添加X锁, -- 同时对于未命中任何现有行但是落入指定区间的虚拟空间也附加相应的GAP locks. UPDATE t SET col = val WHERE id BETWEEN 0 AND 5; ``` 上述例子展示了如何利用间隙锁保护整个数值序列不受到外部干扰的情况下的修改行为[^2]. #### 3. **间隙锁的应用场景** - 高并发环境下的数据一致性维护; - 当应用程序需要确保某个时间段内的连续编号不会被打断或者重叠的时候非常有用; - 对于那些依赖数据库自动生成唯一标识符的企业解决方案而言至关重要; 需要注意的是虽然间隙锁有助于增强系统的稳定性和可靠性,但它同时也可能导致死锁风险增加以及其他负面影响如降低整体吞吐量等问题因此应该谨慎评估何时何地采用此类技术手段[^1]. ### 总结 综上所述,MySQL中的间隙锁作为保障事务间数据一致性的关键技术之一发挥了不可替代的作用。通过对尚未存在却有可能成为未来目标对象所在之处预先声明所有权的方式实现了更为精细粒度级别的访问权限管理方案设计思路.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值