【问题标题】:Flask, SQLAlchemy and MySQL Server has gone awayFlask、SQLAlchemy 和 MySQL Server 已经消失
【发布时间】:2016-06-07 02:52:52
【问题描述】:

我的 Flask 应用程序中有一个与 MariaDB (MySQL) 服务器的 SQLAlchemy 连接。我使用作用域会话,并在应用程序上下文拆解时删除会话。

engine = create_engine(config.SQLALCHEMY_DATABASE_URI, pool_recycle=3600, isolation_level='READ_COMMITTED')
db_session = scoped_session(sessionmaker(autocommit=True, bind=engine))

@app.teardown_appcontext
def shutdown_session(exception=None):
    db_session.remove()

我还使用 uwsgi 和 8 个 worker 将我的应用程序绑定到 nginx。

有时我在请求期间收到错误“MySQL 服务器已消失”。当我重复请求时,我没有错误,但如果我再次重复,我再次收到错误。多次重复请求后,问题消失了。 它会在应用程序重新启动后发生(并非总是如此),有时在 MySQL 重新启动后发生。

This 回答建议每次使用后关闭会话,我认为在 teardown_appcontext 上删除会话是一回事。

我也手动尝试了rollback session,但没有帮助。

【问题讨论】:

  • 这可能有多种原因。我有一个很长的磨难记录在这里stackoverflow.com/questions/34684554/… ....这个具体问题归结为pool_recycle需要设置小于MySQL timeout
  • @Busturdust 我将pool_recycle 设置为小于 MySQL 超时,但这对我没有帮助。很难重现此错误。上次我在 MySQL 服务器重新启动后遇到此错误。但是当我再次重新启动它时,没有出现错误。

标签: python mysql flask sqlalchemy mariadb


【解决方案1】:

以下解决方案适合我。服务器连接错误在自定义 Session 和 Query(用于 ORM 查询)类的方法中处理。

from sqlalchemy import exc, create_engine, MetaData
from sqlalchemy.orm import scoped_session, sessionmaker, Session, Query

MAX_RETRIES = 2

class RetryQuery(Query):
    def _execute_and_instances(self, *args, **kwargs):
        retry = MAX_RETRIES
        while retry:
            retry -= 1
            try:
                return super(RetryQuery, self)._execute_and_instances(*args, **kwargs)
            except exc.SQLAlchemyError as e:
                if e.orig.args[0] in (2006, 2013, 2014, 2045, 2055) and retry and e.connection_invalidated:
                    continue
                else:
                    raise


class RetrySession(Session):
    def __init__(self, *args, **kwargs):
        kwargs['query_cls'] = RetryQuery
        super(RetrySession, self).__init__(*args, **kwargs)

    def execute(self, *args, **kwargs):
        retry = MAX_RETRIES
        while retry:
            retry -= 1
            try:
                return super(ReconnSession, self).execute(*args, **kwargs)
            except exc.SQLAlchemyError as e:
                if e.orig.args[0] in (2006, 2013, 2014, 2045, 2055) and retry and e.connection_invalidated:
                    continue
                else:
                    raise


engine = create_engine(config.SQLALCHEMY_DATABASE_URI, pool_recycle=3600, isolation_level='READ_COMMITTED')
db_session = scoped_session(class_=RetrySession, sessionmaker(autocommit=True, bind=engine))

db_session.execute("SELECT col FROM table")
db_session.query(User).all()

【讨论】:

    【解决方案2】:

    我找到了这个麻烦的真正原因:8个uwsgi worker使用了共享内存。将lazy-apps = true 添加到 uwsgi 配置后,MySQL 连接工作正常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-09
      • 2013-12-31
      • 2015-03-14
      • 2018-12-31
      • 2018-12-27
      • 2011-04-25
      • 1970-01-01
      相关资源
      最近更新 更多