PostgreSQL中从共享队列提取项目的多个调用
如果在一个表中有一个要做的工作队列,该队列将由多个不同的工作者客户端定期轮询……那么防止每个工作者获得相同的工作项的最佳方法是什么 假设一个表,如:ItemId、LastAttemptDateTime、AttemptCount和各种项目详细信息 给定LastAttemptDateTime上的索引并按升序排序,各种客户端都在查询表以获取要处理的项 我使用MS SQL中的存储过程来执行此操作…类似于:PostgreSQL中从共享队列提取项目的多个调用,postgresql,Postgresql,如果在一个表中有一个要做的工作队列,该队列将由多个不同的工作者客户端定期轮询……那么防止每个工作者获得相同的工作项的最佳方法是什么 假设一个表,如:ItemId、LastAttemptDateTime、AttemptCount和各种项目详细信息 给定LastAttemptDateTime上的索引并按升序排序,各种客户端都在查询表以获取要处理的项 我使用MS SQL中的存储过程来执行此操作…类似于: CREATE PROCEDURE GetNextQueueItem AS SET NOCOUNT
CREATE PROCEDURE GetNextQueueItem AS
SET NOCOUNT ON
DECLARE @ItemId INT
UPDATE myqueue SET @ItemId=ItemId, AttemptCount=AttemptCount+1, LastAttemptDateTime=GetDate()
WHERE ItemId=(SELECT TOP 1 ItemId
FROM myqueue
ORDER BY LastAttemptDateTime ASC)
SELECT ItemId, AttemptCount, and various item detail fields
FROM myqueue
WHERE ItemId = @ItemId
我是PostgreSQL的新手,不知道是否有其他方法可用。(顶部1将更改为限制1。)由于PostgreSQL具有独立的序列,以标识列递增,可用于其他用途,一种很好的方法是使用序列在表上设置id,另一种方法用于获取项:
currval
,如果它高于或等于表的max
id,则没有项目等待nextval
。如果没有具有匹配id的项,则循环回1(如果对表的插入失败,则可能发生这种情况)这并不是剥除这只猫皮肤的唯一方法(也不是我在其他数据库中使用的方法),但它的优点是对数据库的写操作很少(只改变序列,而不是表)。PostgreSQL等价物可能如下所示:
CREATE OR REPLACE FUNCTION get_next_queue_item()
RETURNS SETOF myqueue AS
$BODY$
BEGIN
RETURN QUERY
UPDATE myqueue
SET attempt_count = attempt_count + 1
,last_attempt_ts = now()
WHERE item_id = (
SELECT item_id
FROM myqueue
ORDER BY last_attempt_ts
LIMIT 1
)
RETURNING myqueue.*;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;
要点
- 您只需要1语句即可完成所有操作。
可以在与UPDATE
子句相同的命令中返回更新的行。 行的状态为更新后状态。如果需要,可以通过多种方法获取更新前状态RETURNING
- 不需要任何变量
- 我将所有标识符都改为小写,这是PostgreSQL中最干净的样式
- 我将您的专栏
重命名为LastAttemptDateTime
last\u尝试
ts..表示“timestamp”,因为这是Postgres中timestamp/datetime类型的名称 - 正如你提到的那样,
而不是limit1
TOP 1
- 我使用
作为返回类型。返回myqueue的集合
是表的关联行类型myqueue
-对于每个表或视图,都会在PostgreSQL中自动创建同名的行类型。myqueue
此声明允许返回多行,但
保证只返回一行LIMIT 1
- 此返回类型允许直接返回结果行,无需任何中间步骤。快速、干净
UPDATE myqueue
SET attempt_count = attempt_count + 1
,last_attempt_ts = now()
WHERE item_id = (
SELECT item_id
FROM myqueue
ORDER BY last_attempt_ts
LIMIT 1
)
RETURNING myqueue.*;
查看此帖子: