一、scoped_session介绍
scoped_session可以理解为session的注册器。
注意事项:
缺省情况下,scoped_session注册表使用Python threading.local()来跟踪Session实例。 这并不一定与所有应用服务器兼容,特别是那些使用greenlet或其他可选并发控制形式的应用服务器,当在中等到高并发场景中使用时,这可能会导致竞争条件(例如随机发生的故障)。需要更全面地理解使用threading.local()跟踪会话对象的含义,并考虑在使用非基于传统线程的应用服务器时使用更显式的作用域方法。
scoped_session对象是许多SQLAlchemy应用程序使用的非常流行和有用的对象。 但是,需要注意的是,它只提供了解决会话管理问题的一种方法。 如果您对SQLAlchemy不熟悉,特别是如果“线程局部变量”这个术语对您来说很陌生,我们建议您首先熟悉现有的集成系统,如Flask-SQLAlchemy或zope.sqlalchemy。
二、scoped_session的工作原理
熟悉多线程编程的用户会注意到,将任何东西表示为全局变量通常都不是一个好主意,因为这意味着该全局对象将被多个线程并发地访问。 Session对象完全被设计为以非并发方式使用,就多线程而言,这意味着“一次只在一个线程中”。 因此,我们上面的scoped_session使用示例(在该示例中,在多个调用中维护同一个Session对象)表明,需要适当设置一些进程,以便跨多个线程的多个调用实际上不能获得同一个会话的句柄。 我们将这个概念称为线程本地存储,这意味着使用一个特殊的对象来维护每个应用程序线程的不同对象。 Python通过threading.local() 结构提供了这一点。 缺省情况下,scoped_session对象使用这个对象作为存储,因此为所有调用scoped_session注册表的人维护单个会话,但只在单个线程的范围内。 在不同线程中调用注册表的调用者将获得该其他线程本地的Session实例。
使用这种技术,scoped_session提供了一种快速且相对简单(如果熟悉线程本地存储)的方法,可以在应用程序中提供单个全局对象,可以安全地从多个线程调用该对象。
scoped_session.remove()方法一如既往地删除与线程关联的当前Session(如果有的话)。 然而,thread .local()对象的一个优点是,如果应用程序线程本身结束,该线程的“存储”也会被垃圾回收。 因此,在生成和删除线程的应用程序中使用线程局部作用域实际上是“安全的”,而不需要调用scoped_session.remove()。 然而,事务本身的作用域,即通过Session.commit()或Session.rollback()结束事务,通常仍然是必须在适当的时间显式安排的,除非应用程序实际将线程的生命周期与事务的生命周期绑定。
三
二、在web框架中使用scoped_session
使用上面的流程,将Session与web应用程序集成的过程有两个要求:
Web Server Web Framework SQLAlchemy ORM Code
startup -> Web framework # Session registry is established
initializes Session = scoped_session(sessionmaker())
incoming
web request -> web request -> # The registry is optionally
starts # called upon explicitly to create
# a Session local to the thread and/or request
Session()
# the Session registry can otherwise
# be used at any time, creating the
# request-local Session() if not present,
# or returning the existing one
Session.query(MyClass) # ...
Session.add(some_object) # ...
# if data was modified, commit the
# transaction
Session.commit()
web request ends -> # the registry is instructed to
# remove the Session
Session.remove()
sends output <-
outgoing web <-
response
正如前面提到的,上面的模式只是将Session与web框架集成的一种可能的方式,它特别地假设web框架将web请求与应用线程关联起来。 然而,强烈建议使用web框架本身提供的集成工具(如果可用的话),而不是scoped_session。
X、参考文档
1.Contextual/Thread-local Sessions
https://docs.sqlalchemy.org/en/14/orm/contextual.html?highlight=scoped_session#thread-local-scope