ではない特定の行をロックすることを主張する場合にのみ、これは良い考えです。 何が必要。 任意のが必要です 適格な、利用可能な(ロックされていない)行。重要な違いはこれです(Postgres 9.4のマニュアルを引用):FOR UPDATE NOWAIT
NOWAIT
を使用 、選択した行をすぐにロックできない場合、ステートメントは待機ではなくエラーを報告します。
同一のクエリは、同じ任意のピックをロックしようとする可能性が非常に高くなります。 FOR UPDATE NOWAIT
例外を除いてベイルアウトし(エラーをトラップしない限りトランザクション全体をロールバックします)、再試行する必要があります。
dba.SEに関する私の参照回答の解決策は、プレーンな FOR UPDATE
の組み合わせを使用しています pg_try_advisory_lock()
と組み合わせて :
pg_try_advisory_lock
pg_advisory_lock
に似ています 、ただし、関数はロックが使用可能になるのを待機しません。ロックをすぐに取得してtrueを返すか、ロックをすぐに取得できない場合はfalseを返します。
したがって、最良のオプション は...3番目の選択肢:新しい FOR UPDATE SKIP LOCKED
Postgres 9.5では、追加の関数呼び出しなしで同じ動作を実装します。
Postgres 9.5のマニュアルでは、2つのオプションを比較し、違いをもう少し説明しています。
操作が他のトランザクションのコミットを待機しないようにするには、
NOWAIT
のいずれかを使用します またはSKIP LOCKED
オプション。NOWAIT
を使用 、選択した行をすぐにロックできない場合、ステートメントは待機ではなくエラーを報告します。SKIP LOCKED
を使用 、すぐにロックできない選択した行はスキップされます。
Postgres 9.4以前では、次善のオプション pg_try_advisory_xact_lock(id)
を使用することです FOR UPDATE
と組み合わせて 参照された回答に示されているように:
- PostgresUPDATE…制限1
(FOR UPDATE SKIP LOCKED
を使用した実装でも 。)
厳密に言えば、真にランダムな選択ではなく、任意の選択を取得します。これは重要な違いになる可能性があります。
監査されたバージョンのクエリが、他の質問に対する私の回答に含まれています。