考えられる解決策: http://groups.google.com/group/django-users/browse_thread/thread/2c7421cdb9b99e48
最近まで、これを Django 1.1.1 でテストしたいと思っていました。この例外は再びスローされますか...驚き、再び発生しました。これをデバッグするのに少し時間がかかりましたが、役立つヒントは、(前)フォーク時にのみ表示されることでした。したがって、これらの例外がランダムに発生する人のために、私は言うことができます...コードを修正してください:)わかりました..真剣に、これを行う方法は常にほとんどないので、最初にどこに問題があるかを説明させてください。データベースから構成を読み取るなど、モジュールのいずれかがインポートされるときにデータベースにアクセスすると、このエラーが発生します。fastcgi-prefork アプリケーションが開始されると、最初にすべてのモジュールがインポートされ、これが子をフォークした後でのみインポートされます。インポート中にデータベース接続を確立した場合、すべての子プロセスはそのオブジェクトの正確なコピーを持ちます。この接続は、要求フェーズ (request_finished シグナル) の終わりに閉じられています。したがって、リクエストを処理するために呼び出される最初の子は、この接続を閉じます。しかし、残りの子プロセスはどうなるでしょうか? 彼らは、データベースへの接続が開いていて、おそらく機能していると信じているため、データベース操作を行うと例外が発生します。これがスレッド実行モデルに表示されないのはなぜですか? スレッドが同じオブジェクトを使用しており、他のスレッドがいつ接続を閉じているかを知っているためだと思います。これを修正する方法は?最善の方法はコードを修正することですが、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。したがって、リクエストを処理するために呼び出される最初の子は、この接続を閉じます。しかし、残りの子プロセスはどうなるでしょうか? 彼らは、データベースへの接続が開いていて、おそらく機能していると信じているため、データベース操作を行うと例外が発生します。これがスレッド実行モデルに表示されないのはなぜですか? スレッドが同じオブジェクトを使用しており、他のスレッドがいつ接続を閉じているかを知っているためだと思います。これを修正する方法は?最善の方法はコードを修正することですが、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。したがって、リクエストを処理するために呼び出される最初の子は、この接続を閉じます。しかし、残りの子プロセスはどうなるでしょうか? 彼らは、データベースへの接続が開いていて、おそらく機能していると信じているため、データベース操作を行うと例外が発生します。これがスレッド実行モデルに表示されないのはなぜですか? スレッドが同じオブジェクトを使用しており、他のスレッドがいつ接続を閉じているかを知っているためだと思います。これを修正する方法は?最善の方法はコードを修正することですが、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。しかし、残りの子プロセスはどうなるでしょうか? 彼らは、データベースへの接続が開いていて、おそらく機能していると信じているため、データベース操作を行うと例外が発生します。これがスレッド実行モデルに表示されないのはなぜですか? スレッドが同じオブジェクトを使用しており、他のスレッドがいつ接続を閉じているかを知っているためだと思います。これを修正する方法は?最善の方法はコードを修正することですが、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。しかし、残りの子プロセスはどうなるでしょうか? 彼らは、データベースへの接続が開いていて、おそらく機能していると信じているため、データベース操作を行うと例外が発生します。これがスレッド実行モデルに表示されないのはなぜですか? スレッドが同じオブジェクトを使用しており、他のスレッドがいつ接続を閉じているかを知っているためだと思います。これを修正する方法は?最善の方法はコードを修正することですが、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。しかし、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。しかし、これは難しい場合があります。私の意見では、他のオプションは、アプリケーションの小さなコードのどこかに書くことです。
from django.db import connection
from django.core import signals
def close_connection(**kwargs):
connection.close()
signals.request_started.connect(close_connection)
理想的な考えではありません.DBに2回接続することは、せいぜい回避策です。
考えられる解決策: 接続プーリング (pgpool、pgbouncer) を使用して、DB 接続をプールして安定させ、FCGI デーモンにすばやく渡します。
問題は、これが別のバグを引き起こし、psycopg2 が2 回切断しようとしているため、 InterfaceErrorを発生させることです (pgbouncer は既にこれを処理しています)。
現在、原因は Django シグナルrequest_finishedがconnection.close()をトリガーし、既に切断されていても大声で失敗することです。リクエストがすでに終了しているかのように、DB 接続はもう気にしないので、この動作は望ましくないと思います。これを修正するためのパッチは簡単なはずです。
関連するトレースバック:
/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/core/handlers/wsgi.py in __call__(self=<django.core.handlers.wsgi.WSGIHandler object at 0x24fb210>, environ={'AUTH_TYPE': 'Basic', 'DOCUMENT_ROOT': '/storage/test', 'GATEWAY_INTERFACE': 'CGI/1.1', 'HTTPS': 'off', 'HTTP_ACCEPT': 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate', 'HTTP_AUTHORIZATION': 'Basic dGVzdGU6c3VjZXNzbw==', 'HTTP_CONNECTION': 'keep-alive', 'HTTP_COOKIE': '__utma=175602209.1371964931.1269354495.126938948...none); sessionid=a1990f0d8d32c78a285489586c510e8c', 'HTTP_HOST': 'www.rede-colibri.com', ...}, start_response=<function start_response at 0x24f87d0>)
246 response = self.apply_response_fixes(request, response)
247 finally:
248 signals.request_finished.send(sender=self.__class__)
249
250 try:
global signals = <module 'django.core.signals' from '/usr/local/l.../Django-1.1.1-py2.6.egg/django/core/signals.pyc'>, signals.request_finished = <django.dispatch.dispatcher.Signal object at 0x1975710>, signals.request_finished.send = <bound method Signal.send of <django.dispatch.dispatcher.Signal object at 0x1975710>>, sender undefined, self = <django.core.handlers.wsgi.WSGIHandler object at 0x24fb210>, self.__class__ = <class 'django.core.handlers.wsgi.WSGIHandler'>
/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/dispatch/dispatcher.py in send(self=<django.dispatch.dispatcher.Signal object at 0x1975710>, sender=<class 'django.core.handlers.wsgi.WSGIHandler'>, **named={})
164
165 for receiver in self._live_receivers(_make_id(sender)):
166 response = receiver(signal=self, sender=sender, **named)
167 responses.append((receiver, response))
168 return responses
response undefined, receiver = <function close_connection at 0x197b050>, signal undefined, self = <django.dispatch.dispatcher.Signal object at 0x1975710>, sender = <class 'django.core.handlers.wsgi.WSGIHandler'>, named = {}
/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/__init__.py in close_connection(**kwargs={'sender': <class 'django.core.handlers.wsgi.WSGIHandler'>, 'signal': <django.dispatch.dispatcher.Signal object at 0x1975710>})
63 # when a Django request is finished.
64 def close_connection(**kwargs):
65 connection.close()
66 signals.request_finished.connect(close_connection)
67
global connection = <django.db.backends.postgresql_psycopg2.base.DatabaseWrapper object at 0x17b14c8>, connection.close = <bound method DatabaseWrapper.close of <django.d...ycopg2.base.DatabaseWrapper object at 0x17b14c8>>
/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/backends/__init__.py in close(self=<django.db.backends.postgresql_psycopg2.base.DatabaseWrapper object at 0x17b14c8>)
74 def close(self):
75 if self.connection is not None:
76 self.connection.close()
77 self.connection = None
78
self = <django.db.backends.postgresql_psycopg2.base.DatabaseWrapper object at 0x17b14c8>, self.connection = <connection object at 0x1f80870; dsn: 'dbname=co...st=127.0.0.1 port=6432 user=postgres', closed: 2>, self.connection.close = <built-in method close of psycopg2._psycopg.connection object at 0x1f80870>
ここで例外処理を行うと、より寛大になる可能性があります。
/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/__init__.py
63 # when a Django request is finished.
64 def close_connection(**kwargs):
65 connection.close()
66 signals.request_finished.connect(close_connection)
または、psycopg2 でより適切に処理できるため、接続を切断するだけですでに次のようになっている場合に致命的なエラーをスローしないようにすることができます。
/usr/local/lib/python2.6/dist-packages/Django-1.1.1-py2.6.egg/django/db/backends/__init__.py
74 def close(self):
75 if self.connection is not None:
76 self.connection.close()
77 self.connection = None
それ以外は、アイデアが不足しています。