4 июня 2026 года вышла PostgreSQL 19 Beta 1. В ней появилась штатная команда REPACK: она переписывает раздутую таблицу и возвращает свободное место операционной системе. Режим CONCURRENTLY оставляет таблицу доступной почти до конца операции.
Почти — здесь главное слово. Перед заменой файлов PostgreSQL всё равно запрашивает ACCESS EXCLUSIVE. Документация PostgreSQL 19 предупреждает и о другой проблеме: REPACK CONCURRENTLY пока небезопасен для старых снимков MVCC.
Администратору базы 1С нужно освободить диск после множества UPDATE и DELETE, но не останавливать пользователей на долгий VACUUM FULL. Нативный REPACK подходит к этой задаче ближе прежних штатных средств. Переходить ради него на PostgreSQL 19 Beta нельзя.
Почему обычный VACUUM не уменьшает файл таблицы
При UPDATE PostgreSQL не меняет строку на прежнем месте. Он записывает новую версию, а старую помечает мёртвой. После DELETE строка тоже остаётся в файле, хотя транзакции её больше не видят.
Обычный VACUUM находит такие версии и отдаёт занятое ими место под будущие записи. PostgreSQL повторно использует свободные участки, но файл на диске обычно не уменьшается. Эту механику описывают документация PostgreSQL и разбор Selectel о раздувании таблиц.
Значит ли это, что VACUUM бесполезен? Нет. Он обслуживает MVCC и не даёт таблице бесконтрольно расти. Но уже накопленные сотни лишних гигабайт файловой системе не вернёт.
Чтобы уменьшить файл, сервер должен перенести живые строки в новый. Так работают VACUUM FULL, расширение pg_repack и команда REPACK.
| Способ | Возвращает место ОС | Доступ к таблице во время работы | Как переносит текущие изменения |
|---|---|---|---|
VACUUM | Нет, освобождает место внутри файла | Чтение и запись продолжаются | Не переписывает таблицу |
VACUUM FULL | Да | Держит ACCESS EXCLUSIVE до завершения | Не принимает изменения: таблица заблокирована |
pg_repack | Да | Основное копирование идёт при доступной таблице | Записывает изменения через триггер во вспомогательную таблицу |
REPACK CONCURRENTLY | Да | Основное копирование идёт при доступной таблице | Собирает изменения через логическое декодирование |
Штатный REPACK занимает место между фоновым VACUUM и полной остановкой на VACUUM FULL. До функциональности pg_repack ему пока далеко.
Как REPACK CONCURRENTLY переписывает живую таблицу
REPACK создаёт новый файл таблицы и копирует в него видимые строки. Потом PostgreSQL заново строит индексы. Старый файл хранится до конца операции.
С ключом CONCURRENTLY сервер параллельно получает изменения через логическое декодирование. Всё, что записали после начала копирования, PostgreSQL переносит в новую версию таблицы перед переключением файлов.
Каждая такая операция забирает один слот из пула max_repack_replication_slots. Нет свободного слота — команда не стартует.
После копирования сервер должен атомарно подменить файлы таблицы и индексов. В этот момент он запрашивает ACCESS EXCLUSIVE. Блокировка не висит часами вместе с перепаковкой, но чтение и запись на время переключения остановятся.
Предсказать длительность этой остановки нельзя. lock_timeout ограничивает ожидание блокировки, а не срок её удержания. Если PostgreSQL уже получил ACCESS EXCLUSIVE, параметр не прервёт работу через заданное время.
Для 1С это заметный операционный риск. Переключению могут помешать долгий запрос, фоновое задание или забытая транзакция. Когда блокировка всё же будет получена, новые обращения к таблице встанут до завершения замены файлов.
Поэтому проверяйте команду на копии базы под рабочей нагрузкой. Пустая тестовая база подтвердит синтаксис, но ничего не скажет о блокировках при активных сеансах 1С.
Старые снимки MVCC могут увидеть пустую таблицу
Документация PostgreSQL 19 прямо предупреждает: REPACK CONCURRENTLY небезопасен для MVCC. При определённых условиях транзакция со старым снимком увидит перепакованную таблицу пустой.
Проблема касается уровней изоляции REPEATABLE READ и SERIALIZABLE. Такие транзакции держат снимок дольше, чем обычные операции с READ COMMITTED.
До обслуживания проверьте активные транзакции и их возраст. Малое число пользователей ничего не гарантирует. Старый снимок может удерживать фоновый процесс, который никак не проявляет себя в интерфейсе 1С.
Не завершайте найденные транзакции вслепую. Сначала установите, какой процесс их открыл и можно ли повторить его работу. Иначе вместо освобождённого диска вы получите оборванный обмен или незавершённое регламентное задание.
Какие таблицы нельзя перепаковать в concurrent-режиме
REPACK CONCURRENTLY принимает не любую таблицу. Ограничения перечислены в документации PostgreSQL 19, а сама команда проверяет их перед запуском.
| Признак | Почему команда не запустится | Что проверить или изменить |
|---|---|---|
Таблица UNLOGGED | Логическое декодирование не соберёт нужный поток изменений | Использовать обычный REPACK с окном простоя либо прежний способ обслуживания |
| Таблица секционирована | CONCURRENTLY не поддерживает секционированные таблицы | Обслуживать секции допустимым способом и проверить синтаксис на своей схеме |
Нет первичного ключа и индексной REPLICA IDENTITY | Сервер не сможет однозначно сопоставить изменённые строки | Проверить ключи и REPLICA IDENTITY; не добавлять индекс без анализа схемы 1С |
| Системный каталог или TOAST-таблица | Эти объекты исключены из concurrent-режима | Не запускать команду напрямую для такого объекта |
| Команда запущена внутри транзакционного блока | REPACK CONCURRENTLY запрещён внутри BEGIN … COMMIT | Выполнить отдельную команду с автокоммитом |
Нет свободного max_repack_replication_slots | Операции нужен дополнительный слот | До обслуживания проверить параметр и занятые слоты |
Запущен режим по всей базе без table_name | Массовый режим несовместим с CONCURRENTLY | Указать одну целевую таблицу |
Выберите одну таблицу и укажите её имя явно. Без table_name команда проходит по доступным таблицам и материализованным представлениям всей базы. Совместить такой запуск с CONCURRENTLY нельзя.
Отдельная опасность — параллельный DDL. Если структура таблицы изменится во время перепаковки, команда может упасть с ошибкой. На время испытания запретите обновление конфигурации и другие работы со схемой.
Не добавляйте первичный ключ в таблицу 1С только ради REPACK. Структурой этих объектов управляет платформа, поэтому любое вмешательство требует отдельной проверки. Нет подходящего ключа — оставьте прежний способ обслуживания.
Сколько места потребуется для новой копии
Документация PostgreSQL 19 задаёт две границы свободного места. Конкретное значение зависит от плана чтения и упорядочивания таблицы.
Пусть T — размер таблицы, а I — суммарный размер её индексов.
При индексном чтении или последовательном чтении без сортировки потребуется минимум:
T + I
Если планировщик выберет последовательное чтение с сортировкой, пиковая потребность вырастет до:
2T + I
Посчитаем для таблицы на 200 ГБ с индексами на 80 ГБ. Это расчёт по формулам документации, не замер скорости или нагрузки.
Нижняя граница:
200 + 80 = 280 ГБ
Пиковое значение при сортировке:
2 × 200 + 80 = 480 ГБ
| Исходные данные | Способ чтения | Расчёт | Требуемое место |
|---|---|---|---|
| Таблица 200 ГБ, индексы 80 ГБ | Индексное чтение | 200 + 80 | Не менее 280 ГБ |
| Таблица 200 ГБ, индексы 80 ГБ | Последовательное чтение без сортировки | 200 + 80 | Не менее 280 ГБ |
| Таблица 200 ГБ, индексы 80 ГБ | Последовательное чтение с сортировкой | 2 × 200 + 80 | До 480 ГБ |
Для своей таблицы подставьте фактические T и I. Формулы не включают рост WAL, временные файлы соседних запросов и новые записи пользователей.
Универсального запаса на эту активность документация не задаёт. Поэтому нельзя механически накинуть 10 или 20 процентов и объявить полученный объём безопасным.
Если на томе нет 480 ГБ, документация PostgreSQL предлагает отключить сортировку через enable_sort = off. Планировщик тогда не выберет последовательное чтение с последующей сортировкой. Расчёт вернётся к T + I.
Сначала испытайте этот вариант на отдельной копии. Запрет сортировки изменит план, но нагрузка на диски никуда не исчезнет. Перед опытом подготовьте восстанавливаемый бэкап PostgreSQL для базы 1С и разверните его отдельно от рабочей базы.
Чем штатный REPACK уступает pg_repack
Встроенная команда избавляет от стороннего расширения. Но одной этой разницы мало, чтобы назвать её прямой заменой pg_repack.
pg_repack отслеживает изменения через триггер, что указано в документации расширения. Штатный REPACK опирается на логическое декодирование и отдельный пул временных слотов. Отсюда разные требования к подготовке сервера и диагностике операции.
Функциональность тоже различается.
| Задача | pg_repack | REPACK в PostgreSQL 19 |
|---|---|---|
| Параллельно строить индексы | Поддерживает через --jobs | Строит индексы последовательно |
| Перенести таблицу и индексы в другой tablespace | Есть --tablespace и --moveidx | Не поддерживает перенос в другой tablespace |
| Задать произвольный порядок строк | Есть --order-by | Сортирует только по существующему индексу через USING INDEX |
| Настроить ожидание блокировки | Есть --wait-timeout и --no-kill-backend | Сопоставимой встроенной политики нет |
| Обработать набор таблиц в online-режиме | Есть режимы отбора объектов | Массовый REPACK несовместим с CONCURRENTLY |
| Собирать изменения во время копирования | Через триггер и вспомогательную таблицу | Через логическое декодирование |
Нужна параллельная сборка индексов, перенос tablespace или управляемое ожидание блокировки — оставляйте pg_repack. Штатная команда рассчитана на более узкую задачу: одна поддерживаемая таблица, достаточно места на томе и допустимая финальная блокировка.
Есть ограничение жёстче функциональных различий. Изученные материалы относятся к PostgreSQL 19 Beta 1 и beta2. Официальная страница документации помечает эту версию как неподдерживаемую.
Не переводите боевую базу 1С на PostgreSQL 19 ради одной команды. Сначала дождитесь поддерживаемого выпуска, затем проверьте его совместимость со своей версией платформы 1С. Если вы ещё выбираете СУБД, отдельно сверьте различия SQL Server и PostgreSQL в эксплуатации 1С.
Как проверить REPACK после стабильного релиза
Первым делом возьмите резервную копию, которую уже удавалось развернуть. Успешный запуск pg_dump или pg_basebackup подтверждает создание файла, но не восстановление базы. Порядок для разных вариантов 1С есть в руководстве по резервному копированию 1С.
После этого выберите одну раздутую таблицу. Не начинайте со всей базы. На одной таблице проще оценить свободное место, нагрузку и последствия финальной блокировки.
Перед запуском проверьте:
- Таблица не относится к
UNLOGGED, секционированным, системным или TOAST-объектам. - У неё есть первичный ключ либо индексная
REPLICA IDENTITY. - В
max_repack_replication_slotsостался свободный слот. - На диске помещаются
T + I, а при возможной сортировке —2T + I. - На время операции исключены DDL и обновление конфигурации.
- Нет долгих транзакций с
REPEATABLE READилиSERIALIZABLE. - Приложение выдержит финальную блокировку
ACCESS EXCLUSIVE.
Команде нужна привилегия MAINTAIN на целевую таблицу. Права суперпользователя для самой операции документация PostgreSQL 19 не требует.
Ход перепаковки виден в pg_stat_progress_repack. Представление показывает работу каждого backend, который выполняет REPACK. Операцию с неприемлемой нагрузкой можно отменить, но при новом запуске всё начнётся сначала.
После перепаковки выполните ANALYZE для обработанной таблицы. PostgreSQL обновит статистику, чтобы планировщик заново оценил планы запросов.
Итоговая развилка проста. Берите REPACK CONCURRENTLY, когда он вошёл в поддерживаемый выпуск, таблица проходит проверки, копия помещается на диске, а 1С выдерживает финальный ACCESS EXCLUSIVE. Не выполняется хотя бы одно условие — сохраняйте прежний способ обслуживания.