多线程使用SQLAlchemy

maa*_*det 49 python multithreading sqlalchemy

我想创建一个用Python编写的数据库应用程序编程接口,并使用SQLAlchemy(或任何其他数据库连接器,如果它被告知使用SQLAlchemy进行此类任务不是一个好方法).该设置是在Linux或BSD上运行的MySQL服务器,以及在Linux或BSD机器上运行的Python软件(外部或本地).

基本上我想要做的是为每个连接生成一个新线程,协议将是自定义的并且非常简单,尽管对于每个请求我想打开一个新事务(或者我读过的会话)然后我需要提交会议.我现在面临的问题是,另一个会话很可能同时从另一个连接发生.

我的问题是我应该怎样处理这种情况?

  • 我应该使用锁定,因此只能同时运行一个会话吗?
  • 会话实际上是线程安全的,我认为它们不是吗?
  • 有没有更好的方法来处理这种情况?
  • 是不是要走的路?

cul*_*lix 52

会话对象不是线程安全的,但是是线程本地的.来自文档:

"该Session对象完全被设计为以非并发方式使用,在多线程方面意味着"一次仅在一个线程中".某些进程需要到位,以便多个线程之间的多个调用不会实际上得到了同一个会话的句柄.我们称之为概念线程本地存储."

如果您不想自己管理线程和会话,SQLAlchemy有一个ScopedSession对象可以为您处理:

ScopedSession默认情况下,该对象使用[threading.local()]作为存储,因此Session为所有调用ScopedSession注册表的人维护单个,但仅在单个线程的范围内.在另一个线程中调用注册表的调用者获取该另一个线程的本地会话实例.

使用这种技术,它ScopedSession提供了一种快速且相对简单的方法,可以在应用程序中提供可以安全地从多个线程调用的单个全局对象.

请参阅上下文/线程局部会话中的示例以设置您自己的线程安全会话:

# set up a scoped_session
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker

session_factory = sessionmaker(bind=some_engine)
Session = scoped_session(session_factory)

# now all calls to Session() will create a thread-local session
some_session = Session()

# you can now use some_session to run multiple queries, etc.
# remember to close it when you're finished!
Session.remove()
Run Code Online (Sandbox Code Playgroud)

  • @AllanRuin:如果通过`session`你的意思是来自提供的例子的`some_session`,没有.`session`对象没有`remove`方法.在这种情况下,`Session`是一个`scoped_session`对象.它的`remove`方法识别当前的`session`并在丢弃它之前调用它的`close`方法.解释[在文档中](http://docs.sqlalchemy.org/en/latest/orm/contextual.html?highlight=scoped#sqlalchemy.orm.scoping.scoped_session.remove). (5认同)
  • 这不是`session.remove()`? (3认同)
  • 更新了文档的链接:http://docs.sqlalchemy.org/en/latest/orm/contextual.html (2认同)
  • 发动机怎么样?你在主线程中保留一个全局引擎吗?或者你为每个线程创建一个引擎? (2认同)
  • @culix:介意在您的答案中添加有关引擎的详细信息吗?我一直在阅读,在并行化时,必须确保每个进程仅存在一个引擎。对于多线程,这很容易,对于多处理,可能需要更多的工作。参见http://docs.sqlalchemy.org/en/latest/core/connections.html#engine-disposal (2认同)