2

良い一日。postgresで分離レベルをいじっていたREAD COMMITTEDところ、公式ドキュメントに従わない奇妙な動作が見つかりました。テーブルaccount(id int,name text,amount int)と 2 つの行があるとします。

test> select * from account;                       
-[ RECORD 1 ]-------------------------
id     | 1
name   | Bob
amount | 800
-[ RECORD 2 ]-------------------------
id     | 2
name   | Bob
amount | 200

ここで、2 つの READ COMMITTED トランザクションを開始します。最初のものは次のクエリを実行します

UPDATE account set amount = 100 where id = 2; -- 1

そして、2番目はこのクエリを実行します

 UPDATE account set amount = amount+50 --2
  where name in 
      (select DISTINCT name from account group by
      name having sum(amount)>=1000); 

最初のトランザクションがまだコミットされていないため、現在はロックされています。したがって、2 番目のトランザクションでは、合計金額が 1000 以上の各口座に 50 を追加する必要があります。Bob には 2 つの口座 (800+200) があるため、各口座に 50 を追加する必要があります。ただし、最初のトランザクションがコミットさCOMMIT; --1れ、Bob の合計は 900 になり、Documentation Read commit transaction willによると、

コマンドの検索条件 (WHERE 句) が再評価され、更新されたバージョンの行がまだ検索条件に一致するかどうかが確認されます。その場合、2 番目の updater は、行の更新されたバージョンを使用して操作を続行します。

私の知る限り、2 番目のトランザクションは where 条件を再評価し、ボブのアカウントをスキップします。ただし、2 番目のトランザクションがコミットされると、最終的な行は次のようになります

id     | 1                                                                                            │
name   | Bob                                                                                          │
amount | 850                                                                                          │
-[ RECORD 3 ]-------------------------                                                                │
id     | 2                                                                                            │
name   | Bob                                                                                          │
amount | 150 

これは、2 番目のトランザクションが検索条件を再評価せず、条件に一致しない場合でも行に更新を適用したことを意味します。なぜそれが起こるのですか?ドキュメントで何かを見逃していましたか?

4

1 に答える 1