Почему удалённые строки не уменьшают размер базы данных
Архитектура многоверсионного управления параллельным доступом (Multi-Version Concurrency Control, MVCC) в PostgreSQLQL, будучи основой параллельных операций с базой данных, имеет неизбежную цену: разрастание таблиц (table bloat). Когда строка обновляется, PostgreSQLQL не изменяет её на месте, а записывает совершенно новую копию и помечает старую версию как «мёртвую». Этот механизм гарантирует, что транзакции всегда видят согласованный снимок данных, но оставляет после себя след устаревших данных.
Со временем процессы VACUUM очищают эти мёртвые строки, делая их место доступным для новых данных в той же таблице. Важно, что обычная операция VACUUM не возвращает освобождённое место операционной системе. Если удалить половину таблицы, файл на диске зачастую остаётся прежнего размера, что нередко вызывает недовольство администраторов БД.
Исторически единственным встроенным способом физически уменьшить таблицу и вернуть место ОС был VACUUM FULL. Эта команда перезаписывает всю таблицу, уплотняя её на новых страницах диска. Однако VACUUM FULL устанавливает блокировку ACCESS EXCLUSIVE, блокируя все операции чтения и записи в таблице до своего завершения — последствия настолько серьёзны, что даже собственная документация PostgreSQLQL не рекомендует использовать её в производственных средах. Из-за этого администраторам БД приходилось полагаться на сторонние расширения, такие как pg_repack, для онлайн-уплотнения таблиц.
REPACK выносит тяжёлую работу из критического пути
PostgreSQLQL 19 наконец предоставляет администраторам БД встроенное онлайн-решение проблемы разрастания таблиц: REPACK CONCURRENTLY. Эта команда обходит блокирующий VACUUM FULL, создавая новую компактную версию таблицы и позволяя при этом выполнять параллельное чтение и запись в исходную. Это меняет правила игры для поддержания производительности без простоя.
Механизм остроумен: REPACK сначала копирует все актуальные строки во временную новую таблицу. Затем, что принципиально важно, он использует логическое декодирование на основе WAL, чтобы захватить все изменения (вставки, обновления, удаления), произошедшие в исходной таблице во время копирования. Захваченные изменения воспроизводятся в новой таблице, что гарантирует её полную актуальность.
Наконец, REPACK устанавливает кратковременную исключительную блокировку, чтобы атомарно заменить старый файл таблицы новым, компактным. Это минимизирует критическое окно, в течение которого таблица недоступна. Тест Better Stack показал, что таблица размером 493 MB сократилась до 228 MB менее чем за 10 секунд, оставаясь при этом доступной вплоть до финального мгновенного переключения. Это не универсальный бенчмарк, но он показывает значительную экономию дискового пространства и операционную эффективность REPACK.
Крошечная блокировка, способная вызвать большой затор
REPACK CONCURRENTLY не творит чудес, а лишь переносит тяжёлую работу. Хотя основная часть копирования таблицы выполняется онлайн, финальный решающий шаг — замена старого файла таблицы новым, уплотнённым — требует исключительной блокировки. Эта блокировка ACCESS EXCLUSIVE препятствует любым параллельным операциям с таблицей, будь то чтение или запись. Это крошечное атомарное окно, но оно должно дождаться завершения каждой активной транзакции, затрагивающей эту таблицу.
Это узкое место создаёт существенный операционный риск. Тест Better Stack наглядно это продемонстрировал: 20-секундный аналитический отчёт, выполнявшийся в момент переключения, задержал финальную подмену. Из-за этого все последующие запросы к этой таблице выстроились в очередь на целых 18 секунд, что фактически создало ситуацию head-of-line blocking (блокировки головы очереди). Преимущество онлайн-перепаковки снижается, если один долгий запрос может нарушить параллельные операции.
Чтобы снизить этот риск, относитесь к финальному переключению как к критическому событию. Планируйте REPACK CONCURRENTLY на часы минимальной нагрузки, когда долгие отчёты или пакетные задания вряд ли будут конкурировать за таблицу. Заранее проверяйте наличие активных сеансов на целевой таблице перед запуском команды или обратитесь к таким ресурсам, как PostgreSQLQL Documentation: Routine Vacuuming, чтобы узнать больше об обслуживании таблиц. Цель — обеспечить, чтобы подмена метаданных происходила без неожиданных задержек, превращая хитрый приём в надёжный операционный инструмент.
Нравится статья? Получайте такие каждое утро на почту.
одно письмо в день · отписка в два клика · без сторонних трекеров
Встроенный инструмент — не повод отказываться от планирования
Встроенная команда REPACK CONCURRENTLY в PostgreSQLQL 19 — убедительная альтернатива сторонним инструментам, таким как pg_repack, который более десяти лет был опорой сообщества. Встроенная поддержка упрощает управление расширениями, устраняет проблемы совместимости и потенциально улучшает интеграцию с основными операциями базы данных. Эта эволюция отражает растущую тенденцию к переносу важных функций администрирования БД в ядро.
Однако «встроенный» не означает «волшебный». Хотя в видео Better Stack указана целевая дата выпуска PostgreSQLQL 19 — 19 ноября, перед планированием любой миграции пользователям необходимо проверить актуальный статус релиза и поддержку со стороны провайдера. Управляемые сервисы, в частности, могут откладывать внедрение функций или накладывать ограничения на новые команды, поэтому всегда уточняйте возможности у своего поставщика.
Путь разработки PostgreSQLQL 19, как отмечается в видео, был «тернистым»: функции анонсировались, отменялись и сокращались ради стабильности. Такой осторожный подход характерен для PostgreSQLQL Global Development Group. Поэтому, прежде чем полагаться на REPACK CONCURRENTLY в производственных нагрузках, уточните его точное поведение и все эксплуатационные оговорки в официальной документации PostgreSQLQL 19.
В конечном счёте REPACK CONCURRENTLY — мощный новый инструмент в арсенале администратора БД, но не универсальное решение. Его кратковременная, но критически важная исключительная блокировка означает, что стратегическое планирование по-прежнему необходимо. Запуск в периоды низкой активности или при отсутствии долгих запросов позволит получить максимальную пользу и избежать 18-секундной очереди, наблюдавшейся в тестах Better Stack.
Часто задаваемые вопросы
Что делает REPACK в PostgreSQL 19?
REPACK перестраивает таблицу в более компактную физическую структуру, освобождая неиспользуемое место на диске и позволяя при этом продолжать обычную работу базы данных.
Чем REPACK отличается от VACUUM FULL?
VACUUM FULL перезаписывает таблицу, удерживая на время операции блокирующую блокировку. REPACK CONCURRENTLY выполняет основную часть работы, пока таблица остаётся доступной, а затем требует кратковременной исключительной блокировки для переключения файлов.
Может ли REPACK CONCURRENTLY всё же повлиять на трафик приложения?
Да. Финальная подмена должна дождаться завершения запросов, использующих таблицу, а новые запросы могут выстраиваться в очередь за блокировкой.
Делает ли PostgreSQL 19 pg_repack ненужным?
В ряде случаев он может уменьшить потребность в pg_repack, однако командам следует сопоставить доступность и операционную применимость встроенной функции с уже используемыми инструментами.

