2009-08-20 15 views
52

私は自分のスレッドでいくつかの定期的なタスクを実行するようにDjangoを設定しました。そして、彼らはいつも未完成のデータベース接続プロセス(pgsql "Idle In Transaction")を残していたことに気付きました。スレッド化されたDjangoタスクは、トランザクションまたはdb接続を自動的に処理しません。

私はPostgresログを調べて、トランザクションが完了していないことを確認しました(ROLLBACKはありません)。私は、私の機能上、さまざまなトランザクションデコレータを使用してみました。

私は手動トランザクション管理に切り替えて、手動でロールバックを行いました。それはうまくいっていましたが、プロセスは「アイドル」のままでした。

だから、私はconnection.close()を呼び出して、すべてがうまくいっています。

しかし私は疑問に思っていますが、なぜDjangoのメインのスレッドから生成されているこれらのスレッドタスクに対して、Djangoの典型的なトランザクションと接続管理は機能しませんか?テストの週間後

答えて

93

とDjangoのソースコードを読んで、私は自分の質問への答えを見つけた:

取引

Djangoのデフォルトの自動コミットの動作はまだ私のスレッド化機能のためにも当てはまります。しかし、それはDjangoのドキュメントで述べている:

とすぐにデータベースに書き込む必要があるアクションを実行するよう、DjangoはDELETE文/ INSERT/UPDATEを生成し、その後、COMMITありません。暗黙的なROLLBACKはありません。

最後の文は非常にリテラルです。 Djangoの何かがダーティーフラグをセットしていない限り、ROLLBACKコマンドを発行しません。私の関数はSELECTステートメントだけを実行していたので、ダーティー・フラグを決して設定せず、COMMITをトリガーしませんでした。

これは、Djangoがタイムゾーンに対してSETコマンドを発行したため、PostgreSQLがトランザクションにROLLBACKが必要であると考えていることに反します。ログを見直す際、私はこれらのROLLBACK文を見続けて、Djangoのトランザクション管理を元にしていたので、私は自分自身を捨てました。そうではないことが分かります。それは問題ありません。

接続

物事はトリッキー得るのですかどこ接続管理があります。 Djangoはsignals.request_finished.connect(close_connection)を使用して、通常使用するデータベース接続を閉じます。 Djangoでは要求を伴わないことは通常は何も起こらないので、あなたはこの振る舞いを当然受け入れます。

私の場合は、ジョブがスケジュールされているため、要求はありませんでした。要求がないということは信号がないことを意味する。シグナルなしとは、データベース接続が決してクローズされなかったことを意味します。

トランザクションに戻ってみると、トランザクション管理の変更がなければconnection.close()の呼び出しを発行するだけで、私が探していたPostgreSQLログにROLLBACKステートメントが発行されます。解決策は、通常のDjangoのトランザクション管理は、通常のように進行すると、単に接続の3つの方法のいずれかを閉じることを可能にすることである

ソリューション

  1. は接続を閉じデコレータを書くと、それに必要な機能をラップします。
  2. Djangoに接続を閉じるために既存のリクエスト信号にフックします。
  3. 機能の最後に接続を手動で閉じます。

これら3つのうちのどれかが動作します。

これは私を数週間夢中にさせてくれました。私はこれが将来他の誰かに役立つことを願っています!

+1

あなたはついにこれを解決しました。それは明らかではなかった。どこかのドキュメントにメモを追加する価値があるのだろうかと思います。 –

+1

このチケットは非常によく似た問題を記述しています:http://code.djangoproject.com/ticket/9964 – zooglash

+0

うわー。あなたはコードを共有することができますか? – Dejell

関連する問題