18

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。同じトランザクションが存在するため、単独でロックしないでください。

4

3 に答える 3

28

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

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

エラーをキャッチしたという事実により、Postgresが完全な詳細を提供できなくなる可能性があります。dbログに情報がない場合は、plpgsql関数からEXCEPTIONブロックを削除して、再試行してください。

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


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

デッドロックを報告するときは、デッドロックに関係するすべてのクエリのテキストをサーバーログに報告してください(Itagaki Takahiro)

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

関係するデッドロック状況は、8.3.1で修正されVACUUMているはずです。

于 2012-04-09T18:08:58.327 に答える
2

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;
于 2014-01-17T05:14:34.640 に答える
-1

PostgreSQLでは、beginはバッチトランザクションを開始することを意味します。

最初の更新でアカウントの行がロックされますWHERE acct_name like 'A%'; これらの行は、最初の更新後に排他的にロックされます。

最初の更新はまだコミットされていないため、2番目の更新は最初の更新とまったく同じ行を開こうとします。更新は失敗します。

したがって、2番目の更新ヒットのデッドロックはロールバックでした。

于 2014-01-17T05:04:26.700 に答える