#Что означает ошибка
Обычный VACUUM удаляет устаревшие версии строк и в основном делает страницы таблицы доступными для повторного использования внутри PostgreSQL. Он обычно не уменьшает размер файла таблицы на диске — поэтому свободное место в файловой системе может не увеличиться после массового DELETE. VACUUM FULL переписывает таблицу, требует дополнительного свободного места и блокирует её; это не первый шаг.
#Как различить причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Освобождено место внутри таблицы, а не на дискеСтандартный VACUUM очищает мёртвые версии и оставляет большую часть страниц для следующих INSERT. | Размер файла почти не изменился, а n_dead_tup уменьшается и новые записи помещаются без роста файла. | Считать внутреннее повторное использование нормальным; отдельно оценить необходимость уменьшения файла. |
| Есть длительная транзакция или удерживающий горизонт репликацииСтарые снимки, replication slots или длительные запросы могут мешать очищать версии строк. | pg_stat_activity показывает старую транзакцию; статистика dead tuples не уменьшается как ожидалось. | Сначала выяснить владельца блокирующей транзакции и репликации, а не прерывать их. |
| Ожидается уменьшение таблицы/индексовПосле массового удаления в файле и индексах остаётся свободное пространство. | pg_total_relation_size больше pg_relation_size; значение остаётся высоким. | Вариант перепаковки возможен только в окно обслуживания после оценки диска и блокировок. |
#Пошаговая диагностика и устранение
- Убедитесь, что удаление действительно завершилосьОткройте psql или pgAdmin → база → Tools → Query Tool. Выполните
SELECT current_database(), current_user;и безопасный SELECT COUNT(*) по той таблице, где уже было удаление, если таблица не слишком велика; на огромных таблицах вместо COUNT используйте оценку pg_class. Если запрос на удаление ещё не COMMIT, не пытайтесь VACUUM для этой же операции: сначала разберитесь с транзакцией. - Разделите размер таблицы и свободное место файловой системыНа Linux откройте терминал и выполните
df -h, чтобы увидеть свободное место на файловой системе, содержащей кластер. На Windows откройте Проводник → «Этот компьютер» → свойства нужного диска. Сам каталог данных узнают у администратора либо через SHOW data_directory, если разрешено; не открывайте системные файлы базы вручную. - Посмотрите размер таблицы до дальнейших действийВ psql запустите
SELECT pg_size_pretty(pg_relation_size('public.orders'::regclass)), pg_size_pretty(pg_total_relation_size('public.orders'::regclass));, заменив public.orders реальным именем. Первое измеряет основной файл таблицы, второе — вместе с индексами и TOAST. Если таблица не существует в данной схеме, проверьте название, а не создавайте её повторно. - Проверьте мёртвые строки и время последнего VACUUMВыполните запрос к pg_stat_user_tables по имени таблицы; найдите n_dead_tup, last_vacuum, last_autovacuum, n_live_tup. Это оценочные показатели, а не точная инвентаризация каждой строки. Сравните их с историей удаления и предыдущим замером: когда mёртвых строк стало меньше, обычный VACUUM, вероятно, сделал свою работу.
- Разрешите обычному VACUUM закончить корректноЕсли массовое удаление уже подтверждено и нет длительной транзакции, проверьте, не выполняется ли autovacuum, через pg_stat_progress_vacuum в поддерживаемой версии. На своей тестовой базе разрешено выполнить
VACUUM (VERBOSE, ANALYZE) public.orders;вне BEGIN, заменив имя таблицы. На рабочей — согласуйте нагрузку с администратором. После выполнения переснимите статистику: отсутствие уменьшения файла не означает неуспех. - Проверьте, не мешают ли старые снимкиАдминистратор должен изучить сессии с долгими транзакциями и репликацию, прежде чем решать о сжатии. В pg_stat_activity смотрят xact_start и backend_xmin, у репликационных слотов — xmin/catalog_xmin. Не завершайте неизвестную транзакцию и не удаляйте replication slot: это может повредить репликацию или резервное восстановление.
- Оцените альтернативу уменьшению файлаЕсли место нужно вернуть операционной системе, сначала выясните, будет ли таблица вновь расти: если да, сохранение свободных страниц может быть выгоднее. VACUUM FULL требует эксклюзивной блокировки таблицы, места на переписывание и времени обслуживания; иногда подходит плановая миграция/перепаковка. Не включайте его в автоматический скрипт устранения нехватки места.
- Сравните результат и подготовьте план откатаПовторите pg_relation_size, pg_total_relation_size и df -h, записав значения до/после; проверьте реальные INSERT/SELECT на тестовой копии. Для обычного VACUUM откат не нужен и он не должен уничтожать живые строки; результаты файловой перепаковки через ROLLBACK после завершения вернуть нельзя. Если свободного места критически мало, остановите потенциально разрушающие операции и попросите администратора расширить диск/провести обслуживание.
- Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
#Воспроизведение и проверка только в отдельной тестовой базе
SELECT pg_size_pretty(pg_relation_size('pg_class'::regclass)) AS file_size, pg_size_pretty(pg_total_relation_size('pg_class'::regclass)) AS total_size;#Как убедиться в исправлении и что делать дальше
При успехе VACUUM освободил версии строк для повторного использования, n_dead_tup уменьшился с учётом неточности статистики, а приложение корректно читает и записывает данные. Место на диске может остаться прежним — это нормально. Если реальная цель уменьшить файл, передайте владельцу БД измерения, доступный запас диска, допустимое окно блокировки и план резервного копирования.