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