温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

MVCC能避免幻读问题吗

发布时间:2026-09-09 20:01:03 来源:亿速云 阅读:88 作者:小樊 栏目:数据库

简短结论先给出:在 MySQL InnoDB 的“读已提交(RC)”隔离级别下,MVCC 不能避免幻读;在“可重复读(RR)”隔离级别下,MVCC 本身能避免「快照读」的幻读,但并不能完全避免「当前读」的幻读,InnoDB 是通过 MVCC + Next-Key Lock 一起解决幻读问题的。

下面分层说明。


1. 什么是幻读

幻读指的是:

同一个事务中,两次相同的范围查询,第二次查到了第一次没有看到的新插入行。

例如:

SELECT * FROM t WHERE age > 20;
-- 另一个事务插入 age=25 并提交
SELECT * FROM t WHERE age > 20;

第二次查询多了一行,就是幻读。


2. MVCC 能做什么

MVCC(多版本并发控制)核心机制:

  • 每行数据有隐藏的 事务ID 和 回滚指针
  • 读操作根据**事务开启时的快照(Read View)**读取可见版本
  • 普通 SELECT 是快照读

在 RR(可重复读) 下:

  • 事务第一次读时生成 Read View
  • 后续快照读都复用这个 Read View
  • 其他事务新插入并提交的数据,对当前事务不可见

✅ 所以:

RR 下,MVCC 能避免快照读中的幻读


3. MVCC 不能做什么

MVCC 只解决「读」的问题,不解决「写」的问题。

以下情况是当前读:

SELECT ... FOR UPDATE;
SELECT ... LOCK IN SHARE MODE;
UPDATE / DELETE / INSERT;

当前读会读取最新已提交数据,不走快照。

举例(RR + 当前读):

SELECT * FROM t WHERE age > 20 FOR UPDATE;
-- 另一事务插入 age=25 并提交
SELECT * FROM t WHERE age > 20 FOR UPDATE;

此时可能看到新行 → 幻读

❌ MVCC alone 不能避免这种情况


4. InnoDB 如何真正解决幻读

在 RR 下,InnoDB 使用:

  • MVCC:解决快照读幻读
  • Next-Key Lock(间隙锁 + 记录锁):解决当前读幻读

例如:

SELECT * FROM t WHERE age > 20 FOR UPDATE;

会锁住:

  • 满足条件的记录
  • 这些记录之间的「间隙」

其他事务无法插入 age > 20 的新行
→ 当前读也不会幻读


5. 不同隔离级别总结

隔离级别 MVCC 幻读是否可能
Read Uncommitted ❌ 可能
Read Committed (RC) ✅ 可能(每次新快照)
Repeatable Read (RR) ✅ 快照读不会,当前读靠锁
Serializable ✅ 不会(强制串行)

6. 一句话总结

MVCC 能避免“快照读”的幻读,但不能单独避免“当前读”的幻读;MySQL InnoDB 在 RR 下是靠 MVCC + Next-Key Lock 共同避免幻读的。

如果你愿意,我也可以用事务执行时序图或具体 SQL 示例来演示幻读是怎么发生的。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI
助
手