PostgreSQL выбирает одновременное обновление

Я пытаюсь выбрать какое-то обновление для очереди заданий. Он мне нужен для поддержки одновременных процессов, влияющих на одну и ту же таблицу или базу данных. Этот сервер будет использоваться только для очереди, поэтому база данных для каждой очереди является приемлемой. Первоначально я думал о чем-то вроде следующего:

UPDATE state=1,ts=NOW() FROM queue WHERE ID IN (SELECT ID FROM queue WHERE state=0 LIMIT X) RETURN *

Я читал, что это вызовет состояние гонки, я прочитал, что для подзапроса SELECT есть опция использования FOR UPDATE, но тогда это заблокирует строку, и параллельные вызовы будут заблокированы, где я не возражаю, если они пропустят перейти к следующему разблокированному ряду.

Итак, что я прошу, так это лучший способ иметь систему fifo в postgres, которая требует минимального количества блокировок всей базы данных.

1 ответ

Типичный способ сделать это - обернуть его в функцию PLPGSQL, выбрать FOR UPDATE NOWAIT, а затем использовать обработку исключений, чтобы пропустить заблокированные строки.

Это накладывает некоторые дополнительные издержки на функцию, поскольку обработка исключений требует дополнительных циклов процессора для управления, даже если исключений нет.

В качестве очень простого примера:

 CREATE OR REPLACE FUNCTION get_all_unlocked_customers() RETURNS SETOF customer
 LANGUAGE PLPGSQL AS
 $$
 RETURN QUERY SELECT * FROM customer FOR UPDATE NOWAIT;
 EXCEPTION
    WHEN LOCK_NOT_AVAILABLE THEN
    -- NO NEED TO DO ANYTHING
    END;
 END;
 $$;
Другие вопросы по тегам