【发布时间】:2015-04-22 17:16:37
【问题描述】:
我正在使用 multiprocessing.Pool 运行多个进程
每个进程都必须查询我的 mysql 数据库。
我目前连接数据库一次,然后在进程之间共享连接
它可以工作,但偶尔会出现奇怪的错误。我已经确认是查询数据库时出现的错误。
我认为问题是因为所有进程都使用相同的连接。
- 正确吗?
当我寻找答案时,我偶然发现了这个问答 How to share a single MySQL database connection between multiple processes in Python
所以我查了 Class pooling.MySQLConnectionPool
- http://dev.mysql.com/doc/connector-python/en/connector-python-connection-pooling.html
- http://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlconnectionpool.html
- http://dev.mysql.com/doc/connector-python/en/connector-python-api-pooledmysqlconnection.html
如果我明白这一点。我将设置一个包含多个连接的池并在进程之间共享该池。然后每个进程将查看该池,如果有可用连接,则使用它,否则等待连接被释放。
- 正确吗?
但后来我发现了这个问答 Accessing a MySQL connection pool from Python multiprocessing
“mata”似乎首先证实了我的怀疑,但同时他驳斥了设置一个在进程之间共享的池的使用
在不同进程之间共享数据库连接(或连接池)是个坏主意(我非常怀疑它是否能正常工作),
相反,他建议
所以每个使用它自己的连接的进程实际上是你应该瞄准的。
这是什么意思?
- 我应该为每个工作人员创建一个连接吗? 那么mysql池有什么用呢?
mata 在他的回答中给出的例子似乎很合理,但我不明白整个池作为 init 参数的传递
p = Pool(initializer=init)
- 为什么?(正如 ph_singer 在 cmets 中指出的那样,这不是一个好的解决方案)
将阻塞的 Pool.map() 方法更改为 Pool.map_async() 并将连接从池发送到 map_async(q, ConnObj) 就足够了?
- 正确吗?
在 cmets 中提到
使用具有多个进程的单个池的唯一方法是拥有一个专用进程,该进程使用队列与所有数据库访问进行通信
更新 找到这个。似乎同意:https://stackoverflow.com/a/26072257/1267259
如果您需要大量并发工作人员,但他们并不一直使用数据库,那么您应该拥有一组数据库工作进程来处理所有数据库访问并与其他工作进程交换数据。每个数据库工作进程都有一个数据库连接。其他进程仅通过您的数据库工作者与数据库对话。
Python 的多处理队列、fifo 等为此提供了适当的消息传递功能。
- 这真的正确吗?
mysql 池的目的不是处理进程的请求并将它们中继到可用的连接吗?
现在我很困惑......
【问题讨论】:
-
你读过the documentation关于这个吗?基本上,这个想法是在主进程中创建一个连接池,然后在每个衍生的线程/进程中,您从该池中请求连接。线程不应该共享相同的连接,因为这样线程可以相互阻止线程应该帮助的主要活动之一:IO。
-
另一种非常好的方法是将请求连接的代码仅放在代码的线程/进程特定部分中,以便每个线程都有自己的连接(以及其中隐含的“池” case 是实际的数据库驱动程序本身,它支持并发连接)。特别是对于那些只需要快速连接以独立于其他进程/线程来查询数据的令人尴尬的并行问题,这是有道理的。但是,您失去的是对连接总数和(与带有 ISAM 的 MySQL 无关)事务管理的显式控制。
-
"为什么使用 [db connections] 池" -- 如果您的工作进程中有多个 线程,那么该池可能很有用(几个线程可以并行读取/写入数据(CPython 可以在 I/O 期间释放 GIL)。如果每个工作进程只有一个线程,那么没有必要使用数据库池。
-
@user1267259:没有。这是我之前提到的基本误解:“不要在进程之间传递池”——大多数池实现不能传递(并且他们不应该)。从每个进程的单个 db 连接开始(或者如果其中有多个 db 交互线程,则在工作进程中创建 inside 的 db 连接池) -- if它会中断然后准确描述您的具体情况。
-
@user1267259:是的。它们是有区别的。但没关系。你也不应该这样做。你什么都没通过。如果需要,每个子进程都会创建自己的数据库连接(单独或作为池)。
标签: python mysql python-3.x multiprocessing