2011-06-09 30 views
30

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

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

我在这里的问题是我应该怎么做来处理这种情况?

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

回答

33

会话对象是线程安全的,但线程局部From the docs:

“的Session对象完全设计为非并发方式,这在多线程的术语是指用于‘仅在在时间’一个线程..一些过程需要在适当位置这样跨多线程的多线程调用实际上不会获得同一个会话的句柄,我们称之为线程本地存储。“

如果你不想做自己管理线程和会议工作,SQLAlchemy的有ScopedSession对象照顾这对你:

ScopedSession对象默认情况下会[穿线.local()]作为存储,以便为所有调用ScopedSession注册表的人员维护一个单一的Session,但仅限于单个线程的范围内。在另一个线程中调用注册表的调用者会获得一个对其他线程本地的Session实例。

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

Contextual/Thread-local Sessions例子设立自己的线程安全会议:

# 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() 
+2

这不是'session.remove()'? – 2014-11-09 14:18:39

+4

@AllanRuin:如果通过'session'你提到的例子是'some_session',否则。 'session'对象没有'remove'方法。在这种情况下,'Session'是一个'scoped_session'对象。它的'remove'方法标识当前'session'并在放弃它之前调用它的'close'方法。解释[在文档](http://docs.sqlalchemy.org/en/latest/orm/contextual.html?高亮=作用域#sqlalchemy.orm.scoping.scoped_session.remove)。 – bfin 2015-05-29 21:19:50

+2

已更新链接到文档:http://docs.sqlalchemy.org/en/latest/orm/contextual.html – Mahdi 2016-07-11 14:25:30