【问题标题】:Serializable Isolation Level Confusion - Write Skew (Postgres)可序列化隔离级别混淆 - 写入偏差 (Postgres)
【发布时间】:2021-06-21 16:18:16
【问题描述】:

我正在运行 Postgres12,但对可序列化事务级别的行为感到困惑。

表格:

活动

  1. 身份证
  2. 难度

经理

  1. 身份证
  2. 级别

预期行为(在序列化事务中):

  1. 检查是否有 7 个或更多难度事件=2
  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


【解决方案1】:

SERIALIZABLE 表示有一种方法可以顺序执行事务(一个接一个),这样效果是一样的。在您的情况下,这个等效的串行执行将首先运行会话 1,然后运行会话 2,效果相同。

您可以说会话 1 在会话 2 之前“逻辑地”执行。

【讨论】:

  • 抱歉更新了问题,两个交易都是可序列化的(见图)。但是,是的,订购点是正确的。执行事务 1,然后执行事务 2 也会导致 1 个经理级别=2 和 6 个事件 difficutly=2。
【解决方案2】:

经过思考后回答我自己的问题!

序列化检查不会阻止两个会话提交,因为有可能序列化两个事务,但最终仍会出现 2 级管理器和 6 个难度=2 的事件。

例如

  1. 运行会话 1(检查 7 个事件是否难度=2,创建经理级别=2)提交;
  2. 运行会话 2(删除 1 个事件,现在 6 个事件,难度=2)提交;

^输出 = 6 个事件,1 个经理

这与并发运行的结果相同,因此这被视为这两个可序列化事务的“可接受”状态。

如果您想阻止这种行为,可以将会话 2 更新为以下内容

begin transaction isolation level serializable;
select count(*) from manager where level=2; 
--if no managers
update events set difficulty=1 where id=4;

现在没有合乎逻辑的方法来以序列化排序结束状态 6 事件 1 管理器。顺序排序的两种可能结果是

  1. 会话 1 运行
  2. 会话 2 运行

^输出 = 7 个事件 1 个经理

  1. 会话 2 运行
  2. 会话 1 运行

^输出 = 6 个事件 0 个经理

所以在这种情况下(使用更新的会话 2),您的一个事务将被阻止,因为这些事务不再可序列化。

【讨论】:

    猜你喜欢
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-29
    • 2020-07-16
    • 2015-03-24
    • 2023-03-04
    • 2021-01-14
    相关资源
    最近更新 更多