はい、いいえ-いつものように、それは異なります。 ドキュメント 厳密に言うと:
つまり、単にSELECTはSELECT FOR UPDATE / DELETE/UPDATEとは異なります。
簡単なテストケースを作成して、その動作を観察できます。
セッション1強い>
test=> START TRANSACTION;
START TRANSACTION
test=> SELECT * FROM test;
x
----
1
2
3
4
5
6
7
8
9
10
(10 rows)
test=> DELETE FROM test;
DELETE 10
test=>
別のセッション2にログインします:
test=> START TRANSACTION;
START TRANSACTION
test=> SELECT * FROM test;
x
----
1
2
3
4
5
6
7
8
9
10
(10 rows)
test=> SELECT * FROM test WHERE x = 5 FOR UPDATE;
最後のコマンドの後SELECT ... FOR UPDATE
セッション1は「ハング」し、何かを待っています......
セッション1に戻る
test=> insert into test select * from generate_series(1,10);
INSERT 0 10
test=> commit;
COMMIT
セッション2に戻ると、次のように表示されます。
test=> SELECT * FROM test WHERE x = 5 FOR UPDATE;
x
---
(0 rows)
test=> select * from test;
x
----
1
2
3
4
5
6
7
8
9
10
(10 rows)
つまり、単純なSELECT
SELECT ... FOR UPDATE
の間、まだ変更は表示されません。 行が削除されたことを確認します。ただし、セッション1によって挿入された新しい行は表示されません
実際、表示されているシーケンスは次のとおりです。
- プロセスAがトランザクションを開始します
- プロセスAはテーブルTからすべてを削除します
- プロセスBがトランザクションを開始します
- プロセスBは、テーブルTの1つの行で更新の選択を試みます
- プロセスBは「ハング」し、セッションAがコミットまたはロールバックを実行するまで待機します
- プロセスAは、受信データからテーブルTを再作成します
- プロセスAはトランザクションをコミットします
- プロセスBが空になり(0行-セッションAのコミット後)、ロールバックを呼び出します