Python Django在PostgreSQL死亡时未重新连接,是否需要自定义后端?
我已经做了一些测试,并且能够确认使用Python Django在PostgreSQL死亡时未重新连接,是否需要自定义后端?,python,django,postgresql,backend,custom-backend,Python,Django,Postgresql,Backend,Custom Backend,我已经做了一些测试,并且能够确认使用Django与PostgreSQL和PGBouncer时,它不会在失去连接时自动重新连接。老实说,我不确定这是一个bug还是设计的。如果它是一个错误,我会很高兴地报告它,如果不是,我想一些解释为什么和如何绕过它,而不是另一个自定义后端 通过在Django 1.8.4和Django 1.8.6上执行以下操作,我相当轻松地完成了这些测试: >>>Model.objects.all().count() 24 # Restart postgres w
Django
与PostgreSQL
和PGBouncer
时,它不会在失去连接时自动重新连接。老实说,我不确定这是一个bug还是设计的。如果它是一个错误,我会很高兴地报告它,如果不是,我想一些解释为什么和如何绕过它,而不是另一个自定义后端
通过在Django 1.8.4
和Django 1.8.6
上执行以下操作,我相当轻松地完成了这些测试:
>>>Model.objects.all().count()
24
# Restart postgres with `sudo service postgres restart`
>>>Model.objects.all().count()
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 318, in count
return self.query.get_count(using=self.db)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/query.py", line 466, in get_count
number = obj.get_aggregation(using, ['__count'])['__count']
File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/query.py", line 447, in get_aggregation
result = compiler.execute_sql(SINGLE)
File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 840, in execute_sql
cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.7/dist-packages/django/db/utils.py", line 98, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
OperationalError: server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
现在来看看代码:
from django.db.backends.postgresql_psycopg2.base import DatabaseError, \
IntegrityError, DatabaseWrapper as PostgresWrapper
class DatabaseWrapper(PostgresWrapper):
def _reconnect(self):
try:
self.connect()
except (DatabaseError, OperationalError):
pass
def ensure_connection(self):
"""
Guarantees that a connection to the database is established.
"""
if self.connection is None:
with self.wrap_database_errors:
self._reconnect()
else:
try:
self.connection.cursor().execute('SELECT 1')
except (DatabaseError, OperationalError):
self._reconnect()
我想我终于明白了。我不完全确定我的第一种方法有什么问题,但这一种似乎工作得更好
class DatabaseWrapper(PostgresWrapper):
def _cursor(self):
if self.connection is not None:
if not self.is_usable():
self.connection.close()
self.connection = None
return super(DatabaseWrapper, self)._cursor()
编辑:最终公开了这项工作。我不确定它是否100%需要,但在服务器上重新启动Postgres服务后,它工作正常。您可以在pypi上找到它,它的名称是django postgreconnect,也可以在GitHub上找到它
class DatabaseWrapper(PostgresWrapper):
def _cursor(self):
if self.connection is not None:
if not self.is_usable():
self.connection.close()
self.connection = None
return super(DatabaseWrapper, self)._cursor()