PostgreSQL中从共享队列提取项目的多个调用

PostgreSQL中从共享队列提取项目的多个调用,postgresql,Postgresql,如果在一个表中有一个要做的工作队列,该队列将由多个不同的工作者客户端定期轮询……那么防止每个工作者获得相同的工作项的最佳方法是什么 假设一个表,如:ItemId、LastAttemptDateTime、AttemptCount和各种项目详细信息 给定LastAttemptDateTime上的索引并按升序排序,各种客户端都在查询表以获取要处理的项 我使用MS SQL中的存储过程来执行此操作…类似于: CREATE PROCEDURE GetNextQueueItem AS SET NOCOUNT

如果在一个表中有一个要做的工作队列,该队列将由多个不同的工作者客户端定期轮询……那么防止每个工作者获得相同的工作项的最佳方法是什么

假设一个表,如: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的新手,不知道是否有其他方法可用。(顶部1将更改为限制1。)

由于PostgreSQL具有独立的序列,以标识列递增,可用于其他用途,一种很好的方法是使用序列在表上设置id,另一种方法用于获取项:

  • 查看序列的
    currval
    ,如果它高于或等于表的
    max
    id,则没有项目等待

  • 获取
    nextval
    。如果没有具有匹配id的项,则循环回1(如果对表的插入失败,则可能发生这种情况)

  • 获取具有匹配id的行


  • 这并不是剥除这只猫皮肤的唯一方法(也不是我在其他数据库中使用的方法),但它的优点是对数据库的写操作很少(只改变序列,而不是表)。

    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
      是表的关联行类型
      myqueue
      -对于每个表或视图,都会在PostgreSQL中自动创建同名的行类型。
      此声明允许返回多行,但
      LIMIT 1
      保证只返回一行

    • 此返回类型允许直接返回结果行,无需任何中间步骤。快速、干净

    实际上,您根本不需要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.*;
    
    查看此帖子: