ТранзакцииПродвинутый
Deadlock (взаимная блокировка)
Ситуация, когда две транзакции ждут блокировок друг друга и не могут продолжить.
Синтаксис
-- Защита от дедлоков: одинаковый порядок блокировок SELECT * FROM ... WHERE id IN (...) ORDER BY id FOR UPDATE;
Объяснение
Дедлок: транзакция A блокирует строку 1, транзакция B блокирует строку 2. A хочет строку 2, B хочет строку 1 — оба ждут вечно.
PostgreSQL автоматически обнаруживает дедлоки и откатывает одну из транзакций с ошибкой.
Как избежать:
- Всегда блокируй ресурсы в одном порядке
- Используй SELECT ... FOR UPDATE SKIP LOCKED для очередей
- Держи транзакции короткими
Пример
-- Безопасная очередь задач SELECT * FROM tasks WHERE status = 'pending' ORDER BY created_at LIMIT 1 FOR UPDATE SKIP LOCKED;
Связанные термины
Анекдоты по теме
Программист: — Я сделал бэкап перед DELETE. DBA: — Молодец. Программист: — А потом забыл, куда сохранил. DBA: — Классика.
Разработчик открывает транзакцию в понедельник. Закрывает в пятницу. Таблица заблокирована всю неделю. В пятницу вечером приходит DBA с молотком.
— Что такое advisory locks? — Пользовательские блокировки вне транзакций. — Пример? — SELECT pg_advisory_lock(12345); — захватить блокировку с ID 12345. — Зачем? — Распределённые mutex: только один воркер обрабатывает задачу с ID 12345. — Как Redis SETNX, но в PostgreSQL. — Именно, без Redis.