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
でステートメント全体をブロックした場合。同じトランザクションがあり、それ自体でロックされるべきではありません。
間違いなく同じリソースを求めて競合する他のプロセスがあります。それがデッドロックの性質です。表示するような関数は、それ自体をデッドロックすることはありません。 下の@kgrittnによるコメント を参照してください。これは、PostgreSQLの同時実行の専門家です。
PostgreSQLのバージョンがありません。最新バージョンでは、詳細なエラーメッセージが発生します。リソースを競合する両方のプロセスが、標準のログ設定とともに詳細にリストされます。 dbログを確認してください。
エラーをキャッチすると、Postgresが完全な詳細を提供できなくなる場合があります。 [〜#〜] exception [〜#〜]ブロックをplpgsql関数から削除します。dbログの情報が得られない場合は、再試行。
デッドロックを軽減するために、いくつかのことができます。すべてのクライアントが同期した順序でリソースにアクセスする場合、デッドロックは発生しません。このマニュアルは、 デッドロック に関する章のほとんどのケースを解決するための基本的な戦略を提供します。
バージョン8.3の場合:より新しいバージョンへのアップグレードを検討してください。特に、バージョン8.4でのこの改善は興味深いものです( リリースノートの引用 )。
デッドロックを報告するときは、デッドロックに関連するすべてのクエリのテキストをサーバーログに報告します。
また、バージョン8.3は 2013年2月のサポート終了 に対応します。アップグレードを検討する必要があります。
VACUUM
に関連するデッドロック状況は 8.3.1で修正されました でした。
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;