Выбор ответа Senior Транзакции и изоляция обновлено

Долгая транзакция и раздувание таблиц

Вопрос

Сервис открыл транзакцию и забыл её закрыть: соединение несколько часов висит в состоянии idle in transaction. Что происходит с базой?

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: VACUUM не удалит мёртвые версии после её старта, таблицы раздуются. Пока жива транзакция со старым снимком, любая версия строки, которую она теоретически может увидеть, считается нужной, и VACUUM её не удалит.

Варианты ответа

  1. Ничего: транзакция ничего не делает и ресурсов не держит
  2. VACUUM не удалит мёртвые версии после её старта, таблицы раздуютсяправильный ответ
  3. PostgreSQL через 5 минут откатит её автоматически по таймауту
  4. Все остальные транзакции ждут её: она держит блокировку на всю базу

Разбор

Пока жива транзакция со старым снимком, любая версия строки, которую она теоретически может увидеть, считается нужной, и VACUUM её не удалит. В нагруженных таблицах копятся мёртвые строки (bloat), растут индексы, замедляются запросы. Кроме того, она держит блокировки на строки и таблицы, которые успела взять, но не на всю базу. Автоматически такая транзакция не завершается, пока не задан idle_in_transaction_session_timeout; его и стоит выставлять, а искать виновников через pg_stat_activity по state и xact_start.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме