postgresql - 可序列化隔离级别混淆 - 写入偏差 (Postgres)
问题描述
我正在运行 Postgres12 并对可序列化事务级别的行为感到困惑。
表:
活动
- ID
- 困难
经理人
- ID
- 等级
预期行为(在序列化事务中):
- 检查是否有 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 的事件没有被谓词锁定或某种隔离机制锁定或监视?
解决方案
SERIALIZABLE
意味着有一种方法可以顺序执行事务(一个接一个),这样效果是一样的。在您的情况下,这个等效的串行执行将首先运行会话 1,然后运行会话 2,效果相同。
您可以说会话 1 在会话 2 之前“逻辑地”执行。
推荐阅读
- css - 在物化 CSS 上更改日期选择器颜色
- java - OpenCSV + RestTemplate:数组类型
- python - 获取由熊猫中另一列排序的列划分的第一个匹配项
- asp.net-mvc - ASP.net core 3.1 中控制器和剃须刀页面之间的路由
- mysql - 当多条记录同时插入时,如何避免重复的序号?
- javascript - 全局覆盖默认类型属性
- python - 如果输入不在域中,则使 matplotlib 不绘图
- python - 无法使用 blit 在 pygame 中显示图像
- android - Android Navigation 从第一个片段中删除工具栏
- python - Python:从 a-Tag 获取下载链接,其中包含 onclick 生成的链接