我正在尝试为作业队列进行某种更新选择。我需要它来支持影响同一个表或数据库的并发进程此服务器将仅用于队列,因此每个队列的数据库是可接受的。最初我在思考以下内容:
UPDATE state=1,ts=NOW() FROM queue WHERE ID IN (SELECT ID FROM queue WHERE state=0 LIMIT X) RETURN *
我一直在读这会导致竞争条件,我读到SELECT子查询有一个选项可以使用FOR UPDATE,但是那会锁定行,并且会阻塞并发调用我不介意的地方如果他们跳到下一个未锁定的行。
所以我要求的是在postgres中建立一个需要锁定整个数据库最少量的fifo系统的最佳方法。
答案 0 :(得分:0)
执行此操作的典型方法是将其包装在PLPGSQL函数中,选择FOR UPDATE NOWAIT,然后使用异常处理跳过锁定的行。
这会对函数产生一些额外的开销,因为即使没有例外,异常处理也需要额外的处理器周期来管理。
作为一个非常简单的例子:
CREATE OR REPLACE FUNCTION get_all_unlocked_customers() RETURNS SETOF customer
LANGUAGE PLPGSQL AS
$$
RETURN QUERY SELECT * FROM customer FOR UPDATE NOWAIT;
EXCEPTION
WHEN LOCK_NOT_AVAILABLE THEN
-- NO NEED TO DO ANYTHING
END;
END;
$$;