跨进程共享 psycopg2 / libpq 连接
Sharing psycopg2 / libpq connections across processes
libpq
connections shouldn’t be used by a forked processes, so when using a module such as multiprocessing
or a forking web deploy method such as FastCGI make sure to create the connections after the fork.
从该文档中 the link 可以得出:
On Unix, forking a process with open libpq
connections can lead to unpredictable results because the parent and child processes share the same sockets and operating system resources. For this reason, such usage is not recommended, though doing an exec from the child process to load a new executable is safe.
但是 it seems 使用打开的套接字分叉进程没有内在的问题。那么 psycopg2
在连接打开时警告不要分叉的原因是什么?
我的问题的原因是我看到一个(大概是成功的)multiprocessing approach 在分叉之前打开了一个连接。
也许在某些限制下分叉打开的连接是安全的(例如,只有一个进程实际使用过该连接等)?
您的猜测基本上是正确的:只要您不尝试在多个进程中使用它,在分叉之前打开连接就没有问题。
话虽如此,我认为您误解了您提供的 "multiprocessing approach" link。它实际上演示了在每个 child 中打开一个单独的连接。 (在分叉之前 parent 打开了一个连接,但它没有在任何 child 中使用。)
那里的答案(相对于问题中的代码)给出的改进是重构 - 而不是为队列中的每个任务打开一个新连接 - 每个 child 进程打开一个连接然后共享它跨越在同一个 child 中执行的多个任务(即连接作为参数传递给任务处理器)。
编辑:
作为一般做法,人们应该更喜欢在使用它的进程中创建连接。在引用的答案中,在分叉之前在 parent 中创建了一个连接,然后在 child 中使用。这确实可以正常工作,但也会在 parent 中打开每个 "child connection",这充其量是一种资源浪费,也是导致错误的潜在原因。
libpq
connections shouldn’t be used by a forked processes, so when using a module such asmultiprocessing
or a forking web deploy method such as FastCGI make sure to create the connections after the fork.
从该文档中 the link 可以得出:
On Unix, forking a process with open
libpq
connections can lead to unpredictable results because the parent and child processes share the same sockets and operating system resources. For this reason, such usage is not recommended, though doing an exec from the child process to load a new executable is safe.
但是 it seems 使用打开的套接字分叉进程没有内在的问题。那么 psycopg2
在连接打开时警告不要分叉的原因是什么?
我的问题的原因是我看到一个(大概是成功的)multiprocessing approach 在分叉之前打开了一个连接。
也许在某些限制下分叉打开的连接是安全的(例如,只有一个进程实际使用过该连接等)?
您的猜测基本上是正确的:只要您不尝试在多个进程中使用它,在分叉之前打开连接就没有问题。
话虽如此,我认为您误解了您提供的 "multiprocessing approach" link。它实际上演示了在每个 child 中打开一个单独的连接。 (在分叉之前 parent 打开了一个连接,但它没有在任何 child 中使用。)
那里的答案(相对于问题中的代码)给出的改进是重构 - 而不是为队列中的每个任务打开一个新连接 - 每个 child 进程打开一个连接然后共享它跨越在同一个 child 中执行的多个任务(即连接作为参数传递给任务处理器)。
编辑:
作为一般做法,人们应该更喜欢在使用它的进程中创建连接。在引用的答案中,在分叉之前在 parent 中创建了一个连接,然后在 child 中使用。这确实可以正常工作,但也会在 parent 中打开每个 "child connection",这充其量是一种资源浪费,也是导致错误的潜在原因。