一、SQL Server、Oracle、MySQL 的 Read Committed 实现机制对比
| 数据库 | Read Committed 实现方式 | 是否加锁 | 是否使用快照 | 特点说明 |
|---|---|---|---|---|
| SQL Server | 使用共享锁(S 锁)读提交版本 | ✅ 是 | ❌ 默认不使用快照(除非启用 snapshot isolation) | 读时阻塞写,写也会阻塞读;性能一般 |
| Oracle | 使用 MVCC,多版本机制 | ❌ 否 | ✅ 默认使用一致性读 | 使用 undo 实现快照读,不加锁,性能高 |
| MySQL(InnoDB) | 使用 MVCC + undo log + Read View | ❌ 否 | ✅ 默认使用快照读 | 默认读已提交时快照每次创建一次;性能高 |
🔑 关键词:
- SQL Server 默认靠锁保证一致性;
- Oracle 和 MySQL 默认使用多版本快照(MVCC)机制;
- MySQL 和 Oracle 在 Read Committed 下就使用快照,只是快照作用范围不同。
二、MySQL 和 Oracle 中 Read Committed 与 Repeatable Read 快照机制对比
📌 关键区别
| 特性 | Read Committed | Repeatable Read |
|---|---|---|
| 快照生成时机 | 每次查询前生成新的 Read View | 第一次快照读时生成并复用 |
| 快照作用范围 | 语句级一致性 | 事务级一致性 |
| 是否可重复读 | ❌ 否(数据可能变化) | ✅ 是(数据固定) |
| 幻读 | 可能出现 | InnoDB 会通过 next-key lock 避免 |
| 一致性强度 | 较弱(语句级) | 强(事务级) |
🧪 举例说明(MySQL InnoDB)
情况一:Read Committed
-- 事务 A:
BEGIN;
UPDATE user SET name = 'Bob' WHERE id = 1;
-- 未提交
-- 事务 B:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
SELECT name FROM user WHERE id = 1; -- 第一次查询,生成快照A → 返回 'Alice'
-- 事务 A 提交
SELECT name FROM user WHERE id = 1; -- 第二次查询,生成快照B → 返回 'Bob'
✔ 每次读都生成快照,看的是“当前已提交的版本”。
情况二:Repeatable Read
-- 事务 A:
BEGIN;
UPDATE user SET name = 'Bob' WHERE id = 1;
-- 未提交
-- 事务 B:
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
SELECT name FROM user WHERE id = 1; -- 第一次查询,生成快照A → 返回 'Alice'
-- 事务 A 提交
SELECT name FROM user WHERE id = 1; -- 复用快照A → 仍然返回 'Alice'
✔ 整个事务期间快照不变,确保可重复读。
三、MySQL 中 Read View(快照)生成时机与过程
✅ 快照什么时候生成?
- 在执行第一次需要快照读的语句(在SELECT语句之前就生成了)之前生成。
- Read Committed:每次读前都重新生成快照;
- Repeatable Read:首次 SELECT 时生成一次快照,整个事务复用。
📦 Read View 包含哪些内容?
| 字段 | 说明 |
|---|---|
m_ids[] | 当前活跃的未提交事务 ID |
min_trx_id | 活跃事务中最小的事务 ID |
max_trx_id | 当前系统中尚未分配的下一个事务 ID |
creator_trx_id | 当前执行 SELECT 的事务 ID |
🧠 快照如何判断一行数据是否可见?
每条记录有一个 trx_id(最后修改它的事务 ID):
IF (
trx_id < min_trx_id
AND trx_id ≠ 当前事务 ID
AND trx_id ∉ m_ids[]
)
THEN 可见 ✅
ELSE 不可见 ❌
- 如果该版本由老事务提交 → ✅ 可见
- 如果由活跃事务创建、或未提交 → ❌ 不可见
🪜 快照生成过程简述
- 当前事务执行 SELECT,InnoDB 检查是否需要生成 Read View;
- 从事务系统中读取当前活跃事务列表(m_ids);
- 记录当前事务的 ID 与最小事务 ID;
- 使用这些信息生成 Read View(快照);
- 对每条记录,根据版本链 + Read View 决定是否可见。
🔁 补充:快照读 vs 当前读
| 类型 | 是否走快照 | 是否加锁 | 示例 |
|---|---|---|---|
| 快照读(snapshot read) | ✅ 是 | ❌ 否 | SELECT ... |
| 当前读(current read) | ❌ 否 | ✅ 是 | SELECT ... FOR UPDATE、UPDATE、DELETE |
✅ 总结关键点
- Read Committed:每次读生成快照,读已提交版本,语句级一致性,不可重复读。
- Repeatable Read:第一次读生成快照,事务级一致性,可重复读。
- 快照 ≠ 数据拷贝,是通过 Read View + undo log 实现的视图控制。
- 快照是在 SELECT 等语句执行前生成,用于控制 MVCC 可见性。
- SQL Server 用加锁实现一致性;MySQL/Oracle 用快照机制;性能差异明显。

被折叠的 条评论
为什么被折叠?



