Python Flask、SQLAlchemy和MySQL服务器已经消失

Python Flask、SQLAlchemy和MySQL服务器已经消失,python,mysql,flask,sqlalchemy,mariadb,Python,Mysql,Flask,Sqlalchemy,Mariadb,我在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

我在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个工人将我的应用程序绑定到nginx

在请求过程中,有时会出现错误“MySQL服务器已离开”。当我重复请求时,我没有错误,但如果我再次重复,我会再次出错。在多次重复请求后,问题消失了。 它发生在应用程序重启之后(不总是),有时也发生在MySQL重启之后

answer建议每次使用后关闭会话,我认为删除teardown_appcontext上的会话是一样的


我也手动尝试过,但没有任何帮助。

以下解决方案对我来说运行正常。服务器连接错误在自定义会话和查询(对于ORM查询)类的方法中处理


我发现了这个问题的真正原因:8名uwsgi工作人员使用的共享内存。将
lazy apps=true
添加到uwsgi-config-MySQL中后,连接工作正常。

这可能有多种原因。我经历了一段很长的磨难,这里有记载。。。。具体的问题归结为
pool\u recycle
需要设置为小于MySQL
timeout
value@Busturdust我将
pool\u recycle
设置为小于MySQL超时,但这对我没有帮助。很难重现这种错误。上次我在MySQL服务器重新启动后遇到这个错误。但当我重新启动它时,错误并没有出现。
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()