Skip to content

可重复读解决了什么问题?

约 703 字大约 2 分钟

MySQL字节

2025-03-20

⭐ 题目日期:

字节 - 2024/12/17

📝 题解:

MySQL 的 可重复读(Repeatable Read) 隔离级别主要解决了以下两类并发事务问题:


1. 脏读(Dirty Read)

  • 问题:事务 A 读取了事务 B 未提交的修改,若事务 B 回滚,事务 A 读到的数据是无效的。
  • 解决:在可重复读隔离级别下,事务只能读取其他事务 已提交 的数据。

2. 不可重复读(Non-Repeatable Read)

  • 问题:事务 A 多次读取同一数据,事务 B 在此期间修改并提交了该数据,导致事务 A 前后读取结果不一致。
  • 解决:通过 多版本并发控制(MVCC),事务 A 在生命周期内看到的是 一致性视图(快照),不受其他事务提交的影响。

3. 幻读(Phantom Read)(MySQL 增强解决)

  • 问题:事务 A 读取某个范围的数据后,事务 B 插入或删除了该范围内的数据,导致事务 A 再次读取时出现“幻影行”。
  • 解决:MySQL 在可重复读隔离级别下,通过 Next-Key Locks(行锁 + 间隙锁)锁定查询范围,禁止其他事务插入或删除范围内的数据。

4. 实现原理

  • MVCC(多版本并发控制)
    • 每个事务启动时分配一个唯一的事务 ID(tx_id)。
    • 每条记录包含隐藏字段 DB_TRX_ID(最后修改该记录的事务 ID)和 DB_ROLL_PTR(回滚指针,指向历史版本)。
    • 事务只能读取 DB_TRX_ID 小于等于自身 tx_id 且已提交的记录。
  • Next-Key Locks
    • 锁定索引记录和间隙(例如 WHERE id > 10,锁定 (10, +∞) 范围),防止其他事务插入或删除。

5. 对比其他隔离级别

隔离级别脏读不可重复读幻读实现机制
读未提交✔️✔️✔️无锁,直接读最新数据
读已提交✔️✔️MVCC,每次读最新提交数据
可重复读(默认)❌(MySQL 解决)MVCC + Next-Key Locks
串行化所有操作加锁,完全串行

6. 适用场景

  • 可重复读的典型场景
    • 需要事务内多次读取同一数据的一致性(如对账、统计)。
    • 允许高并发但需避免幻读(如订单状态更新)。
  • 不适用场景
    • 对数据实时性要求极高(需用读已提交)。
    • 极高频写入导致锁竞争激烈(需权衡一致性)。

7. 总结

  • 解决的问题
    1. 脏读:确保事务只读已提交的数据。
    2. 不可重复读:通过 MVCC 提供一致性视图。
    3. 幻读(MySQL 增强):通过 Next-Key Locks 锁定范围。
  • 核心优势:在并发性能和数据一致性之间取得平衡,是 MySQL InnoDB 默认隔离级别的原因。