日安。我在postgres中玩READ COMMITTED隔离级别,发现一些奇怪的行为,没有遵循官方文档。假设我有一个表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现在,我开始两个读取提交的事务。首先,执行以下查询
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); 现在它被锁定了,因为第一个事务还没有提交。因此,第二个交易需要在每个帐户中增加50,其总金额大于或等于1000。因为Bob有两个帐户(800+200),那么它应该向每个帐户添加50个帐户。但是,现在第一个事务被提交了COMMIT; --1,现在Bob总共有900个事务,根据文档,Read提交的事务将
重新计算命令的搜索条件( WHERE子句),以查看更新后的行版本是否仍然与搜索条件匹配。如果是的话,第二个更新程序将继续使用行的更新版本进行操作。
据我所知,第二个事务将重新评估的条件,跳过Bob的帐户。然而,当第二个事务被提交时,最后的行如下所示
id | 1 │
name | Bob │
amount | 850 │
-[ RECORD 3 ]------------------------- │
id | 2 │
name | Bob │
amount | 150 这意味着第二个事务没有重新评估搜索条件,并将更新应用于行,即使它们不是条件匹配的。为什么会发生这种事。我在文件里漏掉了什么吗?
发布于 2020-05-13 19:39:30
第一个事务中的UPDATE阻塞第二个查询中的UPDATE,而不是该查询中的子subselect。子选择已经完成,之和被确定为1000,因此执行UPDATE并阻塞。子查询在锁消失时不会被重新计算.
您从文档中引用的段落是关于SELECT ... FOR UPDATE (或FOR SHARE)的,您不使用它。它不能在您的示例中使用,因为它在使用聚合函数或分组的查询中没有意义。
https://stackoverflow.com/questions/61781595
复制相似问题