MySql理解RR(可重复读)事务隔离级别

demo,理解mysql的可重复读隔离级别,当前读、快照读的区别

如下图,表sys_user中我同时开启三个事务连接:
在这里插入图片描述

session1:
在这里插入图片描述
当session1开启事务时,mysql使用快照读保存事务开始前的数据,所以这条事务未提交前,查询的结果都是最开始保存的数据。
无论session2还是session3,查询结构都是0。

session2

在这里插入图片描述
session2开启事务,执行一条update语句,mysql开始当前读,对当前修改的行加锁。此时查询出来的值是最新值。
查询结果是最新值。
session3
在这里插入图片描述
session3执行语句,此时它也想要修改数据,由于2还没提交事务,它只能等待2释放锁。

ps:如果session3先执行,他是自动提交事务的。session2就会在3的基础上在更新。

<think>嗯,用户的问题是关于MySQLRR隔离级别下幻的发生条件和场景。从引用内容来看,用户已经查阅了一些资料,但可能对幻RR级别下的具体表现还有疑惑。 用户提到的引用内容很有价值,特别是引用[3]和引用[5]中提到的"通过更新操作导致幻"的场景很关键。这正好解释了为什么RR级别不能完全避免幻——因为快照当前的机制不同。 在组织回答时,我需要重点区分两种场景:一种是标准的快照不会出现幻,这是RR级别保证的;另一种是用户操作引发的特殊情况,比如先更新后查询,这时候MVCC机制会让更新后的新记录对当前事务可见。 用户可能还关心实际开发中如何避免这种情况,所以最后要给出实用建议。考虑到用户是技术人员,可以适当使用术语,但要把GAP锁、next-key lock这些机制的作用说清楚。 从引用[4]提到的github讨论来看,这个问题确实存在很多争议,回答时要明确指出InnoDB的实现和SQL标准的差异,避免用户混淆。</think>在 MySQL 的 `REPEATABLE READ` (RR) 隔离级别下,**幻现象并非完全被杜绝**。其发生与否取决于具体的操作类型和场景。以下是幻可能发生的条件和场景分析: --- ### **一、RR级别下通常避免幻的机制** 1. **快照 (Snapshot Read)**: * 普通 `SELECT` 语句基于 **MVCC (多版本并发控制)** 实现。 * 事务首次执行 `SELECT` 时生成 **ReadView**,后续查询均基于此快照,**不会看到其他事务提交的新数据**,因此不会因新插入数据产生幻[^1][^3][^5]。 2. **当前 (Current Read)**: * 通过 `SELECT ... FOR UPDATE` 或 `SELECT ... LOCK IN SHARE MODE` 加锁。 * InnoDB 通过 **GAP锁(间隙锁)** 和 **Next-Key Lock** 锁定查询范围,阻止其他事务在范围内插入新数据,从而避免幻[^2][^4]。 --- ### **二、RR级别下幻发生的场景** #### **场景1:先快照 &rarr; 其他事务插入 &rarr; 当前** ```sql -- 事务A (RR级别) BEGIN; SELECT * FROM t WHERE id > 100; -- 快照:返回空结果(假设无数据) -- 事务B 插入并提交: INSERT INTO t (id) VALUES (101); COMMIT; SELECT * FROM t WHERE id > 100 FOR UPDATE; -- 当前:返回id=101(幻发生) ``` **原因**: 第一次快照未加锁,事务B可插入数据;第二次当前(加锁)会取最新数据,导致幻[^2][^4]。 --- #### **场景2:先快照 &rarr; 其他事务插入 &rarr; 更新操作 &rarr; 快照** ```sql -- 事务A (RR级别) BEGIN; SELECT * FROM t WHERE id > 100; -- 快照:返回空 -- 事务B 插入并提交: INSERT INTO t (id) VALUES (101); COMMIT; UPDATE t SET name='a' WHERE id > 100; -- 更新操作,影响新插入的行 SELECT * FROM t WHERE id > 100; -- 快照:返回id=101(幻发生) ``` **原因**: 更新操作属于"当前写",会**强制取最新数据**(包括其他事务已提交的插入)。更新后,新记录的 `trx_id` 被修改为事务A的ID,后续快照会认为这是"自身修改的数据",因此可见[^3][^5]。 --- ### **三、幻的本质与解决关键** | **操作类型** | **是否可能幻** | **原因与机制** | |---------------------|------------------|-------------------------------------------| | 纯快照 (`SELECT`) | ❌ 否 | MVCC 快照隔离旧数据 | | 当前 (加锁`SELECT`) | ❌ 否 | GAP锁/Next-Key Lock 阻塞插入 | | **混合操作** | ✅ 是 | 更新操作使新数据对当前事务可见 | **核心结论**: RR 级别通过 **MVCC 解决快照的幻**,通过 **GAP锁解决当前的幻**。但若事务中**混合快照与更新操作**,可能因更新操作"污染"快照而触发幻[^3][^5]。 --- ### **四、彻底避免幻的方案** 1. **升级隔离级别**: 使用 `SERIALIZABLE`,所有查询默认加锁(性能代价高)。 2. **显式加锁**: 在首次查询时直接使用 `SELECT ... FOR UPDATE` 锁定范围[^2][^4]。 3. **优化事务逻辑**: 避免在事务中混合快照与更新操作。 > **引用说明**: > RR 级别下幻的发生依赖于操作序列和锁机制[^1][^2],MVCC 和 GAP 锁是防护基础[^4],但更新操作会突破快照隔离[^3][^5]。 --- **相关问题** 1. RR 隔离级别下,GAP 锁如何防止新数据插入? 2. 为什么更新操作会导致 RR 级别出现幻? 3. 如何设计事务流程以避免 RR 级别的幻
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值