При администрировании связки 1С8.3, PostgreSQL 13 и Debian 11, одной из наиболее актуальных и часто вызывающих вопросы задач является правильная организация резервного копирования и, в частности, управление архивом журналов упреждающей записи (WAL, Write-Ahead Log). WAL-файлы критически важны для обеспечения целостности данных, восстановления на момент времени (PITR) и работы репликации. Однако, их бесконтрольное накопление может быстро исчерпать свободное дисковое пространство. В этой статье мы подробно разберем, как эффективно настроить автоматическую очистку архива WAL-файлов на основном сервере PostgreSQL, устраним распространенные заблуждения и предоставим практические рекомендации.
Мы выясним, почему стандартный параметр archive_cleanup_command не всегда является решением для основного сервера и какие механизмы следует использовать для безопасного и автоматизированного удаления устаревших WAL-архивов. Проанализируем роль утилиты pg_archivecleanup и значение файлов .backup, создаваемых после выполнения pg_basebackup.
Начнем с параметра archive_cleanup_command в файле postgresql.conf, который часто вызывает путаницу, как это произошло в исходном обсуждении. Важно понимать, что этот параметр предназначен в первую очередь для
серверов-реплик (standby servers). Его основная задача — автоматически удалять устаревшие WAL-файлы из архива, которые больше не нужны именно этому конкретному серверу-реплике для восстановления или продолжения работы.
Рассмотрим подробнее его функционирование:
archive_cleanup_command выполняется на сервере-реплике при каждом restartpoint (точке перезапуска). Restartpoint — это аналог контрольной точки (checkpoint) в обычной работе, но для реплики, указывающий на согласованное состояние данных.
%r в команде заменяется именем WAL-файла, который соответствует последней действительной точке перезапуска реплики.pg_archivecleanup, указанная в archive_cleanup_command, удалит все WAL-файлы из общего каталога архива, которые логически предшествуют файлу, обозначенному %r. Это гарантирует, что реплика всегда имеет доступ к необходимым для восстановления WAL-файлам, но при этом не хранит чрезмерно старые, уже обработанные сегменты.Почему его не рекомендуется использовать для долгосрочного архива WAL на основном сервере?
Если мы используем archive_cleanup_command на основном сервере, или в ситуации, когда несколько реплик восстанавливаются из одного и того же архива, это может привести к проблемам. Основной сервер не имеет концепции "restartpoint" для архива, и команда будет выполняться не так, как ожидается. Более того, удаление файлов на основе логики одной реплики может нарушить возможность восстановления на момент времени (PITR) для других реплик или для самого основного сервера в случае необходимости восстановления из базовой резервной копии. Нам нужен более контролируемый и глобальный подход к очистке архива WAL.
На основном сервере PostgreSQL не удаляет автоматически архивированные WAL-файлы. Они будут накапливаться в указанном каталоге архива, если не настроить явный механизм очистки. Для управления этим процессом на основном сервере используются следующие подходы:
Утилита pg_archivecleanup — это мощный инструмент, который может быть использован как самостоятельная команда для удаления старых WAL-файлов из любого места файловой системы, где вы храните ваш архив. Мы должны явно указать ей, какие файлы следует сохранить, передавая в качестве аргумента имя самого старого WAL-файла (или его префикса), который все еще необходим для восстановления.
Ключевая роль файлов .backup:
После успешного выполнения базовой резервной копии с помощью pg_basebackup, в каталоге архива WAL создается специальный файл истории резервной копии с расширением .backup. Этот файл содержит важную информацию о точке, с которой начинается базовая резервная копия, включая имя первого WAL-файла, который был активен на момент создания копии. pg_archivecleanup может использовать имя этого файла (или его префикса) для определения самого старого WAL-файла, который требуется для данной базовой резервной копии. Это критически важный механизм для безопасной очистки архивов, связанных с вашими базовыми резервными копиями.
Например, если у нас есть базовая резервная копия, созданная pg_basebackup, и она сгенерировала файл 000000010000003700000010.00000020.backup в нашем каталоге архива /var/lib/pgpro/wal, то для удаления всех WAL-файлов, предшествующих этому, мы можем использовать следующую команду:
pg_archivecleanup -d /var/lib/pgpro/wal 000000010000003700000010.00000020.backup
Опция -d (debug) очень полезна для отладки, так как она выводит подробную информацию о процессе удаления, позволяя нам понять, какие файлы будут удалены, прежде чем реально это произойдет.
Наиболее распространенный и рекомендуемый метод автоматической очистки архивов WAL на основном сервере — это написание пользовательского скрипта, который запускается по расписанию, например, с помощью системного планировщика cron. Этот скрипт будет выполнять следующие шаги:
Определение политики хранения: Мы должны четко определить, как долго хотим хранить WAL-файлы. Это напрямую зависит от наших требований к восстановлению на момент времени (PITR) и частоты создания базовых резервных копий.
Идентификация базовых резервных копий: Скрипт должен найти все файлы .backup в каталоге архива WAL. Каждый такой файл соответствует одной базовой резервной копии.
Определение самого старого необходимого WAL: На основе нашей политики хранения и файлов .backup, скрипт должен определить самый старый WAL-файл, который нам еще нужен. Например, если мы хотим хранить WAL-файлы, необходимые для восстановления за последние 7 дней, и у нас есть базовая резервная копия, сделанная 3 дня назад, скрипт должен убедиться, что мы не удаляем WAL-файлы, необходимые для этой базовой копии и последующего PITR.
Вызов pg_archivecleanup: После определения "точки отсечения", скрипт вызовет pg_archivecleanup, передавая ему имя соответствующего WAL-файла (или файла .backup) в качестве аргумента.
Пример логики скрипта (псевдокод):
#!/bin/bash
WAL_ARCHIVE_DIR="/var/lib/pgpro/wal"
LOG_FILE="/var/log/pg_wal_cleanup.log"
# Найти все файлы .backup и отсортировать их по времени создания/имени
# Ищем самый старый .backup файл, который еще должен быть сохранен
# (например, все .backup файлы за последние N дней или N базовых копий)
# Для примера возьмем самый старый .backup файл из архива:
# Если у нас есть политика хранения "N последних базовых копий",
# то нам нужно найти N-ную по счету самую старую копию.
# Если же у нас политика "хранить WAL за последние N дней",
# то нам нужно найти самую старую базовую копию, которая попадает в этот интервал.
# В данном простом примере мы найдем самый старый .backup файл вообще
# Это может быть слишком агрессивным, если у вас одна старая базовая копия,
# и вы хотите удалить WALs, которые не относятся к последней актуальной
# pg_basebackup.
#
# Более надежный подход:
# 1. Запустить pg_basebackup (желательно использовать инструменты типа pgBackRest)
# 2. Получить имя последнего .backup файла.
# 3. Использовать его как точку отсечения для pg_archivecleanup.
# Простой пример, который удалит все WAL-файлы, предшествующие самому старому
# .backup файлу в каталоге. ОСТОРОЖНО: это может быть слишком агрессивно!
# Необходимо тщательно продумать логику на основе вашей политики.
OLDEST_BACKUP_FILE=$(find "$WAL_ARCHIVE_DIR" -name "*.backup" | sort | head -n 1)
if [ -n "$OLDEST_BACKUP_FILE" ]; then
echo "--- $(date) ---" >> "$LOG_FILE"
echo "Cleaning WAL archive based on oldest backup file: $(basename "$OLDEST_BACKUP_FILE")" >> "$LOG_FILE"
/usr/lib/postgresql/13/bin/pg_archivecleanup -d "$WAL_ARCHIVE_DIR" "$(basename "$OLDEST_BACKUP_FILE")" >> "$LOG_FILE" 2>&1
if [ $? -eq 0 ]; then
echo "Cleanup successful." >> "$LOG_FILE"
else
echo "Cleanup failed with exit code $?." >> "$LOG_FILE"
fi
else
echo "--- $(date) ---" >> "$LOG_FILE"
echo "No .backup files found in $WAL_ARCHIVE_DIR. Skipping cleanup." >> "$LOG_FILE"
fi
Мы настоятельно рекомендуем тщательно продумать логику этого скрипта на основе вашей конкретной политики хранения. Для продакшн-систем обычно используют более сложные скрипты или специализированные решения, которые учитывают не только самый старый файл .backup, но и последние успешные pg_basebackup, а также слоты репликации.
Критически важно определить четкую и продуманную политику хранения WAL-файлов. Эта политика должна учитывать следующие факторы:
Требования к восстановлению на момент времени (PITR): Как далеко в прошлое мы должны быть способны восстановить базу данных? Это напрямую влияет на количество WAL-файлов, которые необходимо хранить.
Частота создания базовых резервных копий: Чем чаще мы создаем полные базовые резервные копии (с помощью pg_basebackup или других инструментов), тем меньше WAL-файлов требуется хранить между этими копиями для PITR.
Доступное дисковое пространство: Естественно, объем доступного хранилища является ограничивающим фактором. Нам нужно найти баланс между требованиями к восстановлению и объемом диска.
Недостаточное хранение WAL-файлов может нарушить возможность PITR и репликации, делая базу данных уязвимой. Чрезмерное же хранение WAL-файлов приводит к быстрому заполнению дискового пространства, что тоже может привести к проблемам.
В сообщениях форума мы столкнулись с проблемой, когда файл cleanup.log не создавался, и очистка не работала. Одна из причин может быть связана с синтаксической ошибкой в параметре archive_cleanup_command. Изначально была строка: archive_cleanup_command = 'pg_archivecleanup -d /var/lib/pgpro/wal% r 2 >> cleanup.log'. Обратите внимание на пробел между % и r.
Правильный синтаксис команды pg_archivecleanup в параметре archive_cleanup_command должен быть без пробела между путем к каталогу архива и %r, или с пробелом перед %r, если %r является отдельным аргументом: archive_cleanup_command = 'pg_archivecleanup /var/lib/pgpro/wal %r 2>>cleanup.log'. Хотя в данном случае, как мы уже выяснили, этот параметр больше подходит для реплик.
Если cleanup.log не создается, это может указывать на следующие проблемы:
Команда не выполняется: Убедитесь, что изменения в postgresql.conf были применены путем перезапуска сервера PostgreSQL. Команда archive_cleanup_command срабатывает только в определенных условиях (restartpoint для реплики).
Права доступа: Убедитесь, что пользователь PostgreSQL имеет достаточные права доступа для записи в каталог, где должен быть создан cleanup.log, и для чтения/записи/удаления WAL-файлов в /var/lib/pgpro/wal. Проверьте права на сам каталог /var/lib/pgpro/wal и на родительские каталоги.
Неправильный путь: Убедитесь, что путь к каталогу /var/lib/pgpro/wal (или /var/lib/pgpro/1c-13/wal, как было упомянуто) является правильным и существует.
Ошибки в журналах PostgreSQL: Всегда проверяйте основные журналы ошибок PostgreSQL (обычно находятся в каталоге данных или указаны в log_directory в postgresql.conf) на наличие предупреждений или ошибок, связанных с archive_cleanup_command или процессом архивации в целом.
Никогда не удаляйте WAL-файлы вручную из каталога pg_wal (или pg_xlog в старых версиях). Этот каталог очищается автоматически самим PostgreSQL, если нет проблем с архивацией, репликационными слотами или активными транзакциями. Ручное вмешательство может привести к повреждению базы данных и потере данных.
Регулярно тестируйте процесс восстановления. Это критически важно, чтобы убедиться в работоспособности вашего архива WAL и механизма очистки. Если вы не можете восстановиться из архива, то вся ваша стратегия резервного копирования бесполезна.
Для крупных и высоконагруженных систем мы рекомендуем использовать специализированные инструменты для резервного копирования и восстановления PostgreSQL, такие как pgBackRest или Barman. Эти инструменты предлагают гораздо более надежные и автоматизированные решения для управления WAL-файлами, включая сжатие, очистку, политики хранения, а также интеграцию с pg_basebackup и механизмом PITR. Они значительно упрощают и делают более безопасным процесс администрирования резервных копий.
Для корректной работы архивации WAL-файлов, ваш файл postgresql.conf должен содержать следующие параметры (пример из исходного сообщения):
archive_mode = on # enables archiving; off, on, or always
archive_command = 'cp %p /var/lib/pgpro/wal/%f' # command to use to archive a logfile segment
Здесь:
archive_mode = on включает режим архивации. Это означает, что после заполнения каждого WAL-сегмента он будет передан команде archive_command.
archive_command определяет команду оболочки, которая будет выполнена для каждого завершенного WAL-сегмента. В этой команде:
%p заменяется на полный путь к файлу WAL, который нужно архивировать.%f заменяется на имя файла WAL, который нужно архивировать.Пример 'cp %p /var/lib/pgpro/wal/%f' копирует завершенный WAL-сегмент в каталог /var/lib/pgpro/wal. Нам необходимо убедиться, что каталог существует и доступен для записи пользователю PostgreSQL.
После изменения postgresql.conf всегда требуется перезапуск сервера PostgreSQL для применения этих изменений. Мы можем проверить статус архивации, просмотрев журналы PostgreSQL, где будут регистрироваться сообщения о выполнении archive_command.
В заключение, эффективное управление WAL-архивами на основном сервере PostgreSQL для 1С8.3 на Debian 11 требует понимания того, что archive_cleanup_command не является универсальным решением для очистки. Вместо этого, мы должны полагаться на скрипты, запускаемые по расписанию, которые используют утилиту pg_archivecleanup в связке с информацией из файлов .backup, создаваемых pg_basebackup, и вашей четко определенной политикой хранения данных. Такой подход обеспечивает баланс между безопасностью данных, возможностью восстановления и эффективным использованием дискового пространства.