为什么 PostgreSQL 会中止这个可序列化的计划

mlj*_*jrg 4 postgresql concurrency transactions serializable

理论指出,一组并发事务是可序列化的,当且仅当它们的并发执行等效于其中一个可能的串行执行。

现在下面的事务T1和T2的并发执行是可串行化的,因为等价于串行执行“T1然后T2”

T1: r1x   w1y  c1
T2:    w2x   c2

(i.e., T1 reads x, T2 writes x, T1 writes y, T2 commits, and finally, T1 commits)
Run Code Online (Sandbox Code Playgroud)

但是,在 PostgreSQL 10.4 中尝试时,如下所示:

T1: begin
T1: set transaction isolation level serializable;
T2: begin
T2: set transaction isolation level serializable;
T2: update variables set value = value + 1 where name = 'x'
T1: update variables set value = value + 1 where name = 'y'
T2: commit
T1: commit
Run Code Online (Sandbox Code Playgroud)

当此事务尝试提交时,数据库将中止 T1。为什么?

Lau*_*lbe 5

PostgreSQL 使用启发式方法来确定是否中止可序列化的事务,因为这很难准确。因此,即使存在等效的串行执行(误报),事务也可能中止。

但我怀疑在这种情况下有不同的原因。如果查看执行计划,您可能会看到顺序扫描。现在顺序扫描读取所有行,因此 T2y在其更新期间已读取。

可序列化事务的行为取决于选择的执行计划!