可序列化隔离级别未按预期工作?

Ash*_*win 3 postgresql transaction isolation-level

我有这张桌子

create table testing(
c1 text,
c2 text);
Run Code Online (Sandbox Code Playgroud)

我同时打开两笔交易。t0 t1..表示按递增顺序排列的一系列时间快照 事务 1

BEGIN; -- t0
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- t2
SELECT * FROM testing where c2 = 'rand'; -- t4
INSERT INTO testing VALUES ('rand', 'xyz'); -- t6
COMMIT; -- t8
Run Code Online (Sandbox Code Playgroud)

交易2

BEGIN; -- t1
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- t3
SELECT * FROM testing where c1 = 'rand1'; -- t5
INSERT INTO testing VALUES ('rand1', 'abc'); -- t7
COMMIT; -- t9
Run Code Online (Sandbox Code Playgroud)

t9当我收到这个错误 后
ERROR: could not serialize access due to read/write dependencies among transactions DETAIL: Reason code: Canceled on identification as a pivot, during commit attempt. HINT: The transaction might succeed if retried.

但如果您看到这些语句,它们会根据不同的值rand和进行操作rand1。抛出这个错误是没有意义的,因为它们永远不会处于糟糕的状态。

我的理解正确吗?

Lau*_*lbe 5

你的理解基本上是正确的。您没有意识到,使用隔离级别时可能会出现误报结果SERIALIZABLE

文档说:

虽然 PostgreSQL 的可序列化事务隔离级别仅在可以证明存在可产生相同效果的串行执行顺序的情况下才允许并发事务提交,但它并不总是能够防止引发真正串行执行中不会发生的错误。

在这种特殊情况下,我假设问题是您没有索引c1c2或者 PostgreSQL 选择执行顺序扫描。您可以在同一页面上进一步阅读:

  • 顺序扫描始终需要关系级谓词锁。这可能会导致序列化失败率增加。