Apache2、mod_python、およびpostgresql_psycopg2データベースバックエンドを備えたPostgreSQL8.3を使用してDjangoで適度に人気のあるWebアプリを実行します。私は時折ライブロックを経験しています。これは、apache2プロセスが数分以上CPUの99%を継続的に消費している場合に識別できます。
apache2プロセスでstrace- ppidを実行したところ、次のシステムコールが継続的に繰り返されていることがわかりました。
sendto(25, "Q\0\0\0SSELECT (1) AS \"a\" FROM \"account_profile\" WHERE \"account_profile\".\"id\" = 66201 \0", 84, 0, NULL, 0) = 84
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
poll([{fd=25, events=POLLIN|POLLERR, revents=POLLIN}], 1, -1) = 1
recvfrom(25, "E\0\0\0\210SERROR\0C25P02\0Mcurrent transaction is aborted, commands ignored until end of transaction block\0Fpostgres.c\0L906\0Rexec_simple_query\0\0Z\0\0\0\5E", 16384, 0, NULL, NULL) = 143
この正確なフラグメントはトレース内で継続的に繰り返され、最終的にapache2プロセスを強制終了する前に10分以上実行されていました。(注:これを編集して、以前のstraceフラグメントを、切り捨てられるのではなく、文字列の内容全体を表示する新しいフラグメントに置き換えました。)
上記の私の解釈は、djangoが私のテーブルaccount_profileで存在チェックを行おうとしているということですが、ある初期の時点(トレースを開始する前)で何かがうまくいきませんでした(SQL解析エラー?参照整合性または一意性制約違反?誰が知っていますか? )、そして今Postgresqlはエラー「現在のトランザクションは中止されました」を返しています。何らかの理由で、例外を発生させてあきらめる代わりに、再試行を続けます。
1つの可能性は、これがProfile.objects.get_or_createの呼び出しでトリガーされていることです。これは、account_profileテーブルにマップするモデルクラスです。おそらく、get_or_createに、広すぎる例外のセットをキャッチして再試行するように設計されたものがありますか?Webサーバーのログから、このライブロックは、サイトの登録フォームのPOSTボタンをダブルクリックした結果として発生した可能性があるようです。
この状態は、ライブサイトで過去数日間に数回発生し、介入するまで大幅に遅くなるため、無限のデッドロック以外のほとんどの問題が改善されます。:)