gpt4 book ai didi

python - os.fork() 之后的共享对象

转载 作者:太空宇宙 更新时间:2023-11-04 10:35:50 24 4
gpt4 key购买 nike

在使用多个进程与数据库交互时,我遇到了一些奇怪的应用程序行为。我正在使用 Linux。

我有自己的 QueryExecutor 实现,它在其生命周期内使用单个连接:

class QueryExecutor(object):
def __init__(self, db_conf):
self._db_config = db_conf
self._conn = self._get_connection()

def execute_query(self, query):
# some code
# some more code

def query_executor():
global _QUERY_EXECUTOR
if _QUERY_EXECUTOR is None:
_QUERY_EXECUTOR = QueryExecutor(some_db_config)
return _QUERY_EXECUTOR

Query Executor 在实例化后永远不会被修改。

最初只有一个进程,它会时不时地 fork (os.fork()) 几次。新进程是执行一些任务然后退出的 worker 。每个工作人员都调用 query_executor() 来执行 SQL 查询。

我发现sql查询经常返回错误的结果(好像有时候sql查询结果返回到错误的进程)。唯一合理的解释是所有进程共享相同的 sql 连接(根据 MySQLdb 文档:threadsafety = 1 线程可以共享模块,但不能共享连接)。

不知道是什么OS机制导致了这种情况。据我所知,在 Linux 上,当进程 fork 时,父进程的页面不会为子进程复制,它们由两个进程共享,直到其中一个尝试修改某些页面(写时复制).正如我之前提到的,QueryExecutor 对象在创建后保持不变。我想这就是所有进程使用相同的 QueryExecutor 实例并因此使用相同的 sql 连接的原因。

我是对的还是我错过了什么?你有什么建议吗?

提前致谢!

格热戈日

最佳答案

问题的根源在于fork()只是创建了一个进程的完全独立的副本,但这两个进程share opened files, sockets and pipes .这就是为什么 MySQL 服务器写入的任何数据可能 [正确] 只能从单个进程读取,如果两个进程尝试发出请求并读取响应,那么它们很可能会相互干扰工作。这与“多线程”无关,因为在多线程的情况下,只有一个进程和很少的执行线程,它们共享数据并可以协调。

使用fork() 的正确方法是close (或重新打开)在除进程的一个副本之外的所有文件句柄类对象之后立即 fork ,或者至少避免在多个进程中使用它们。

关于python - os.fork() 之后的共享对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23385700/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com