PostgreSQL 隔离级别的行为

Behavior of PostgreSQL isolation levels

我正在阅读PostgreSQL Manual的第13.2节,但发现那里的文字描述不够清楚,并且缺乏示例。

比如下面两段谁在学PostgreSQL就不清楚了:

INSERT with an ON CONFLICT DO UPDATE clause behaves similarly. In Read Committed mode, each row proposed for insertion will either insert or update. Unless there are unrelated errors, one of those two outcomes is guaranteed. If a conflict originates in another transaction whose effects are not yet visible to the INSERT, the UPDATE clause will affect that row, even though possibly no version of that row is conventionally visible to the command."

The Repeatable Read mode provides a rigorous guarantee that each transaction sees a completely stable view of the database. However, this view will not necessarily always be consistent with some serial (one at a time) execution of concurrent transactions of the same level. For example, even a read only transaction at this level may see a control record updated to show that a batch has been completed but not see one of the detail records which is logically part of the batch because it read an earlier revision of the control record.

有人可以举例说明这两段中的内容吗?

有谁知道在哪里可以找到 PostgreSQL 隔离级别行为的正式描述?我正在寻找这个,因为它是一个高级主题,我相信正式的描述将有助于阐明它是如何工作的,从而有助于避免 t运行sactions.

之间的并发错误。

UPDATE:我的另一个疑问是,根据数据库机制决定提交或中止它的方式,可序列化的 t运行saction 是如何处理的,当它可以 运行 与其他隔离级别的其他 t运行 操作同时进行吗?数据库是否决定可序列化 t运行saction 的结果,就好像其他 t运行saction 也是 运行 具有可序列化隔离的?

谢谢

更新 2:到目前为止,关于隔离级别的实现细节,我发现最好的是 PostgreSQL Wiki Serializable Page.

  • READ COMMITTED:每个 SQL 语句都会获取数据库的新快照,因此每个语句都会看到由并发事务一经提交就立即处理。不会出现序列化错误。

  • REPEATABLE READ:事务中的第一条语句对整个事务保留的数据库进行快照,所以所有语句见数据库的相同状态。如果您尝试修改在获取快照后已被并发事务修改的行,则可能会发生序列化错误。这个隔离级别并不比READ COMMITTED.

  • SERIALIZABLE:任何可能导致结果与事务的某些串行执行顺序不一致的事务将被中止序列化错误。可能存在误报。此隔离级别比其他隔离级别更昂贵。

具体问题的答案:

  • INSERT ... ON CONFLICT 在读提交隔离中:

    如果事务 1 已插入一行,但尚未提交,事务 2 运行 INSERT ... ON CONFLICT 将等待直到事务 1 已提交或回滚,然后根据需要更新或插入。不会发生约束冲突。

  • 批处理作业和 REPEATABLE READ:

    这一段是黑暗的;忽略它。它试图说明两个并发的可重复读取翻译可以产生与任何串行执行都不一致的结果。

    一个更好的例子可能是两个并发事务,它们都读取相同的数据并根据读取结果对其执行更新。这些事务中的每一个都看不到另一个事务的修改。

    查看 "serializable" 下的 PostgreSQL Wiki 以获得更详细的示例。

  • 更新问题:

    这个问题我不是很清楚

    可序列化事务采用特殊的 "SI" 锁来跟踪读写访问并在提交后继续存在。它们不会阻止其他会话,但用于确定是否存在 可能 冲突。可序列化隔离级别仅在 所有 个并发事务使用可序列化隔离级别时才能正常工作。

关于 UPDATE

中的问题

Does the database decides on the result of the serializable transaction as if the other transactions were ran with serializable isolation too?"

答案是否定的

仅在可序列化隔离级别 的并发事务之间验证可序列化性。例如,给定两个事务 T1 和 T2 交错如下:

T1: begin
T1: set transaction isolation level read committed;
T1: update addresses set street = 'Sun street' where id = 1
T2: begin
T2: set transaction isolation level serializable;
T2: select street from addresses where id = 1
T2: update addresses set street = 'Sea street' where id = 2
T1: select street from addresses where id = 2
T1: commit
T2: commit

T1 和 T2 都将提交。但是,如果将 T1 设置为可序列化隔离,则 T2 将中止。