Иногда нужно запретить параллельную обработку одного объекта, но подходящей строки для
FOR UPDATE ещё может не быть.SELECT pg_advisory_xact_lock(10, 42);
pg_advisory_xact_lock создаёт транзакционную пользовательскую блокировку. Первый аргумент удобно использовать как namespace, второй — как id объекта.SELECT pg_advisory_xact_lock(20, user_id);
Пока транзакция не завершится, другой процесс с тем же ключом будет ждать. После
COMMIT или ROLLBACK блокировка снимается автоматически.SELECT pg_try_advisory_xact_lock(20, user_id);
Если ждать нельзя, используй
pg_try_advisory_xact_lock: он сразу вернёт true или false, и приложение сможет аккуратно пропустить задачу.BEGIN;
SELECT pg_advisory_xact_lock(30, 123);
UPDATE invoices SET status = 'paid' WHERE id = 123;
COMMIT;
advisory lock не блокирует таблицу и не заменяет ограничения БД. Это кооперативная блокировка, поэтому все участники должны использовать один и тот же ключ.🔥 Полезно для идемпотентных операций, генерации документов, биллинга, обработки вебхуков и любых мест, где один и тот же объект нельзя обрабатывать параллельно.
➡️ SQL Ready | #совет
