PostgreSQL работает на MVCC (Multi-Version Concurrency Control) — механизме, при котором обновление строки не удаляет старую версию, а оставляет её висеть с пометкой «мёртвая» (dead tuple). Транзакции изолированы — это хорошо. Но «мёртвые» строки никуда не деваются сами по себе и тихо съедают место на диске.
VACUUM делает три вещи, без которых база рано или поздно встанет:
- Освобождение места — помечает пространство «мёртвых» строк как пригодное для новых данных (именно помечает, а не возвращает ОС — для этого нужен VACUUM FULL)
- Обновление карты видимости — без актуальной visibility map Index-Only Scans вынуждены лезть в heap, теряя всё своё преимущество по скорости
- Заморозка старых транзакций — предотвращает Transaction ID Wraparound, который в худшем случае кладёт базу полностью и безвозвратно
Без регулярного VACUUM база раздуется до неприличных размеров, запросы начнут спотыкаться о «мёртвые» строки при каждом сканировании, а после ~2 миллиардов транзакций PostgreSQL просто остановится сам — принудительно, чтобы не допустить wraparound. Мы видели такое в проде. Это больно.
Оставить комментарий