PostgreSQL: растёт размер WAL — причины и решение
Диск заполняется, и виновник — каталог pg_wal: PostgreSQL растёт размер WAL. WAL (write-ahead log) — это журнал предзаписи, механизм надёжности PostgreSQL, и в норме он не должен разрастаться бесконтрольно. Если pg_wal съедает десятки гигабайт, почти всегда причина конкретна: застрявший слот репликации, сломанное архивирование или сбитые чекпоинты. Разберём, как найти причину и безопасно вернуть место, не сломав базу.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Первое действие: оцените размер и не удаляйте WAL вручную
Сначала подтвердите, что проблема именно в WAL, и запомните главное правило: файлы в pg_wal нельзя удалять командой rm — это повредит базу. Посмотрите размер каталога и настройки:
du -sh /var/lib/postgresql/*/main/pg_wal
df -h
Если pg_wal занимает непропорционально много (гигабайты и десятки гигабайт при небольшой базе) — что-то мешает PostgreSQL переиспользовать эти файлы. WAL устроен так: после чекпоинта и, при необходимости, архивирования и вычитки репликами старые сегменты становятся ненужными и переиспользуются. Если этот цикл где-то застрял, сегменты копятся. Ваша задача — найти, что именно держит WAL, и устранить это средствами PostgreSQL. Удаление файлов вручную кажется быстрым решением, но приводит к потере данных и неработоспособной базе — так делать нельзя ни при каких обстоятельствах.
Причина 1: застрявший слот репликации
Самая частая причина неконтролируемого роста WAL — неактивный слот репликации. Слот (replication slot) гарантирует, что PostgreSQL сохранит WAL, пока его не вычитает реплика. Если реплика отключилась или слот был создан и заброшен, база честно копит WAL «на всякий случай» — и заполняет диск. Проверьте слоты:
SELECT slot_name, active, restart_lsn FROM pg_replication_slots;
Если есть слот с active = false, который никто не использует, — вот виновник. Пока такой слот существует, WAL не удаляется. Удалите ненужный неактивный слот:
SELECT pg_drop_replication_slot('имя_слота');
После этого PostgreSQL сможет переиспользовать накопленные сегменты, и pg_wal вскоре уменьшится. Будьте внимательны: удаляйте только тот слот, который точно не нужен, — если это слот работающей, но временно отставшей реплики, его удаление разорвёт репликацию. Но заброшенный неактивный слот — почти всегда безопасная и правильная цель.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS под базуПричина 2: сломанное архивирование WAL
Если у вас включено архивирование (archive_mode = on) и задан archive_command, PostgreSQL не удалит сегмент WAL, пока команда архивирования не отработает успешно. Если archive_command сломалась — например, недоступно место назначения архива или ошибка в скрипте, — сегменты копятся бесконечно, ожидая успешной архивации. Проверьте статус архивирования:
SELECT archived_count, failed_count, last_failed_time FROM pg_stat_archiver;
Растущий failed_count и свежий last_failed_time — прямой признак сломанного архивирования. Смотрите лог PostgreSQL: там будет причина сбоя команды. Почините archive_command (доступ к хранилищу, права, корректность скрипта) — как только архивирование пойдёт успешно, накопленные сегменты заархивируются и освободятся. Если архивирование вам вообще не нужно, его отключают осознанно. Но пока archive_mode = on, а команда падает, WAL будет расти, поэтому чинить нужно именно архивирование, а не бороться с симптомом.
Причина 3: слишком большие настройки WAL
Иногда WAL занимает много просто потому, что так настроено. Параметры max_wal_size, wal_keep_size (или устаревший wal_keep_segments) и частота чекпоинтов определяют, сколько WAL база держит между чекпоинтами. Если они выставлены с большим запасом, pg_wal будет стабильно объёмным — это нормально и не является проблемой, если места хватает. Проверьте значения:
SHOW max_wal_size;
SHOW wal_keep_size;
Большой wal_keep_size заставляет держать много сегментов для возможных реплик, даже когда их нет. Если вы не используете физическую репликацию через wal_keep_size, уменьшите его. max_wal_size влияет на то, как далеко WAL уходит между чекпоинтами: слишком маленькое значение вызывает частые чекпоинты и нагрузку на диск, слишком большое — раздувает pg_wal. Здесь нужен баланс под ваш объём записи, а не борьба за минимум. В отличие от застрявшего слота или сломанного архива, это не «поломка», а вопрос настройки под ресурсы сервера.
Причина 4: всплеск записи или долгая транзакция
Резкий рост WAL бывает при массовой записи — большой загрузке данных, миграции, объёмном обновлении — это временно и нормально: после чекпоинта место вернётся. Но долгая незакрытая транзакция способна удерживать WAL надолго, мешая его очистке. Найдите самые старые активные транзакции:
SELECT pid, state, xact_start, query FROM pg_stat_activity
ORDER BY xact_start LIMIT 5;
Транзакция, висящая часами в состоянии idle in transaction, — частая проблема: приложение открыло транзакцию и не закрыло, а PostgreSQL вынужден удерживать ресурсы, включая WAL. Завершите такую зависшую транзакцию и почините приложение, чтобы оно не оставляло транзакции открытыми. Настройка idle_in_transaction_session_timeout автоматически обрывает такие сессии по таймауту — её полезно включить. Массовый всплеск записи лечения не требует, а вот забытые долгие транзакции стоит устранять и предотвращать.
Как убедиться, что WAL пришёл в норму
После устранения причины дайте базе пройти чекпоинт и проверьте, что pg_wal уменьшился. Можно инициировать чекпоинт вручную и посмотреть размер снова:
CHECKPOINT;
du -sh /var/lib/postgresql/*/main/pg_wal
Если после чекпоинта каталог заметно сократился и продолжает держаться в разумных пределах — проблема решена. Если WAL по-прежнему растёт, значит причина не устранена: снова проверьте слоты (pg_replication_slots), архиватор (pg_stat_archiver) и старые транзакции. Обычно одна из этих трёх вещей и держит WAL. Контроль после правки важен: он подтверждает, что база вернулась к нормальному циклу переиспользования сегментов, а не просто временно затихла.
Профилактика: держим WAL под контролем
Чтобы WAL не заполнял диск внезапно, следите за ключевыми точками. Мониторьте наличие неактивных слотов репликации — заброшенный слот тихо копит WAL неделями. Если используете архивирование, настройте оповещение о росте failed_count в pg_stat_archiver, чтобы сразу узнавать о поломке команды. Включите idle_in_transaction_session_timeout, чтобы забытые транзакции не удерживали ресурсы. Задайте max_wal_size и wal_keep_size осознанно под ваш объём записи и наличие реплик.
И, как всегда, держите запас свободного места на диске под базой с мониторингом заполнения: WAL — механизм надёжности, и лишать его места опасно. Помните главное правило на случай аврала: файлы pg_wal никогда не удаляют вручную — только устраняют причину, а PostgreSQL сам переиспользует сегменты. Такой подход бережёт и данные, и нервы, превращая пугающий рост WAL в понятную и решаемую задачу.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS под базуОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Можно ли удалить файлы из pg_wal вручную, чтобы освободить место?
Нет, категорически: ручное удаление WAL повреждает базу и ведёт к потере данных. Нужно устранить причину роста, и PostgreSQL сам переиспользует сегменты.
Что чаще всего заставляет WAL расти?
Неактивный слот репликации, который держит сегменты для отключившейся реплики, и сломанный archive_command, из-за которого сегменты не архивируются. Реже — долгие открытые транзакции.
Как понять, что виноват слот репликации?
Выполните SELECT slot_name, active FROM pg_replication_slots;. Слот с active = false, который не используется, держит WAL — его нужно удалить через pg_drop_replication_slot.
Как оплатить сервер с большим диском из России?
В MAATRIX — картой российского банка, через СБП, криптовалютой или токеном MAAT. Иностранная карта не нужна.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.