在MySQL的InnoDB存储引擎中,Read View 是一种用于实现事务隔离级别的机制。本文将探讨 Read View 在不同事务隔离级别下的应用方式,以及它如何影响数据的一致性和可见性。
Read View 的作用
Read View 主要应用于 Repeatable Read (RR) 和 Read Committed (RC) 两种事务隔离级别中,以决定哪些数据对事务可见。而在 Read Uncommitted (RU) 和 Serializable 两种隔离级别下,则不需要使用 Read View。
Read Uncommitted (RU)
特点:允许事务读取未提交的数据,即发生脏读。原因:无需通过 Read View 来限制数据的可见性范围,事务可以自由读取其他事务未提交的数据。
Serializable
特点:提供最高级别的隔离性,确保每次读取都能看到一致的快照。原因:使用锁机制来保证事务之间的串行执行,不需要 Read View 来判断可见性。
RC 和 RR 下的 Read View
RC (Read Committed)生成时机:每次 SELECT 数据前都生成一个新的 Read View。效果:每次查询时都基于最新的数据生成 Read View,因此每次查询可能看到不同的数据版本。RR (Repeatable Read)生成时机:只在第一次读取数据时生成一个 Read View,之后复用同一个 Read View。效果:确保在同一个事务内多次查询同一数据时看到相同的结果,即重复读。
举例说明
假设有一个表 users,包含 id 和 name 字段。初始状态下,表中有一条记录 id=1, name="小明"。现在有三个事务 A、B、C 按照以下顺序执行:
| 事务A(事务ID: 100) | 事务B(事务ID: 200) | 事务C(事务ID: 300) | |
|---|---|---|---|
| T1 | begin | ||
| T2 | begin | begin | |
| T3 | update user set name="小王" where id=1 | ||
| T4 | update user set name="小红" where id=1 | select * from user where id = 1 | |
| T5 | commit | update user set name="小黑" where id=1 | |
| T6 | update user set name="小白" where id=1 | select * from user where id = 1 | |
| T7 | commit | ||
| T8 | select * from user where id = 1 | ||
| T9 | commit | ||
| T10 |
RC 下的 Read View
事务A 将 name 修改为 "小红"。事务B 将 name 修改为 "小白"。事务C 读取 name 的值。RC 下的 Read ViewT4时刻:事务A 和 事务B 都还未提交,此时事务C 读取数据。根据可见性原则,事务C 最终看到的 name 值为 "小明"。T6时刻:事务A 提交,事务C 再次读取数据。此时会生成新的 Read View,根据可见性原则,事务C 最终看到的 name 值为 "小红"。T8时刻:事务B 提交,事务C 再次读取数据。再次生成新的 Read View,根据可见性原则,事务C 最终看到的 name 值为 "小白"。RR 下的 Read ViewT4时刻:与 RC 情况一致,事务C 最终看到的 name 值为 "小明"。T6时刻:事务C 再次读取数据,但 RR 会复用之前的 Read View,因此事务C 仍看到 name 值为 "小明"。T8时刻:事务C 再次读取数据,继续复用之前的 Read View,事务C 仍看到 name 值为 "小明"。
总结通过以上例子可以看出,在 RC 隔离级别下,由于每次查询都会生成新的 Read View,因此可以看到最新的已提交数据。而在 RR 隔离级别下,由于复用了初次查询时生成的 Read View,因此事务内多次查询同一数据时看到的结果始终一致。
这篇文章简洁明了地介绍了 Read View 在不同事务隔离级别下的工作原理,并通过实例帮助读者更好地理解其在实际场景中的应用。希望对您有所帮助!如果需要进一步调整,请随时告知。




