在可重复读的情况下存在不一致性。

http://www.postgresql.org/docs/9.2/static/transaction-iso.html

可重复读模式提供了一个严格的保证,即每个事务都能看到数据库的完全稳定的视图。然而,这个视图不一定总是与同一级别的并发事务的串行(逐个执行)执行一致。例如,即使在这个级别上的只读事务也可能会看到一个控制记录被更新以显示批处理已完成,但却没有看到逻辑上属于该批处理的详细记录之一,因为它读取了控制记录的早期版本。在这个隔离级别下运行的事务试图通过强制执行业务规则来阻止冲突事务,但很可能无法正常工作,除非仔细使用显式锁来阻塞冲突事务。 这不就是幻读吗?在可重复读模式下不可能出现幻读吗? 文档中说,在可重复读事务中的查询会看到事务开始时的快照,那么查询如何可能读取不一致的数据呢?
3个回答

这是我对那个部分的理解。我承认它很令人困惑。 假设我有两个表格:
CREATE TABLE batch (
   id serial not null unique,
   control_code text primary key,
   date_posted date not null default now()
);

CREATE TABLE details (
   batch_id int not null references batch(id),
   description text,
   primary key(batch_id, description)
);
现在,假设我们在不同的事务中插入批次和详细记录。会话1插入一个批次并开始插入详细信息,但在完成之前,会话2启动了。会话2可以看到批次标题信息,但不会等待详细信息提交后再通知用户找不到记录。如果您的批次和详细信息完全在同一个事务中,那么这就不是一个问题。 这与串行化不同,串行化会等待前一个插入完成并提交或回滚,然后再确定是否通知用户找不到行。

在PostgreSQL Wiki中有一个文档,展示了在REPEATABLE READ事务隔离级别下,某些事务组合可能出现的问题,以及从PostgreSQL 9.1版本开始,在SERIALIZABLE事务隔离级别下如何避免这些问题。 它还包含一个示例,说明了一个REPEATABLE READ级别的只读事务如何读取不一致的数据。

@dezso 你可能对这个感兴趣 - Aleksei Chernenkov

幻读(请务必不要将其与不可重复读混淆)在“可重复读”隔离级别下是可能发生的...原则上。但是,当您选择“可重复读”时,PostgreSQL的实际行为比标准更强大(几乎等同于“串行化”隔离级别),因此实际上您不会遇到幻读。文档: 引用: 当您选择“未提交读”级别时,实际上获得的是“已提交读”,在PostgreSQL的“可重复读”实现中,幻读是不可能发生的,因此实际隔离级别可能比您选择的更严格。 那么,关于这个警告“该视图不一定始终与同一级别的并发事务的某些串行(逐个执行)执行保持一致”,我认为(不确定)它意味着从“外部”(在事务开始时固定)获取的快照最终可能包含来自其他事务的行,但可能无法包含同一事务中的其他行。