sqlalchemy中的scoped_session(session_maker())或plain session_maker()?

nor*_*ner 30 python django orm sqlalchemy flask-sqlalchemy

我在我的网络项目中使用SQlAlchemy.我应该使用scoped_session(session_maker())或plain session_maker()以及为什么?或者我应该使用其他东西?

## model.py
from sqlalchemy import *
from sqlalchemy.orm import *

engine = create_engine('mysql://dbUser:dbPassword@dbServer:dbPort/dbName',
pool_recycle=3600, echo=False)
metadata = MetaData(engine)
Session = scoped_session(sessionmaker())
Session.configure(bind=engine)
user = Table('user', metadata, autoload=True)

class User(object):
pass

usermapper = mapper(User, user)

## some other python file called abc.py
from models import *

def getalluser():
   session = Session()  
   session.query(User).all()
   session.flush()
   session.close()

## onemore file defg.py
from models import *

def updateuser():
   session = Session()  
   session.query(User).filter(User.user_id == '4').update({User.user_lname: 'villkoo'})
   session.commit()
   session.flush()
   session.close()
Run Code Online (Sandbox Code Playgroud)

我为每个请求创建一个session = Session()对象,然后关闭它.我做对了还是有更好的方法吗?

tuo*_*mur 30

建议阅读文档:

提供了scoped_session()函数,该函数生成一个Session对象的线程管理注册表.它通常用于Web应用程序,因此可以使用单个全局变量来安全地表示具有对象集的事务会话,这些对象集中在单个线程中.

简而言之,使用scoped_session()来保证线程安全.

  • @DanielKluev,这是一个很长的页面,自你的评论以来已经有一段时间了,所以也许我正在读错页面或者页面已经改变了,但似乎页面正好相反.对我来说,"不要这样做"代码示例似乎与OP的代码示例中使用的模式非常相似,其中为每个数据库请求创建了一个新会话.这是一个混合的术语问题(网页请求与数据库请求)还是我错过的两个片段之间有区别? (6认同)
  • @northlondoner,不仅是它的安全,而且是推荐的做事方式,见http://www.sqlalchemy.org/docs/orm/session.html#lifespan-of-a-contextual-session (4认同)
  • @mmitchell 目前的文档可能更清楚:[Session 不是线程安全对象](https://docs.sqlalchemy.org/en/13/orm/session_basics.html#is-the-session-thread-安全),并且[tuomur答案中指出的同一篇文章](https://docs.sqlalchemy.org/en/13/orm/contextual.html#contextual-thread-local-sessions)仍然存在并且有效,以某种方式解释它是如何工作的,带有一个[Web应用程序显式示例](https://docs.sqlalchemy.org/en/13/orm/contextual.html#using-thread-local-scope-with-web-applications)。 (3认同)
  • 谢谢。为每个请求打开和关闭会话对象是否安全? (2认同)

Bas*_*usa 11

不要使用scoped_session,也不要使用Flask-SQLAlchemy。

\n

只需Session = sessionmaker()在单例/服务类中使用,并session = Session()在每个 HTTP 请求上使用即可保证提供新的连接。

\n

线程本地存储很笨拙,并且涉及保持状态,这与不同的 Web 服务器线程模型不能很好地配合。最好保持无国籍状态。例如,请参阅 SqlAlchemy\'s 文档,其中提到.remove()如果您正在使用scoped_session. 有人会记得这样做吗?

\n

以下是https://docs.sqlalchemy.org/en/14/orm/contextual.html#using-thread-local-scope-with-web-applications的摘录:

\n
\n

使用上述流程,将 Session 与 Web 应用程序集成的过程恰好有两个要求:

\n
    \n
  • 当 Web 应用程序首次启动时创建一个scoped_session注册表,确保应用程序的其余部分可以访问该对象。

    \n
  • \n
  • 确保scoped_session.remove()在 Web 请求结束时调用,通常通过与 Web 框架\xe2\x80\x99s 事件系统集成来建立 \xe2\x80\x9con 请求结束\xe2\x80\x9d 事件。

    \n
  • \n
\n
\n


Abd*_*der 9

Scoped_session在每个方法中都会为你提供一个你无法事先获得的本地会话线程(比如在模块级别).不需要在每个方法中打开一个新会话,你可以使用全局会话,仅在创建会话时全局会话不可用.即你可以编写一个返回会话的方法,并将其添加到包内的init .py中.