Postgres read committed 不会重新读取更新的行
Postgres read commited doesn't re read updated row
美好的一天。我在 postgres 中使用 READ COMMITTED
隔离级别,发现不符合官方文档的奇怪行为。
假设我有一个 table account(id int,name text,amount int)
和两行。
test> select * from account;
-[ RECORD 1 ]-------------------------
id | 1
name | Bob
amount | 800
-[ RECORD 2 ]-------------------------
id | 2
name | Bob
amount | 200
现在我开始两个 READ COMMITTED 事务。第一个执行以下查询
UPDATE account set amount = 100 where id = 2; -- 1
然后第二个执行此查询
UPDATE account set amount = amount+50 --2
where name in
(select DISTINCT name from account group by
name having sum(amount)>=1000);
现在它被锁定,因为第一个事务还没有提交。所以第二笔交易想要给每个总金额大于或等于1000的账户加50。因为Bob有两个账户(800+200)那么它应该给每个账户加50。但是,现在第一个事务已提交 COMMIT; --1
,现在 Bob 总共有 900 个,根据 Documentation 读取已提交的事务将
The search condition of the command (the WHERE clause) is
re-evaluated to see if the updated version of the row still matches
the search condition. If so, the second updater proceeds with its
operation using the updated version of the row
据我了解,第二笔交易将重新评估 where 条件并跳过 Bob 的帐户。但是,当提交第二个事务时,最后的行看起来像这样
id | 1 │
name | Bob │
amount | 850 │
-[ RECORD 3 ]------------------------- │
id | 2 │
name | Bob │
amount | 150
这意味着第二个事务没有重新评估搜索条件并应用更新到行,即使它们不符合条件。为什么会这样。我错过了文档中的某些内容吗?
第一个事务中的 UPDATE
会阻塞第二个查询中的 UPDATE
,但 不会 该查询中的子查询。 subselect已经完成,sum已经确定为1000,所以UPDATE
被执行,that被阻塞。当锁消失时,子查询不会重新求值。
您从文档中引用的段落是关于 SELECT ... FOR UPDATE
(或 FOR SHARE
)的,您没有使用它。它不能在您的示例中使用,因为它在使用聚合函数或分组的查询中没有意义。
美好的一天。我在 postgres 中使用 READ COMMITTED
隔离级别,发现不符合官方文档的奇怪行为。
假设我有一个 table account(id int,name text,amount int)
和两行。
test> select * from account;
-[ RECORD 1 ]-------------------------
id | 1
name | Bob
amount | 800
-[ RECORD 2 ]-------------------------
id | 2
name | Bob
amount | 200
现在我开始两个 READ COMMITTED 事务。第一个执行以下查询
UPDATE account set amount = 100 where id = 2; -- 1
然后第二个执行此查询
UPDATE account set amount = amount+50 --2
where name in
(select DISTINCT name from account group by
name having sum(amount)>=1000);
现在它被锁定,因为第一个事务还没有提交。所以第二笔交易想要给每个总金额大于或等于1000的账户加50。因为Bob有两个账户(800+200)那么它应该给每个账户加50。但是,现在第一个事务已提交 COMMIT; --1
,现在 Bob 总共有 900 个,根据 Documentation 读取已提交的事务将
The search condition of the command (the WHERE clause) is re-evaluated to see if the updated version of the row still matches the search condition. If so, the second updater proceeds with its operation using the updated version of the row
据我了解,第二笔交易将重新评估 where 条件并跳过 Bob 的帐户。但是,当提交第二个事务时,最后的行看起来像这样
id | 1 │
name | Bob │
amount | 850 │
-[ RECORD 3 ]------------------------- │
id | 2 │
name | Bob │
amount | 150
这意味着第二个事务没有重新评估搜索条件并应用更新到行,即使它们不符合条件。为什么会这样。我错过了文档中的某些内容吗?
第一个事务中的 UPDATE
会阻塞第二个查询中的 UPDATE
,但 不会 该查询中的子查询。 subselect已经完成,sum已经确定为1000,所以UPDATE
被执行,that被阻塞。当锁消失时,子查询不会重新求值。
您从文档中引用的段落是关于 SELECT ... FOR UPDATE
(或 FOR SHARE
)的,您没有使用它。它不能在您的示例中使用,因为它在使用聚合函数或分组的查询中没有意义。