pip install mysql_server_has_gone_away
settings.py:
DATABASES = {
'default': {
'ENGINE': 'mysql_server_has_gone_away'
}
}
TL;DR
在我的情况下,我使用的是 django ORM 和 long living request (webocket)。 CONN_MAX_AGE 在我的情况下不起作用。
一开始我创建了一个包装器来尝试捕获错误,但是由于 django 延迟加载,它只是不清楚你应该为哪些东西包装它。所以我最终在整个项目中复制了这段代码,这让我很头疼。而不是写例如User.objects.get(id=3) 我会做do_db(User.objects.get, id=3),而数据库是try: return callback(*args, **kwargs); catch e: conn.close(); callback(*args, **kwargs)。
在深入研究 django 后端时,我们可以在连接级别迁移此解决方案。因此,进入 db 的每个查询都将被包裹起来:
settings.py:
DATABASES = {
'default': {
'ENGINE': 'lol'
}
}
lol/base.py:
"""
https://stackoverflow.com/a/60894948/3872976
"""
from django.db.backends.mysql import base
def check_mysql_gone_away(db_wrapper):
def decorate(f):
def wrapper(self, query, args=None):
try:
return f(self, query, args)
except (base.Database.OperationalError, base.Database.InterfaceError) as e:
if 'MySQL server has gone away' in str(e):
db_wrapper.connection.close()
db_wrapper.connect()
self.cursor = db_wrapper.connection.cursor()
return f(self, query, args)
# Map some error codes to IntegrityError, since they seem to be
# misclassified and Django would prefer the more logical place.
if e.args[0] in self.codes_for_integrityerror:
raise base.utils.IntegrityError(*tuple(e.args))
raise
return wrapper
return decorate
class DatabaseWrapper(base.DatabaseWrapper):
def create_cursor(self, name=None):
class CursorWrapper(base.CursorWrapper):
@check_mysql_gone_away(self)
def execute(self, query, args=None):
return self.cursor.execute(query, args)
@check_mysql_gone_away(self)
def executemany(self, query, args):
return self.cursor.executemany(query, args)
cursor = self.connection.cursor()
return CursorWrapper(cursor)
您应该注意,如果您在原子操作期间 mysql 断开连接,您将遇到事务问题。但不幸的是,没有其他办法。