我正在阅读PostgreSQL手册的第13.2节,但发现其中的文本描述不够清晰,并且缺乏示例。
例如,以下两段不清楚谁在学习PostgreSQL:
带有ON CONFLICT DO UPDATE子句的INSERT的行为类似。在读取提交模式下,建议插入的每一行都将插入或更新。除非有不相关的错误,否则这两个结果中的一个是肯定的。如果冲突起源于另一个事务,其影响对INSERT尚不可见,则UPDATE子句将影响该行,即使该命令通常可能不可见该行的任何版本。”
和
可重复读取模式提供了严格的保证,每个事务都能看到数据库的完全稳定视图。但是,此视图不一定总是与同一级别的并发事务的某些串行(一次一个)执行一致。例如,即使是此级别的只读事务也可能会看到更新的控制记录以显示批处理已完成,但看不到逻辑上属于批处理的详细记录之一,因为它读取了控制记录的早期修订。
有人能举例说明这两段的内容吗?
有人知道在哪里可以找到PostgreSQL隔离级别行为的正式描述吗?我正在寻找这个,因为它是一个高级主题,我相信正式的描述将有助于阐明它是如何工作的,从而有助于避免事务之间的并发错误。
更新:我的另一个疑问是,当可序列化事务可以与其他隔离级别的其他事务同时运行时,数据库机器如何决定提交或中止它?数据库是否决定可序列化事务的结果,就好像其他事务也使用可序列化隔离运行一样?
谢啦
更新2:到目前为止,我在隔离级别的实现细节方面发现的最好的是PostgreSQL Wiki Serializable Page。
>
READ COMMITTED
:每个SQL语句都会获取数据库的新快照,因此每个语句都会在提交后立即看到并发事务所做的更改。不会发生序列化错误。
REPEATABLE READ
:事务中的第一条语句获取为整个事务保留的数据库的快照,因此所有语句都看到数据库的相同状态。如果您在获取快照后尝试修改已被并发事务修改的行,则可能会发生序列化错误。此隔离级别不会比READ COMMITTED
更昂贵。
SERIALIZABLE
:任何可能导致结果与事务的某些串行执行顺序不一致的事务都将因序列化错误而中止。可能会出现误报。此隔离级别比其他隔离级别更昂贵。
具体问题的答案:
>
INSERT… ON CONFLICT
在读提交隔离中:
如果事务1插入了一行,但尚未提交,则运行INSERT… ON CONFLICT
的事务2将等待,直到事务1提交或回滚,然后根据需要更新或插入。不会发生违反约束的情况。
批处理作业和可重复读取
:
这一段是黑暗的;忽略它。它试图说明两个并发的可重复读取翻译会产生与任何串行执行不一致的结果。
一个更好的例子可能是两个并发事务,它们都读取相同的数据并根据读取结果对它们执行更新。这些事务中的每一个都看不到另一个事务的修改。
查看“可序列化”下的PostgreSQL Wiki以获取更详细的示例。
更新问题:
这个问题我不太清楚。
可序列化事务采用特殊的“SI”锁,用于跟踪读写访问并在提交后幸存下来。它们不会阻塞其他会话,但用于确定是否可能存在冲突。可序列化隔离级别仅在所有并发事务都使用可序列化隔离级别时才能正常工作。
关于更新中的问题
数据库是否决定可序列化事务的结果,就好像其他事务也使用可序列化隔离运行一样?”
答案是否定的。
可串行性仅在可串行化隔离级别的并发事务之间进行验证。例如,给定两个事务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将中止。