如何在sqlalchemy中正确关闭mysql连接?

Son*_*Son 9 python mysql sqlalchemy flask

我想知道什么是关闭所有mysql连接的正确方法sqlalchemy.对于上下文,它是一个Flask应用程序,所有视图共享同一个session对象.

engine = create_engine("mysql+pymysql://root:root@127.0.0.1/my_database")

make_session = sessionmaker(bind=engine, autocommit=False)

session = ScopedSession(make_session)()
Run Code Online (Sandbox Code Playgroud)

当应用程序被拆除时,它将session被关闭并被engine丢弃

session.close()
engine.dispose()
Run Code Online (Sandbox Code Playgroud)

但根据数据库日志,我仍然有很多错误[Warning] Aborted connection 940 to db: 'master' user: 'root' host: '172.19.0.7' (Got an error reading communication packets).

我已经尝试了一些解决方案,包括电话gc.collect()engine.pool.dispose()但没有成功...

我怀疑场景后引擎仍然打开了一些连接,需要关闭它们.无论如何列出引擎打开的所有会话/连接?

花了很多时间在这上面,任何建议/帮助/指针将非常感谢!谢谢.

PS:disposeclose调用的灵感来自于如何在MySQL中关闭sqlalchemy连接.顺便问一下,什么是"签出"连接?

Seb*_*ian 6

这可能无法完全回答您的问题,但我一直在使用此方法来确保我的所有会话都已关闭.每个使用会话的函数都会获得provide_session装饰器.请注意,session=None参数必须存在.

例如

@provide_session()
def my_func(session=None):
    do some stuff
    session.commit()
Run Code Online (Sandbox Code Playgroud)

我看到它在Incubator-Airflow项目中使用并且非常喜欢它.

import contextlib
from functools import wraps

...
Session = ScopedSession(make_session)

@contextlib.contextmanager
def create_session():
    """
    Contextmanager that will create and teardown a session.
    """
    session = Session()
    try:
        yield session
        session.expunge_all()
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()


def provide_session(func):
    """
    Function decorator that provides a session if it isn't provided.
    If you want to reuse a session or run the function as part of a
    database transaction, you pass it to the function, if not this wrapper
    will create one and close it for you.
    """
    @wraps(func)
    def wrapper(*args, **kwargs):
        arg_session = 'session'

        func_params = func.__code__.co_varnames
        session_in_args = arg_session in func_params and \
            func_params.index(arg_session) < len(args)
        session_in_kwargs = arg_session in kwargs

        if session_in_kwargs or session_in_args:
            return func(*args, **kwargs)
        else:
            with create_session() as session:
                kwargs[arg_session] = session
                return func(*args, **kwargs)

    return wrapper
Run Code Online (Sandbox Code Playgroud)


Son*_*Son 1

最后我找到了罪魁祸首:在后台进程中启动的apschedulersession使用了连接到数据库的连接,并且似乎没有正确释放它。

此外,我们发现在 Flask 应用程序中处理 sqlalchemy 会话的最佳实践是使用scoped_session并确保remove()在请求结束时调用它(即appcontext_teardown)。这也用在flask-sqlalchemy扩展中。