READ COMMITTED(读已提交)是数据库事务的四种标准隔离级别之一(其余为:READ UNCOMMITTED、REPEATABLE READ、SERIALIZABLE)
READ COMMITTED(读已提交)是数据库事务的四种标准隔离级别之一(其余为:READ UNCOMMITTED、REPEATABLE READ、SERIALIZABLE)。其核心语义是:一个事务只能读取到其他事务已经成功提交(COMMIT)的数据,不能读取未提交的中间状态(即避免脏读)。
✅ 优点:
- 防止脏读(Dirty Read):不会读到其他事务回滚前的临时修改。
⚠️ 局限性:
- 存在不可重复读(Non-Repeatable Read):同一事务中,对同一行数据多次读取,可能因其他事务在两次读之间提交了更新(UPDATE)或删除(DELETE),导致结果不一致。
- 存在幻读(Phantom Read):同一事务中,执行相同范围查询(如
SELECT * FROM t WHERE id > 10),可能因其他事务插入/删除符合该条件的新行而返回不同数量或内容的记录(注意:是否视为幻读取决于具体数据库实现;例如 PostgreSQL 在 READ COMMITTED 下允许幻读,而 Oracle 通过多版本控制(MVCC)避免了幻读但仍有不可重复读)。
实现机制(典型如 PostgreSQL、Oracle、SQL Server 默认):
- 基于多版本并发控制(MVCC),每个查询看到的是事务开始时刻已提交的最新快照;
- 或基于行级锁 + 读锁释放时机(如 SQL Server 的锁机制),读操作加共享锁,但读完立即释放,不持续到事务结束 → 导致后续读可能看到新提交值。
示例(不可重复读):
-- 事务A(READ COMMITTED)BEGIN;SELECTbalanceFROMaccountWHEREid=1;-- 返回 1000-- 此时事务B执行并提交:UPDATE account SET balance = 1500 WHERE id = 1;SELECTbalanceFROMaccountWHEREid=1;-- 可能返回 1500(不可重复读!)COMMIT;READ COMMITTED 与 REPEATABLE READ 在防止不可重复读方面的本质区别在于“一致性快照(consistent snapshot)的创建时机和作用范围不同”:
✅READ COMMITTED:
- 每次 SELECT 都建立一个新快照(以该查询开始时刻已提交的最新数据为准);
- 同一事务内多次读取同一行,若中间有其他事务提交了修改,则后续 SELECT 可能读到新值 →无法防止不可重复读;
- 快照粒度是语句级(statement-level)。
✅REPEATABLE READ:
- 整个事务第一次 SELECT 时创建一个全局快照,并在整个事务生命周期内复用该快照;
- 后续所有读操作(包括相同或不同 SELECT)均基于此初始快照,无视其他事务后续的提交 →可防止不可重复读;
- 快照粒度是事务级(transaction-level)。
📌 补充说明(关键实现差异):
- PostgreSQL / Oracle(MVCC 实现):REPEATABLE READ 级别下严格复用事务启动时的快照,不仅防不可重复读,通常也防幻读(因新插入行的事务ID大于快照时间点,不被可见);
- MySQL InnoDB(MVCC + Next-Key Locks):REPEATABLE READ 级别下虽用事务启动快照防不可重复读,但仍可能遭遇幻读(如 INSERT 新行),因此通过间隙锁(Gap Lock)和临键锁(Next-Key Lock)在 DML 操作时阻塞插入,从而在大多数场景下间接避免幻读(但纯快照 SELECT 仍可能幻读,需配合加锁读如
SELECT ... FOR UPDATE)。
简言之:
READ COMMITTED 的“一致性”止于单条语句;REPEATABLE READ 的“一致性”贯穿整个事务——这是二者防不可重复读能力差异的根本原因。
