【发布时间】:2020-08-30 01:22:22
【问题描述】:
美好的一天。我在 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
现在我开始两个 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,读取已提交事务将
命令的搜索条件(WHERE 子句)是 重新评估以查看该行的更新版本是否仍然匹配 搜索条件。如果是这样,第二个更新程序继续其 使用行的更新版本进行操作
据我了解,第二笔交易将重新评估 where 条件并跳过 Bob 的帐户。然而,当第二个事务被提交时,最后的行看起来像这样
id | 1 │
name | Bob │
amount | 850 │
-[ RECORD 3 ]------------------------- │
id | 2 │
name | Bob │
amount | 150
这意味着第二个事务没有重新评估搜索条件并对行应用更新,即使它们不符合条件。为什么会这样。我错过了文档中的某些内容吗?
【问题讨论】:
-
HAVING 子句不是 WHERE 子句。
-
@pifor 我谈到了第二笔交易调用时的一部分(其中名称在(...)中)
-
WHERE 子句是可能应用以下规则的子查询: 当事务使用此隔离级别时,SELECT 查询(没有 FOR UPDATE/SHARE 子句)只能看到之前提交的数据查询开始;它永远不会看到未提交的数据或并发事务在查询执行期间提交的更改。
标签: postgresql isolation read-committed