温馨提示×

温馨提示×

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

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

MVCC在事务中怎么工作

发布时间:2026-07-15 04:25:53 来源:亿速云 阅读:98 作者:小樊 栏目:数据库

MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种通过保存数据多个版本来实现高并发、非阻塞读的机制,广泛用于 MySQL(InnoDB)、PostgreSQL 等数据库。下面我用原理 + InnoDB 示例 + 事务流程来说明 MVCC 在事务中是如何工作的。


一、MVCC 的核心思想

读不加锁,写不阻塞读

MVCC 的核心思想是:

  • 同一行数据可以有多个版本
  • 不同事务根据自身“可见性规则”读取不同版本
  • 写操作创建新版本,而不是直接覆盖旧数据

二、InnoDB 中 MVCC 的关键结构

1️⃣ 每行记录隐藏字段

InnoDB 的聚簇索引记录中,除了你定义的列,还有:

字段 含义
DB_TRX_ID 最后修改该行的事务 ID
DB_ROLL_PTR 回滚指针,指向 undo log
DB_ROW_ID 行 ID(无主键时自动生成)

2️⃣ undo log(版本链)

  • 每次 UPDATE / DELETE:
    • 旧版本数据写入 undo log
    • 新版本记录 roll_ptr 指向旧版本
  • 多个版本通过 roll_ptr 形成版本链
最新版本 → 旧版本 → 更旧版本 → ... → undo log

3️⃣ Read View(一致性视图)

事务在第一次读时生成 Read View(RC 每次读,RR 第一次读)

Read View 包含:

  • m_ids:当前活跃事务 ID 列表
  • min_trx_id:最小活跃事务 ID
  • max_trx_id:下一个将被分配的事务 ID
  • creator_trx_id:当前事务 ID

三、MVCC 如何判断版本是否可见?

判断规则(重点)

对于某行记录的 DB_TRX_ID:

  1. 小于 min_trx_id
    • ✅ 已提交,可见
  2. 大于等于 max_trx_id
    • ❌ 未来事务,不可见
  3. 在 [min_trx_id, max_trx_id) 之间
    • 若在 m_ids 中 → ❌ 活跃事务,不可见
    • 若不在 → ✅ 已提交,可见
  4. 等于 creator_trx_id
    • ✅ 自己改的,可见

如果当前版本不可见 → 沿 undo log 找上一个版本,继续判断。


四、MVCC 在事务中的完整工作流程(示例)

示例表

CREATE TABLE account (
  id INT PRIMARY KEY,
  balance INT
);

初始数据

id balance
1 100

时间点 1:事务 A(TRX_ID = 100)

START TRANSACTION;
SELECT * FROM account WHERE id = 1;
  • 生成 Read View
  • 当前数据版本 TRX_ID < min_trx_id
  • ✅ 读到 balance = 100

时间点 2:事务 B(TRX_ID = 101)

START TRANSACTION;
UPDATE account SET balance = 200 WHERE id = 1;
COMMIT;
  • 创建新版本:
    • TRX_ID = 101
    • undo log 保存 balance = 100

时间点 3:事务 A 再次读取

SELECT * FROM account WHERE id = 1;
  • 使用同一个 Read View
  • 新版本 TRX_ID = 101:
    • 在活跃事务列表中
    • ❌ 不可见
  • 沿 undo log 找到旧版本
  • ✅ 仍然读到 balance = 100

✅ 可重复读(RR)


五、RC 与 RR 下 MVCC 的区别

隔离级别 Read View 创建时机
READ COMMITTED 每次 SELECT 创建
REPEATABLE READ 事务中第一次 SELECT 创建

所以:

  • RC:能读到其他事务已提交的最新数据
  • RR:整个事务看到同一份快照

六、MVCC 的适用场景与限制

✅ 适合

  • 高并发读
  • 读多写少
  • 普通 SELECT

❌ 不适合 / 不生效

  • UPDATE / DELETE(会加锁)
  • SELECT … FOR UPDATE
  • 当前读(Current Read)

七、一句话总结

MVCC 通过 undo log 保存历史版本,通过 Read View 判断版本可见性,让事务在不加锁的情况下读到一致性数据。

如果你愿意,我可以:

  • 用 PostgreSQL 的 MVCC 对比讲解
  • 画一张 版本链 + Read View 示意图
  • 结合 幻读 / 当前读 / Next-Key Lock 深入讲
向AI问一下细节

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

AI
助
手