sql >> データベース >  >> RDS >> PostgreSQL

ロックされた行を待たないようにするためのアドバイザリロックまたはNOWAIT?

    FOR UPDATE NOWAIT ではない特定の行をロックすることを主張する場合にのみ、これは良い考えです。 何が必要。 任意のが必要です 適格な、利用可能な(ロックされていない)行。重要な違いはこれです(Postgres 9.4のマニュアルを引用):

    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を使用した実装でも 。)

    脇白

    厳密に言えば、真にランダムな選択ではなく、任意の選択を取得します。これは重要な違いになる可能性があります。
    監査されたバージョンのクエリが、他の質問に対する私の回答に含まれています。




    1. Oracleにスクリプトを介して挿入するより速い方法は?

    2. MySQLでロック待機タイムアウト超過エラーを修正する方法

    3. Oracleのビューとマテリアライズド・ビューの違いは何ですか?

    4. PostgreSQLメルトダウンベンチマーク