ドキュメントでは、何が起こるかを次のように説明しています。
更新のため
FOR UPDATE
ステートメントによって取得された行SELECT
が、更新の場合と同様にロックされます。これにより、現在のトランザクションが終了するまで、他のトランザクションによってそれらがロック、変更、または削除されるのを防ぎます。つまり、これらの行の 、、、、またはを試行する他のトランザクションは、UPDATE
現在
の
トランザクションが終了するまでブロックされます。逆に、同じ行でこれらのコマンドのいずれかを実行した同時トランザクションを待機し、ロックして更新された行を返します (行が削除された場合は行を返しません)。ただし、 or
トランザクション内では、ロックする行がトランザクションの開始後に変更された場合、エラーがスローされます。詳細については、セクション 13.4 を参照してください。DELETE
SELECT FOR UPDATE
SELECT FOR NO KEY UPDATE
SELECT FOR SHARE
SELECT FOR KEY SHARE
SELECT FOR UPDATE
REPEATABLE READ
SERIALIZABLE
あなたの質問に対する直接的な答えは、Postgres はすべての行を「すぐに」ロックできないということです。最初にそれらを見つける必要があります。これは、テーブル レベルのロックではなく、行レベルのロックであることを忘れないでください。
ドキュメントには、次の注記が含まれています。
SELECT FOR UPDATE
選択した行を変更してロックされているとマークするため、ディスクへの書き込みが発生します。
SELECT
これは、Postgres がクエリを実行し、行が見つかると、それらをロック済みとしてマークするということだと解釈します。Postgres が行を識別すると、(特定の行の) ロックが開始されます。トランザクションが終了するまで続きます。
このことから、 を使用するとデッドロックが発生する可能性があると思いますSELECT FOR UPDATE
。