【发布时间】:2021-06-21 16:18:16
【问题描述】:
我正在运行 Postgres12,但对可序列化事务级别的行为感到困惑。
表格:
活动
- 身份证
- 难度
经理
- 身份证
- 级别
预期行为(在序列化事务中):
- 检查是否有 7 个或更多难度事件=2
- 如果是这样,请插入 level=2 的经理
我正在以可序列化的方式运行以下事务,但没有看到预期的行为(预计可序列化事务会检测 2 个会话之间的写入偏差)
-- session 1:
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE
SELECT count(*) from events WHERE difficulty=2
-- RETURNS 7
-- now start session 2
-- session 2:
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE
SELECT id FROM events WHERE difficulty=2 LIMIT 1;
/*
id
----
4
*/
UPDATE events SET difficulty=1 WHERE id=4;
COMMIT;
现在只有 6 个难度的事件=2
-- back in session 1
-- since we have counted 7 events of difficulty=2 in this session, create a manager
INSERT INTO manager (level) VALUES (2);
COMMIT;
-- Expected write skew to be detected here bc the read event rows have seen updates (only 6 actually)
不幸的是,我们的最终状态现在是 6 个难度 = 2 的事件和 2 级的经理。 为什么可序列化隔离不能防止这种写入偏差? 我对可序列化隔离用例有什么误解?为什么难度=2 的事件没有被谓词锁定或某种隔离机制锁定或监视?
【问题讨论】:
-
我怀疑这两个事务可以通过首先运行会话 1 中的所有命令,然后运行会话 2 中的所有命令来序列化。它们不会发生冲突,排序确实会导致您看到的结果。您的会话 2 中没有代码会再次删除经理,是吗?
标签: postgresql isolation-level transaction-isolation