2

したがって、このトランザクションを考えると:

select * from table_a where field_a = 'A' for update;

これにより複数の行/結果が得られると仮定すると、データベースはすべての結果をすぐにロックしますか? または、一度に 1 行ずつロックします。

後者が当てはまる場合、このクエリを同時に実行すると、デッドロックが発生する可能性がありますか?

したがって、この問題を解決するには、順序の一貫性を維持するために order by を追加する必要がありますか?

4

1 に答える 1

3

ドキュメントでは、何が起こるかを次のように説明しています。

更新のため

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

于 2016-03-30T23:07:47.843 に答える