deposits
というテーブルがあります
デポジットが行われると、テーブルがロックされるため、クエリは次のようになります。
_SELECT * FROM deposits WHERE id=123 FOR UPDATE
_
_FOR UPDATE
_がテーブルをロックしているため、別のスレッドがデータに踏み込むことなくテーブルを操作できます。
ただし、他のデポジットがテーブルのロックを取得しようとすると、問題が発生します。何が起こるかとは、テーブルのロックとpsql_commit()
の呼び出しの間のどこかが失敗し、ロックを長い間保持していることです。 )。対処が必要なことがいくつかあります。
ロックを取得しようとする後続のクエリは失敗するはずです。NOWAIT
を使用してこれを達成しようとしましたが、タイムアウトメソッドを使用した方がよいでしょう(待機するのはOKで、「愚かな時間」を待たないため)。
理想的には、パスでこれを回避し、最初のクエリでロックを一定時間だけ保持するようにします。これはpostgresqlで可能ですか?
クエリに追加できる他のいくつかの魔法の関数(NOWAITと同様)は、失敗する前に4秒間ロックを待つだけですか?
コードベースの痛みを伴うモノリシックなスパゲッティコードの性質により、単にグローバル構成を変更するだけの問題ではないため、クエリごとのソリューションである必要があります
あなたの助けてくれてありがとう、私はぶらぶらと進み続けますが、私はあまり運がありませんでした。私はこれを見つけたので、これはpsqlの存在しない関数ですか? http://www.postgresql.org/message-id/[email protected]
FOR UPDATEはテーブルをロックしているので、別のスレッドがデータを踏むことなくテーブルを操作できると思います。
いいえ。 FOR UPDATE
はこれらの行のみをロックするため、それらをロックしようとする別のトランザクション(FOR SHARE
、FOR UPDATE
、UPDATE
またはDELETE
)ブロックトランザクションがコミットまたはロールバックするまで。
挿入/更新/削除をブロックするテーブル全体のロックが必要な場合は、おそらくLOCK TABLE ... IN EXCLUSIVE MODE
が必要です。
ロックを取得しようとする後続のクエリは失敗するはずです。NOWAITを使用してこれを達成しようとしましたが、タイムアウトメソッドを好むでしょう(「愚かな時間」を待たずに待つだけでよいため)
the lock_timeout
setting を参照してください。これは9.3で追加され、古いバージョンでは使用できません。
古いバージョンの粗い概算はstatement_timeout
で実現できますが、ステートメントが不必要にキャンセルされる可能性があります。 statement_timeout
が1であり、ステートメントがロックで950ms待機する場合、そのステートメントはロックを取得して続行し、タイムアウトによってすぐにキャンセルされるだけです。あなたが望むものではありません。
lock_timeout
を設定するクエリレベルの方法はありませんが、できます。
SET LOCAL lock_timeout = '1s';
BEGIN
トランザクションの後。
理想的には、パスでこれを回避し、最初のクエリでロックを一定時間だけ保持するようにします。これはpostgresqlで可能ですか?
statementタイムアウトがありますが、ロックはtransactionレベルで保持されます。トランザクションタイムアウト機能はありません。
単一ステートメントのトランザクションを実行している場合は、ステートメントを実行する前にstatement_timeout
を設定して、実行可能な時間を制限できます。これは、ロックを保持できる時間を制限することとはまったく同じではありません。ロックが許可される1秒の900ミリ秒待機し、実際には100ミリ秒だけロックを保持してから、タイムアウトによってキャンセルされるためです。
クエリに追加できる他のいくつかの魔法の関数(NOWAITと同様)は、失敗する前に4秒間ロックを待つだけですか?
いいえ。
BEGIN;
SET LOCAL lock_timeout = '4s';
SELECT ....;
COMMIT;
コードベースの痛みを伴うモノリシックなスパゲッティコードの性質により、単にグローバル構成を変更するだけの問題ではないため、クエリごとのソリューションである必要があります
SET LOCAL
がこれに適しています。
クエリのテキストでこれを行う方法はなく、別のステートメントでなければなりません。
リンクしているメーリングリストの投稿は、実装されていない架空の構文の提案であり(少なくともPostgreSQLのパブリックリリースでは)、存在しません。
このような状況では、「楽観的ロック」と呼ばれることがある「楽観的同時実行制御」を検討する必要がある場合があります。これにより、クエリの繰り返し率が増加し、さらに多くのアプリケーションロジックが必要になる代わりに、ロック動作をより詳細に制御できます。