可重复读中的不一致


10

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

可重复读取模式提供了严格的保证,即每个事务都能看到数据库的完全稳定的视图。但是,此视图不一定总是与同一级别的并发事务的某些串行(一次一个)执行一致。例如,即使是该级别的只读事务,也可能会看到更新了控制记录以显示批次已完成,但是看不到逻辑上属于该批次的详细记录之一,因为它读取了控制记录的较早版本。 。如果不谨慎使用显式锁来阻止冲突的事务,则试图通过在此隔离级别运行的事务来强制执行业务规则的尝试将无法正常工作。

这不是幻像读取吗,在可重复读取模式下是不可能的?

该文档说,在可重复读取事务中的查询在事务开始时看到快照,那么查询怎么可能读取不一致的数据?

Answers:


5

这是我对该部分的阅读。我承认这令人困惑。

假设我有两个表:

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可以查看批处理标题信息,但无需等待详细信息的提交即可通知用户未找到任何记录。现在,如果您的批次和详细信息完全在同一笔交易中,那么这绝对不是问题。

这与可序列化有所不同,在可序列化之前,您希望等待前一个插入操作完成并提交或回滚,然后再确定是否通知用户未找到行。


3

PostgreSQL Wiki中有一个文档,该文档显示了在REPEATABLE READ事务隔离级别中某些事务组合可能发生的一些问题,以及从PostgreSQL版本9.1开始在SERIALIZABLE事务隔离级别中如何避免这些问题。

它还包括一个示例,说明可重复的READ级READ-ONLY事务如何读取不一致的数据。


@dezso您可能对此感兴趣
2015年

1

原则上,可以在“可重复读取”隔离级别中进行幻像读取(请确保不要将其与不可重复的读取混淆)。但是,当您选择“可重复读取”时,Postgresql的实际行为比标准(几乎是“可序列化”隔离)要强,因此,事实上,您不会有幻像读取。文件

当选择级别Read Uncommitted时,您实际上会获得Read Committed,并且在Repeatable Read的PostgreSQL实现中幻像读取是不可能的,因此实际的隔离级别可能比您选择的严格。

现在,该警告“该视图不一定总是与同一级别的并发事务的某个串行(一次一个)执行一致”?我认为(我不确定),这意味着“从外部”快照(在事务开始时固定)最终可以包含来自其他事务的行,但不能包含来自同一事务的其他行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.