Подождите, пока строка станет доступной с SKIP LOCKED - PullRequest
1 голос
/ 05 июля 2019

Я использую PostgreSQL с SKIP LOCKED для реализации очереди, как описано в Для чего SKIP LOCKED в PostgreSQL 9.5? .В принципе, это работает нормально, но иногда, когда рабочие работают быстро и работы не так много, очередь запускается пустой.IOW: SELECT ничего не находит, и поэтому оператор выполняется, ничего не делает в конце, и мы закончили.

Теперь я хотел бы снова выполнить оператор каккак только появится новый ряд, попробуйте еще раз (хотя все остальные работники могут попытаться сделать это тоже).В конце концов, это сводится к опросу базы данных, что, скажем, не оптимально.

Конечно, я мог бы использовать функцию NOTIFY PostgreSQL, чтобы информировать работников, когда новая строка написана, но яИнтересно, возможно ли это в самом SELECT, например, оставить его открытым, пока он не преуспеет и не вернет запись?Нечто такое, как длительный SELECT, который остается открытым столько времени, сколько требуется для возврата результата.

Возможно ли это?

1 Ответ

2 голосов
/ 09 июля 2019

В соответствии с этими ответами невозможно заставить запрос на выборку ожидать результата:

Идея может заключаться в том, чтобы заблокировать таблицу, когда она окажется пустой, и освободить ее до того, как будет произведена вставка, но это звучит жутко ... (см. Там: https://stackoverflow.com/a/17525747/4279120)

Мое мнение таковочто с использованием NOTIFY, даже если он не достигнет именно того, что вы ожидаете, было бы более подходящим здесь , потому что это было сделано для таких случаев.

Конечно, вы могли быреализовать некоторый get_item() метод PL / SQL с помощью простого цикла WHILE, но я предполагаю, что это не то, что вы ищете ...

Просто для получения дополнительных знаний, функция PLSQL, которая ожидает возврата очередипредмет:

CREATE OR REPLACE FUNCTION get_item() 
RETURNS int8 
LANGUAGE plpgsql
AS
$$
DECLARE
    count int8 = 0;
    id int8;
BEGIN
    WHILE id IS Null LOOP
        DELETE FROM queue
        WHERE itemid = (
          SELECT itemid
          FROM queue
          ORDER BY itemid
          FOR UPDATE SKIP LOCKED
          LIMIT 1
        )
        RETURNING itemid INTO id;
        IF id IS Null THEN
           PERFORM pg_sleep(1);
        END IF;
    END LOOP;

    RETURN id;
END;
$$;
...