web-dev-qa-db-ja.com

PL / pgSQL関数で検出されたデッドロック

PostgreSQLデータベースのPL/pgSQL関数からのデッドロック問題に直面しています。コードブロックでSQLステートメントを見つけてください(例のみ):

BEGIN
UPDATE accounts SET balance = 0 WHERE acct_name like 'A%';
UPDATE accounts SET balance = balance + 100 WHERE acct_name like '%A';
EXCEPTION WHEN OTHERS THEN RAISE NOTICE SQLERRM;
END;

このステートメントの実行中にデッドロックが発生したことがわかりました。しかし、このテーブルを同時に更新しようとしている他のステートメントがあったかどうかはわかりません(ロギングシステムで何も見つからなかったためです)。

では、このステートメント内でデッドロックが発生した可能性はありますか?私の知る限り、BEGIN/ENDでステートメント全体をブロックした場合。同じトランザクションがあり、それ自体でロックされるべきではありません。

14

間違いなく同じリソースを求めて競合する他のプロセスがあります。それがデッドロックの性質です。表示するような関数は、それ自体をデッドロックすることはありません。 下の@kgrittnによるコメント を参照してください。これは、PostgreSQLの同時実行の専門家です。

PostgreSQLのバージョンがありません。最新バージョンでは、詳細なエラーメッセージが発生します。リソースを競合する両方のプロセスが、標準のログ設定とともに詳細にリストされます。 dbログを確認してください。

エラーをキャッチすると、Postgresが完全な詳細を提供できなくなる場合があります。 [〜#〜] exception [〜#〜]ブロックをplpgsql関数から削除します。dbログの情報が得られない場合は、再試行。

デッドロックを軽減するために、いくつかのことができます。すべてのクライアントが同期した順序でリソースにアクセスする場合、デッドロックは発生しません。このマニュアルは、 デッドロック に関する章のほとんどのケースを解決するための基本的な戦略を提供します。


バージョン8.3の場合:より新しいバージョンへのアップグレードを検討してください。特に、バージョン8.4でのこの改善は興味深いものです( リリースノートの引用 )。

デッドロックを報告するときは、デッドロックに関連するすべてのクエリのテキストをサーバーログに報告します。

また、バージョン8.3は 2013年2月のサポート終了 に対応します。アップグレードを検討する必要があります。

VACUUMに関連するデッドロック状況は 8.3.1で修正されました でした。

17

commitを追加して排他ロックを解放しても、デッドロックの問題は発生しません。

BEGIN
UPDATE accounts SET balance = 0 WHERE acct_name like 'A%';
COMMIT;  
UPDATE accounts SET balance = balance + 100 WHERE acct_name like '%A';
EXCEPTION WHEN OTHERS THEN RAISE NOTICE SQLERRM;
END;
2
jimmy chen