web 项目中 SQLAlchemy session 的生命周期管理

假设已有一个 Session 工厂类:


Session = sessionmaker(bind=some_engine)

那么 session 实例的生命周期可以为:


最短模式 —— 每次请求新建一个 session,用完就 close


@contextmanager
def get_session_scope():
    try:
        s = Session()
        yield s
        s.commit()
    except:
        s.rollback()
    finally:
        s.close()

这种模式不适合 web 项目或者说其缺点主要在于对 连接池(db pool) 的消耗过快。实际使用中发现,被 close 的 session 的 连接并没有即时返回可用状态。因此在请求频繁时,会出现等待连接的情况。


最长模式 —— 全程使用一个 session


session = Session()

这种方式更加不适合 web 项目。因为根据 SQLAlchemy 的文档描述

The Session object is entirely designed to be used in a non-concurrent fashion, which in terms of multithreading means “only in one thread at a time”.

session 并不是线程安全的。这种并发式的 session 使用会导致错误。


Thread-Local模式 —— 生命周期与 request 同步


@app.before_request
def init_session():
    request.session = Session()

@app.tear_down_request
def close_session():
    request.session.close()

这其实才是最适合 web 项目的 session 管理方式。(伪代码中没有写 commit 和 rollback,可自行添加)这样即避免了连接池的过快消耗,又避免了并发问题。这也是 SQLAlchemy 文档中推荐的做法。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。