总而言之,在线程和进程之间似乎存在着一种混合。该问题一开始就问SQLAlchemy连接池是否是线程安全的,但最后以一个代码例子结束,该例子使用了multiprocessing
.对 "一般问题 "的简短回答是:不,如果使用分叉,你不应该在进程边界上共享一个引擎和它相关的连接池。不过,也有例外。
池的实现本身是线程安全的,通过代理一个替换代码1】也是线程安全的。因为引擎除了保持对池的引用外,并不持有状态。另一方面,从池中检查出来的连接是not线程安全的,以及也不是一个Session
。.
文档说,连接池也不是为多线程设计的。
这有一点误读,因为文档中的原话是关于通过共享连接池的process boundaries, if forking is used. This will likely lead to trouble, because beneath the SQLAlchemy and DB-API layers there is usually a TCP/IP socket or a file handle,以及those should not be operated on concurrently.
在这种特殊情况下,使用NullPool
将是安全的,而其他的则不安全,因为它根本没有池,所以连接不会在进程之间共享,除非有人不顾一切地这么做。
这是否意味着只有3个同时存在的航线 will do some work while others will wait until one or more 航线 will call session.close()
?
假设一个QueuePool
在使用中,设置的大小不是一个硬性限制,有一些溢出的空间。大小决定了在池中持久保持的连接数。如果达到了溢出限制,该调用将等待timeout
秒后才放弃,并举起一个TimeoutError
,如果没有连接可用。
Or there is a chance that >2 航线s将同时使用同一个连接?
Two or more 航线s将不能意外地从一个池子里签出相同的连接,除了一个StaticPool
, but one could explicitly share it between 航线s after (don't).
In the end, "使用引擎和连接的工作--基本用法"涵盖了问题的主要部分。
单个Engine
代表进程管理许多单独的DBAPI连接,并且目的是为了以并行方式调用[强调是后加的]。
对于一个使用os.fork
系统调用的多进程应用程序,或者例如Python的multiprocessing
模块,通常需要为每个子进程使用单独的Engine
。这是因为Engine
维护了对连接池的引用,最终引用了DBAPI连接--这些连接往往不能跨进程移植。被配置为不使用池的Engine
(通过使用NullPool
来实现)就没有这个要求。