MySQL中的可重复读(Repeatable Read)和快照读(Snapshot Read)是事务隔离级别与并发控制的核心机制,具体解析如下:
1. 可重复读(Repeatable Read)
定义:
可重复读是MySQL的默认隔离级别(RR),确保同一事务内多次读取同一数据的结果一致,即使其他事务修改了这些数据。
实现原理:
- MVCC(多版本并发控制):通过为每行数据记录多个版本(版本链),事务读取时基于事务启动时的快照(ReadView)选择可见的历史版本,而非最新数据。
- ReadView机制:
- 在RR级别下,事务首次执行快照读时生成ReadView,后续所有快照读复用该ReadView,确保数据视图一致。
- ReadView包含活跃事务ID集合(m_ids)、最小事务ID(min_trx_id)等字段,用于判断数据版本的可见性。
特点:
- 解决了脏读和不可重复读问题,但未完全解决幻读(Phantom Read)。例如,事务中多次查询可能看不到其他事务插入的新记录,但更新操作可能因新记录的插入导致幻读。
- 通过间隙锁(Gap Lock)和Next-Key Lock防止幻读,但仅对可重复读级别有效。
2. 快照读(Snapshot Read)
定义:
快照读是事务读取数据的默认方式(如普通SELECT语句),通过MVCC获取数据的历史版本,不加锁,从而提升并发性能。
实现原理:
- 版本链与Undo Log:每行数据保存多个版本,通过Undo Log构建版本链。快照读根据ReadView筛选可见版本。
- 可见性规则:
- 若数据版本的事务ID
< ReadView.min_trx_id,则可见(已提交)。 - 若事务ID
> ReadView.max_trx_id,则不可见(未来事务)。 - 若事务ID在
m_ids集合中,需检查是否已提交。
与当前读的区别:
- 当前读(Current Read):读取最新数据并加锁(如
SELECT ... FOR UPDATE),用于INSERT、UPDATE、DELETE等操作,确保数据一致性。 - 关键差异:
- 快照读不阻塞写操作,当前读会加锁阻塞其他事务。
- 快照读依赖历史版本,当前读获取最新版本。
3. 隔离级别与快照读的关系
- 读已提交(RC):每次快照读生成新的ReadView,可见数据为已提交版本,无法完全避免不可重复读。
- 可重复读(RR):首次快照读生成ReadView并复用,确保事务内数据一致性,但需结合锁机制解决幻读。