Han*_*nXu 7 postgresql multithreading psycopg2
我使用PostgreSQL作为作业队列.以下是我检索作业并更新其状态的查询:
UPDATE requests AS re
SET
started_at = NOW(),
finished_at = NULL
FROM (
SELECT
_re.*
FROM requests AS _re
WHERE
_re.state = 'pending'
AND
_re.started_at IS NULL
LIMIT 1
FOR UPDATE SKIP LOCKED
) AS sub
WHERE re.id = sub.id
RETURNING
sub.*
Run Code Online (Sandbox Code Playgroud)
现在,我有几台机器,在每台机器上我有一个带有多个线程的进程,并且在每个线程上我都有一个worker.同一进程中的所有工作程序共享一个连接池,通常具有10-20个连接.
问题是,上面的查询会多次返回一些行!
我找不到任何理由.有人可以帮忙吗?
更详细的说,我使用的是Python3和psycopg2.
更新:
我试过@ a_horse_with_no_name的答案,但似乎不行.
我注意到,一个请求被两个查询检索,started_at更新为:
2016-04-21 14:23:06.970897 + 08
和
2016-04-21 14:23:06.831345 + 08
它们仅相差0.14s.
我想知道当这两个连接执行内部SELECT子查询时,两个锁都没有建立?
更新:
更确切地说,我在一台机器上的1个过程中有200个工人(即200个线程).
另请注意,如果您不希望每个线程相互妨碍,则每个线程都必须拥有自己的连接。
如果您的应用程序使用多个执行线程,它们无法同时共享连接。您必须显式控制对连接的访问(使用互斥体)或为每个线程使用一个连接。如果每个线程都使用自己的连接,则需要使用 AT 子句来指定线程将使用哪个连接。
来自: http: //www.postgresql.org/docs/9.5/static/ecpg-connect.html
如果两个线程共享同一个连接,就会发生各种奇怪的事情。我相信这就是您的情况所发生的情况。如果您对一个连接进行锁定,则使用同一连接的所有其他线程都将有权访问锁定的对象。
请允许我建议一种替代方法,这非常简单。使用redis作为队列。您可以简单地使用 redis-py 和 lpush/rpop 方法,也可以使用 python-rq。