PostgreSQL REPEATABLE READ隔离级别异常现象及底层逻辑问询
PostgreSQL REPEATABLE READ隔离级别特殊现象的实现逻辑
现象说明
- 以
REPEATABLE READ隔离级别启动事务A但未执行任何操作时,启动事务B并提交新数据,事务A查询时能看到该新增数据 - 若事务A启动后先执行过任意查询操作,后续事务B提交的数据则无法被事务A查询到
- 该现象看似与官方文档描述冲突:
可重复读隔离级别仅能看到事务开始前已提交的数据;它永远不会看到未提交的数据或事务执行期间并发事务提交的更改。
核心实现逻辑
PostgreSQL的REPEATABLE READ隔离级别基于快照隔离实现,但快照的创建时机并非事务启动时,而是事务内第一条读取数据的语句执行时:
- 执行
BEGIN启动REPEATABLE READ事务时,数据库不会立即生成快照,仅标记事务的隔离级别 - 当事务内第一次执行需要读取数据的语句(如
SELECT、INSERT ... RETURNING等)时,才会生成当前时刻的快照——该快照记录了所有已提交事务的状态 - 事务后续的所有读取操作都将基于这个固定快照,不会再生成新的快照
现象拆解
- 未执行查询的事务A:启动后未生成快照,第一次查询时会生成新快照,此时事务B已提交的数据已被纳入快照范围,因此能被查询到
- 执行过查询的事务A:第一次查询时已生成快照,后续查询都基于该快照,事务B之后提交的数据不在快照覆盖范围内,因此无法被看到
文档表述的误解点
官方文档中提到的“事务开始”,实际指的是快照创建的时间点(即事务内首次查询的时间),而非BEGIN语句的执行时间。这是文档表述易产生歧义的地方,但实际实现完全符合快照隔离的设计逻辑。
内容的提问来源于stack exchange,提问作者Hyunhum Cho
相关产品推荐
相关产品推荐

