【发布时间】:2016-01-08 19:25:01
【问题描述】:
我有一个运行独立于用户会话的长时间作业的 Web 应用程序。为了实现这一点,我有一个线程本地 Flask-SQLAlchemy 会话的实现。问题是一天几次,当我访问我的网站时收到MySQL server has gone away 错误。该站点始终在刷新时加载。我认为这个问题与这些线程本地会话有关,但我不确定。
这是我的线程本地会话范围的实现:
@contextmanager
def thread_local_session_scope():
"""Provides a transactional scope around a series of operations.
Context is local to current thread.
"""
# See this StackOverflow answer for details:
# http://stackoverflow.com/a/18265238/1830334
Session = scoped_session(session_factory)
threaded_session = Session()
try:
yield threaded_session
threaded_session.commit()
except:
threaded_session.rollback()
raise
finally:
Session.remove()
这是我的标准 Flask-SQLAlchemy 会话:
@contextmanager
def session_scope():
"""Provides a transactional scope around a series of operations.
Context is HTTP request thread using Flask-SQLAlchemy.
"""
try:
yield db.session
db.session.commit()
except Exception as e:
print 'Rolling back database'
print e
db.session.rollback()
# Flask-SQLAlchemy handles closing the session after the HTTP request.
然后我像这样使用两个会话上下文管理器:
def build_report(tag):
report = _save_report(Report())
thread = Thread(target=_build_report, args=(report.id,))
thread.daemon = True
thread.start()
return report.id
# This executes in the main thread.
def _save_report(report):
with session_scope() as session:
session.add(report)
session.commit()
return report
# These executes in a separate thread.
def _build_report(report_id):
with thread_local_session_scope() as session:
report = do_some_stuff(report_id)
session.merge(report)
编辑:引擎配置
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://<username>:<password>@<server>:3306/<db>?charset=utf8'
app.config['SQLALCHEMY_POOL_RECYCLE'] = 3600
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
【问题讨论】:
-
你也可以发布引擎配置
-
@Busturdust,我已经添加了它们。我什么都不做。 Flask-SQLAlchemy 处理其他所有事情。
-
就我而言,范围会话、pool_recycle 和 teardown_request 都是必需的。到目前为止,我似乎在开发中运行稳定。对于 Flask-SQLAlchemy,你可能不需要拆解,但我不能确定
-
我的理解是 Flask-SQLAlchemy 提供了一个作用域会话,其本地上下文是响应 HTTP 请求的线程——并且该会话为您打开和关闭。我会做更多的阅读,看看是不是这样。
标签: python mysql sqlalchemy