如果表中有待办工作队列,将由多个不同的工作客户端定期轮询...防止每个工作人员处理相同项目的最佳方法是什么?
比如一个表:ItemId、LastAttemptDateTime、AttemptCount 和各种项目详细信息。
给定 LastAttemptDateTime 的索引并按升序排序,各种客户端正在查询表以获取要处理的项目。
我在 MS SQL 中使用存储过程来执行此操作...类似:
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 的新手,想知道是否有可用的替代方法。 (TOP 1 将变为 LIMIT 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_attempt_ts
ts .. 代表“时间戳”,因为这是 Postgres 中时间戳/日期时间类型的名称。正如您自己提到的,
LIMIT 1
而不是TOP 1
.我使用
RETURNS SETOF myqueue
作为返回类型。
myqueue
是表的关联行类型myqueue
- 对于每个表或 View ,在 PostgreSQL 中自动创建同名的行类型。
此声明允许返回多行,但LIMIT 1
保证它只会是一个。此返回类型允许 RETURN QUERY直接返回结果行,无需任何中间步骤。快速、干净。
实际上,您根本不需要 plpgsql 函数。您可以使用简单的 SQL 语句:
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.*;
关于postgresql - 多次调用从 PostgreSQL 中的共享队列中提取项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8452774/