Взаимоблокировки: как ловить и предотвращать
Вопрос
На проде в логах появились ошибки deadlock detected. Как вы будете разбираться и что сделаете, чтобы они ушли?
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Deadlock это цикл ожидания: транзакции держат блокировки и ждут друг друга
PostgreSQL проверяет цикл после `deadlock_timeout` (1 с по умолчанию) и откатывает одну из транзакций с ошибкой 40P01
В логе есть оба запроса и тип блокировок; включаю `log_lock_waits` для долгих ожиданий
Главное лечение: единый порядок взятия блокировок, короткие транзакции, блокировка заранее через `SELECT ... FOR UPDATE` в порядке ключа
Приложение должно уметь повторять транзакцию при 40P01 и 40001
Что могут спросить следом
- Почему внешние ключи могут участвовать в deadlock?
- Чем
FOR UPDATEотличается отFOR NO KEY UPDATE? - Что даёт
lock_timeout?
Разбор
Deadlock это когда транзакция A держит ресурс X и ждёт Y, а B держит Y и ждёт X. Сами они не разойдутся, поэтому PostgreSQL после deadlock_timeout (по умолчанию секунда) проверяет граф ожиданий и откатывает одну из транзакций с ошибкой 40P01, а в лог пишет оба процесса, запросы и виды блокировок. Разбор начинаю с лога: какие запросы и какие строки. Типичные причины: обновление одних строк в разном порядке (переводы A→B и B→A, пакетные обновления без сортировки), длинные транзакции с внешними вызовами внутри. Лечение: брать блокировки в едином порядке, например ORDER BY id FOR UPDATE, держать транзакции короткими, не ходить в сеть внутри транзакции. Для долгих ожиданий включаю log_lock_waits, для DDL выставляю lock_timeout. И в любом случае клиент должен уметь повторить транзакцию при 40P01 и 40001.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Предыдущий вопрос
Как избежать deadlock при переводах
Следующий вопрос
Долгая транзакция и раздувание таблиц