Grz*_*zes 1 python unix multiprocessing
我在使用许多进程与数据库交互时遇到了一些奇怪的应用程序行为。我正在使用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
Run Code Online (Sandbox Code Playgroud)
Query Executor实例化后永远不会被修改。
最初只有一个进程,它时不时会 fork ( os.fork()) 几次。新进程是执行一些任务然后退出的工作进程。每个工作人员调用query_executor()都能够执行 SQL 查询。
我发现sql查询经常返回错误的结果(似乎有时sql查询结果返回到错误的进程)。唯一合理的解释是所有进程共享相同的sql连接(根据MySQLdb文档:threadsafety = 1线程可以共享模块,但不能共享连接)。
我想知道是哪种操作系统机制导致了这种情况。据我所知,在Linux上,当进程分叉时,父进程的页面不会被复制给子进程,它们由两个进程共享,直到其中一个进程尝试修改某些页面(写入时复制)。正如我之前提到的,QueryExecutor对象在创建后保持不变。QueryExecutor我想这就是所有进程使用相同实例并因此使用相同 sql 连接的原因。
我是对的还是我错过了什么?你有什么建议吗?
提前致谢!
格热戈日
问题的根源在于,fork()只是创建了一个进程的精确独立副本,但这两个进程共享打开的文件、套接字和管道。这就是为什么 MySQL 服务器写入的任何数据可能只能从单个进程中[正确地]读取,如果两个进程尝试发出请求并读取响应,那么它们很可能会扰乱彼此的工作。这与“多线程”无关,因为在多线程的情况下,有一个进程只有很少的执行线程,它们共享数据并可能进行协调。
正确的使用方法fork()是在进程的所有副本(除了一个副本)中分叉所有类似文件句柄的对象后立即关闭(或重新打开),或者至少避免从多个进程中使用它们。
| 归档时间: |
|
| 查看次数: |
2290 次 |
| 最近记录: |