【发布时间】:2016-03-19 02:22:37
【问题描述】:
我一直在与我的 Flask 应用程序中的一个持续错误作斗争:
OperationalError: (_mysql_exceptions.OperationalError) (2006, 'MySQL server has gone away')
我正在使用 mySQL 服务器实例和 Flask-SQLAlchemy 模块。我仔细检查了 mySQL 实例上连接的过期时间和 SQLAlchemy 配置中的重置时间。那里没有问题,连接池在 mySQL 连接过期之前被重置。我得出的结论是,一定有一些问题导致连接关闭,然后该连接的下一个用户阻塞。
我正在使用产生四个进程的 uWSGI 运行 Flask 应用程序。如果我切换到单个进程,我将无法重现该错误。我猜进程是通过共享连接池互相踩踏的。我添加了以下函数,以便在 uWSGI fork 进程时运行。
from uwsgidecorators import postfork
@postfork
def reset_db_connections():
db.engine.dispose()
在启动时工作正常,并且似乎可以解决同时出现多个请求时的问题。但是,现在当一个进程被重置时,该进程的下一个请求会出现类似但不一样的 SQL Server 已消失错误。这是数据库的初始设置代码
def configure_db():
from my_application.models import SomeModel
db.create_all()
db = SQLAlchemy(app, session_options={'expire_on_commit': False})
configure_db()
数据库的典型用法如下所示:
def save(self):
try:
db.session.add(self)
db.session.commit()
except Exception, ex:
app.logger.error("Error saving campaign: %s" % ex)
db.session.rollback()
读取是以下两种风格之一:
user = db.session.query(User).filter(User.email == email).scalar()
user = User.query.filter(User.email == email).scalar()
我的理解是 Flask-SQLAlchemy 使用范围会话,因此它们应该在多进程环境中提供一些保护。我需要在 fork 上重置连接池吗?分叉时我是否也应该检查实时会话?
更新:
我已经把叉子改成这样:
@postfork
def reset_db_connections():
db.session.close_all()
db.engine.dispose()
db.create_scoped_session()
我仍然收到 OperationalError,但它只发生在分叉期间,并且似乎不会干扰请求。堆栈跟踪不包括叉子,虽然它不允许我抓住它。
Traceback(最近一次调用最后一次):
文件 “/home/vagrant/env/local/lib/python2.7/site-packages/sqlalchemy/pool.py”, 第 636 行,在 _finalize_fairy 中 仙女._reset(池)
文件 “/home/vagrant/env/local/lib/python2.7/site-packages/sqlalchemy/pool.py”, 第 774 行,在 _reset self._reset_agent.rollback()
文件 “/home/vagrant/env/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py”, 第 1563 行,在回滚中 self._do_rollback()
文件 “/home/vagrant/env/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py”, 第 1601 行,在 _do_rollback self.connection._rollback_impl()
文件 “/home/vagrant/env/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py”, 第 670 行,在 _rollback_impl 中 self._handle_dbapi_exception(e, None, None, None, None)
文件 “/home/vagrant/env/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py”, 第 1341 行,在 _handle_dbapi_exception 中 exc_info
文件 “/home/vagrant/env/local/lib/python2.7/site-packages/sqlalchemy/util/compat.py”, 第 199 行,在 raise_from_cause 中 reraise(类型(异常),异常,tb=exc_tb)
文件 “/home/vagrant/env/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py”, 第 668 行,在 _rollback_impl 中 self.engine.dialect.do_rollback(self.connection)
文件 “/home/vagrant/env/local/lib/python2.7/site-packages/sqlalchemy/dialects/mysql/base.py”, 第 2519 行,在 do_rollback 中 dbapi_connection.rollback()
【问题讨论】:
标签: python mysql flask sqlalchemy flask-sqlalchemy