postgresql - 多次调用从 PostgreSQL 中的共享队列中提取项目

标签 postgresql

如果表中有待办工作队列,将由多个不同的工作客户端定期轮询...防止每个工作人员处理相同项目的最佳方法是什么?

比如一个表: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 中最干净的风格。

  • 我将您的专栏重命名为 LastAttemptDateTimelast_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/

相关文章:

php - PHP 的 PostgreSQL API 是否不支持与事务相关的方法?

postgresql - 备份 (AWS) Postgres 数据库的好方法是什么

postgresql - JPA中postgreSQL的DECIMAL对应的Java数据类型是什么?

ruby-on-rails - Heroku 上的 Puma 集群配置

postgresql - 将 Informix 模式转换为 PostgreSQL 模式

postgresql - 如何减少具有有序结果的 postgresql IN 查询的索引扫描时间?

PostgreSQL - "IN"子句中的最大参数数?

postgresql - 列出 Postgres ENUM 类型

java - 尝试使用 JDBC 连接 Heroku 数据库时未找到合适的驱动程序

postgresql - 从 PostgreSQL 中的文本正文中提取所有长度为 1、2 和 3 的 n-gram 的最快方法是什么?