我有一个并行过程,正在PostgreSQL中使用队列表。逻辑是:
多达20个线程正在执行这些步骤。 但是,有时当我尝试对查询执行两步操作时:
UPDATE QUEUE_TABLE
SET QUEUE_TXN_GUID=$RANDOM_GUID,
QUEUE_STATUS=1
WHERE QUEUE_ROW_GUID IN
(SELECT QUEUE_ROW_GUID from QUEUE_TABLE
WHERE QUEUE_STATUS IS NULL OR QUEUE_STATUS = -1
LIMIT 100 FOR UPDATE SKIP LOCKED) RETURNING QUEUE_ROW_GUID
我收到错误消息deadlock detected
。
我在第5步中使用的查询是
UPDATE QUEUE_TABLE SET CDC_QUEUE_REZ_STATUS=$STATUS WHERE CDC_QUEUE_REZ_TXN_GUID=$RANDOM_GUID;
我不知道为什么在第一次更新子查询中使用FOR UPDATE SKIP LOCKED
时会遇到这种奇怪的死锁。
答案 0 :(得分:1)
问题的原因是QUEUE_ROW_GUID
中存在重复项。 Select锁定一些行,但是查询更新不锁定那些行。这就是为什么并发运行的查询可能尝试更新与此行相同的行。因此,SKIP LOCKED
在这种情况下不起作用。
鉴于行的更新可能以不同的顺序发生,第一个查询(试图更新第1行和第2行)可能首先更新第1行,然后尝试更新第2行,但等待锁定。并发运行的查询(也尝试更新1和2)已经更新了第2行,并等待第1行的锁定。因此出现了死锁。
锁定行后,您需要使用唯一标识符来更新行。