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_repackREPACK в 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С.

После этого выберите одну раздутую таблицу. Не начинайте со всей базы. На одной таблице проще оценить свободное место, нагрузку и последствия финальной блокировки.

Перед запуском проверьте:

  1. Таблица не относится к UNLOGGED, секционированным, системным или TOAST-объектам.
  2. У неё есть первичный ключ либо индексная REPLICA IDENTITY.
  3. В max_repack_replication_slots остался свободный слот.
  4. На диске помещаются T + I, а при возможной сортировке — 2T + I.
  5. На время операции исключены DDL и обновление конфигурации.
  6. Нет долгих транзакций с REPEATABLE READ или SERIALIZABLE.
  7. Приложение выдержит финальную блокировку ACCESS EXCLUSIVE.

Команде нужна привилегия MAINTAIN на целевую таблицу. Права суперпользователя для самой операции документация PostgreSQL 19 не требует.

Ход перепаковки виден в pg_stat_progress_repack. Представление показывает работу каждого backend, который выполняет REPACK. Операцию с неприемлемой нагрузкой можно отменить, но при новом запуске всё начнётся сначала.

После перепаковки выполните ANALYZE для обработанной таблицы. PostgreSQL обновит статистику, чтобы планировщик заново оценил планы запросов.

Итоговая развилка проста. Берите REPACK CONCURRENTLY, когда он вошёл в поддерживаемый выпуск, таблица проходит проверки, копия помещается на диске, а 1С выдерживает финальный ACCESS EXCLUSIVE. Не выполняется хотя бы одно условие — сохраняйте прежний способ обслуживания.

pg_repack postgresql обслуживание базы раздувание таблиц сервер 1с