2つの別々のクエリを使用せずに、特定のステートメントを実行する前にアドバイザリロックを取得する安全な方法はありますか?たとえば、次のようなことをした場合、挿入前にロックが取得される保証はないと思います。
WITH x AS (SELECT pg_advisory_lock(1,2)) INSERT ...
しかし、望ましい効果を得る同様の方法はありますか?
2つの別々のクエリを使用せずに、特定のステートメントを実行する前にアドバイザリロックを取得する安全な方法はありますか?たとえば、次のようなことをした場合、挿入前にロックが取得される保証はないと思います。
WITH x AS (SELECT pg_advisory_lock(1,2)) INSERT ...
しかし、望ましい効果を得る同様の方法はありますか?
SQL標準では、実装が最初に行うことは、WITH句で共通のテーブル式を効果的に具体化することであるかのように動作する必要があると確信しています。PostgreSQLはこの要件に準拠しています。
一般的なテーブル式は、(ほとんど)名前付きオブジェクトとして動作します。複数のCTEは、宣言された順序で具体化されます。名前による後方参照は期待どおりに機能し、名前による前方参照はエラーを発生させます。
したがって、一般的なケースでは、INSERTステートメントを実行する前にCTEを具体化する必要があると確信しています。しかし、あなたの場合、PostgreSQLを使用しているので、私は完全に確信しているわけではありません。その理由は次のとおりです。
[一般的なテーブル式の] PostgreSQLの実装は、親クエリによって実際にフェッチされるのと同じ数のWITHクエリの行のみを評価します。
INSERTステートメントがこの意味で行をフェッチするかどうかはわかりません。
確かにユースケースについて十分に説明していませんが、一般に、明示的なロックをPostgreSQLで使用するには、トランザクションがスナップショットを取得する前に取得する必要があります。アドバイザリロックは、トランザクションを開始する前に取得できます。トランザクションスコープを持つほとんどのロックは、トランザクションの開始直後に取得する必要があります。トランザクションIDが必要になる前に。
トランザクションIDを割り当ててスナップショットを設定する前にロックを取得する必要がなく、1つのステートメントを発行してロックを取得して挿入を実行することが重要な場合は、両方を実行する関数を作成します。