区分 ​快照读(Snapshot Read)​​ 和 ​当前读(Current Read)​​

1. 关键概念区分

(1) 快照读(Snapshot Read)
  • 操作:普通 SELECT语句(不加锁)。
  • 原理:基于事务开始时创建的 一致性读视图(Consistent Read View),读取数据的历史版本
  • 效果:在 RR(可重复读) 隔离级别下:同一事务内多次快照读,结果完全一致(即使其他事务提交了新数据)。✅ 天然免疫幻读(因为看不到新插入的数据)。
(2) 当前读(Current Read)
  • 操作:加锁的读操作(如 SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODE)或写操作(UPDATE/DELETE/INSERT)。
  • 原理:读取最新提交的数据,并加锁保护数据一致性。
  • 风险:在 RR(可重复读) 隔离级别下:可能触发幻读(需依赖 Next-Key Lock 防幻读)。

2. 幻读发生的条件

幻读仅发生在当前读的场景中!以下是经典幻读流程:

时间事务A(RR隔离级别)事务B(已提交)
t1SELECT * FROM t WHERE age=3; (快照读,返回空)
t2INSERT INTO t (id, age) VALUES (10, 3); 提交
t3SELECT * FROM t WHERE age=3;快照读,仍返回空
t4UPDATE t SET name='test' WHERE age=3;当前读,发现事务B插入的 age=3的记录)
t5SELECT * FROM t WHERE age=3;快照读,仍返回空
t6SELECT * FROM t WHERE age=3 FOR UPDATE;当前读,返回 id=10的新记录) → 幻读!
关键分析:
  1. t1 & t3:快照读始终看不到新数据(无幻读)。
  2. t4UPDATE是当前读,会看到事务B提交的新数据age=3, id=10),并尝试更新它(此时事务A感知到新数据)。
  3. t6:加锁读(FOR UPDATE)是当前读,直接看到新数据 → 事务A发现“凭空出现”的记录 → 幻读发生

⚠️ 重点:事务A的 快照读始终一致,但 当前读会破坏一致性


3. InnoDB 如何解决幻读?

RR(可重复读) 隔离级别下,InnoDB 通过 Next-Key Lock(临键锁) 防止当前读的幻读:

  • 当事务A执行 SELECT ... FOR UPDATE WHERE age=3时:在 age索引的 (3,3)记录上加 S锁(记录锁)。在 (3,3)(7,7)之间的间隙加 GAP锁(间隙锁)。
  • 效果:其他事务无法插入新的 age=3的记录(如 (3,10))。事务A的当前读始终返回相同结果(无幻读)。

4. 总结:幻读的本质

操作类型是否可能幻读原因
快照读(普通SELECT)❌ 不可能MVCC 读取历史版本,无视新数据
当前读(加锁读/写操作)✅ 可能(不加锁时)读取最新数据,可能看到其他事务的插入
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jessie_waverider

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值