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;
$$;