单条SELECT查询在READ COMMITTED与REPEATABLE READ事务中的执行差异
READ COMMITTED vs REPEATABLE READ for Single-SELECT Transactions
好问题!咱们直接拆解这个场景——当你的事务里只有单条SELECT查询时,这两个隔离级别确实存在一些细微但值得留意的差异,我来给你逐一说明:
核心一致点
首先,大多数常规场景下(比如你直接执行BEGIN; SELECT ...; COMMIT;这种一次性事务),两者的查询结果是完全一致的:
- 不管是READ COMMITTED(PostgreSQL默认)还是REPEATABLE READ,这条SELECT都会基于语句执行瞬间创建的快照来返回数据,只能看到在这之前所有已提交事务的修改。
- 两者都用MVCC(多版本并发控制)来避免加锁,不会阻塞其他事务的读写操作。
关键差异点
1. 时间类系统函数的返回值
这是最容易感知的差异:
- 在READ COMMITTED下,
CURRENT_TIMESTAMP、NOW()、CURRENT_DATE这类时间函数,返回的是这条SELECT语句执行时的时间。 - 在REPEATABLE READ下,如果你的事务是先执行
BEGIN,间隔一段时间后才运行这条SELECT,那么这些函数返回的是事务启动(BEGIN执行)时的时间。举个例子:你执行
BEGIN;后喝了杯咖啡(等了10分钟),再执行SELECT CURRENT_TIMESTAMP;。READ COMMITTED会返回10分钟后的当前时间,而REPEATABLE READ会返回你执行BEGIN那一刻的时间。
2. 快照的生命周期(底层逻辑差异)
- READ COMMITTED的快照是语句级的:这条SELECT执行完,快照就会被销毁(如果事务有后续语句会重新创建新快照,但这里没有)。
- REPEATABLE READ的快照是事务级的:一旦在这条SELECT执行时创建,就会持续保留到事务结束(即使只有这一条查询)。不过这个差异不会影响你当前SELECT的结果,只是底层机制的不同。
极端场景验证
哪怕是扫描超大表的长时间查询,两者的行为也一致:整个查询过程中都会使用同一个快照,不会看到查询执行期间其他事务提交的修改——因为READ COMMITTED的语句级快照和REPEATABLE READ的事务级快照,在单条查询的语境下是等价的。
内容的提问来源于stack exchange,提问作者Lesly O
相关产品推荐
相关产品推荐

