Резервные копии 1С на PostgreSQL заполнили диск — и сломали саму 1С
Типовой крон резервных копий 1С на PostgreSQL перезаписывает недельные копии, а месячные весь первый год только добавляет. Через несколько месяцев раздел с базой заполнился, у 1С начали падать запросы, а одна копия оборвалась — и быстрая проверка этого не показала. Разобрали, почему так выходит, и поставили чистку по заполнению диска.
Недельные копии перезаписываются, месячные копятся целый год. Оборванная копия выглядит целой, пока её не прочитать до конца.
Год копий рядом с базой
Весь первый год каждый месяц — новая полная копия каждой базы, на том же разделе, что и сама база.
Оборванная копия
Оглавление на месте, и pg_restore -l его читает. Данных до конца нет — это видно только при полном прочтении.
Чистка по порогу
Выше порога уходят самые старые копии. Несколько новейших копий каждой базы не трогаются никогда.
Сервер СУБД под 1С: базы на PostgreSQL, резервные копии снимает крон
командой pg_dump. Схема взята из распространённых инструкций по установке
PostgreSQL для 1С: каждый день — копия каждой базы, по 7, 14, 21 и 28
числам — ещё одна, первого числа — месячная. Первые месяцы работает без
вмешательства. До утра, когда 1С начинает сыпать ошибками.
Что случилось
Утром первого числа крон снял очередной месячный набор, и раздел, где лежат и копии, и данные самой СУБД, заполнился до 100 %.
- У 1С падали запросы. Платформа на ходу создаёт временные таблицы, а
СУБД отвечала
could not extend file … No space left on device: расширить файл таблицы было некуда. - СУБД уходила в аварийный перезапуск. Раз за разом, а потом перестала писать и собственный журнал — тоже некуда.
- Копия оборвалась. Та, что снималась в момент заполнения, не дописалась до конца. Следующие копии в тот день не записались вовсе, а файл служебной базы остался пустым.
- Крон промолчал. Об ошибках он сообщает письмом, а почтовой службы на сервере нет, и сообщение просто выбрасывается.
Почему раздел заполнился
| Когда | Как называется копия | Сколько копий живёт |
|---|---|---|
| каждый день или каждый час | база.<день недели>.dump |
7, перезаписываются по кругу |
| 7, 14, 21, 28 числа | база.<день месяца>.dump |
4, перезаписываются |
| 1 числа | база.<день года>.dump |
12: весь первый год каждый месяц новая, перезаписываются только через год |
Недельные и «числовые» копии перезаписывают сами себя, и их объём стоит на месте. Месячная получает имя по номеру дня в году: каждый месяц имя новое, и повторяться имена начинают только через год. Весь первый год каждое первое число добавляет ещё одну полную копию каждой базы. Через год на диске живут 23 полные копии каждой базы: 7 недельных, 4 «числовых» и 12 месячных. Под такой объём раздел обычно не рассчитывают. А лежат копии на одном разделе с данными СУБД, и, если места не хватит, они вытесняют саму базу.
Обрезанная копия выглядит целой
Копия в формате pg_dump -Fc начинается с оглавления — списка таблиц и
других объектов; адреса данных pg_dump дописывает в него только в самом
конце. Привычная быстрая проверка pg_restore -l
читает только оглавление. У оборванного файла оно на месте, поэтому
проверка проходит, хотя данных до конца файла нет.
Из проверок готового файла обрыв ловит только полный проход — пробное восстановление «в никуда»:
pg_restore -f /dev/null база.N.dump
Команда разворачивает копию в SQL-скрипт и тут же его выбрасывает. Для этого ей нужно прочитать файл до конца, и на оборванном она останавливается с ошибкой «не удалось прочитать входной файл: конец файла». Такую копию нельзя считать резервной, пока крон не перезапишет её через неделю.
Полный проход доказывает, что файл читается целиком. Что база из него поднимется и 1С с ней заработает, доказывает только восстановление в тестовую базу.
Что сделали
Крон 1С не меняли — поставили рядом страховку: чистку по заполнению раздела.
- Раз в час, до очередной копии, скрипт смотрит, сколько занято на разделе с копиями.
- Выше верхнего порога он удаляет самые старые копии — по дате файла, через все базы, — пока занятость не опустится ниже нижнего. Первыми уходят старые месячные.
- Несколько новейших копий каждой базы не удаляются никогда, среди них и та, что пишется прямо сейчас.
- Если удалять уже нечего, а раздел всё ещё выше порога, скрипт пишет ошибку в системный журнал и завершается отдельным кодом: дальше нужен человек, чтобы расширить диск или вынести копии.
- Есть режим просмотра: показывает, что было бы удалено, и ничего не трогает. Сразу после установки роль показывает, что чистка удалила бы при текущем заполнении.
- Защиту от двойного запуска держит сам каталог, а не файл в нём. На заполненном до нуля диске файл не создать, и чистка не стартовала бы ровно тогда, когда она нужна.
Верхний порог выбирается так, чтобы свободного места на нём хватило на новый месячный набор всех баз и на всплеск временных таблиц 1С. Чем крупнее базы относительно диска, тем ниже порог. Нижний — на несколько пунктов ниже, чтобы чистка не срабатывала каждый час.
Чистка ставится ролью Ansible. Что поменяли в регламенте: на сервере 1С с такой схемой копий чистку ставим сразу, вместе с кроном, а целостность копии проверяем полным проходом, а не оглавлением.
У чистки есть граница: целостность копий она не проверяет. «Новейшую» копию она определяет по дате, и если оборвётся именно она, на диске останется обрезанный файл. Поэтому копии нужно проверять восстановлением.
Результат
| Было | Стало | |
|---|---|---|
| Месячные копии | копятся весь первый год | самые старые удаляются, когда раздел подходит к порогу |
| Раздел с базой | заполнился до 100 % | чистка освобождает место раньше, чем его не хватит базе |
| Новейшие копии каждой базы | — | не удаляются никогда |
| Удалять нечего, а места нет | крон молчит | ошибка в системном журнале |
| Способ проверки копии | оглавление: копия кажется целой | полный проход до конца файла |
| Схема копий 1С | — | не менялась |
Чем можем помочь
Мы разобрали эту схему до конца и знаем, где она ломается: месячные копии целый год только копятся; копии на одном разделе с базой вытесняют саму базу; оборванная копия проходит проверку оглавлением; а крон сообщает об ошибке письмом, которое некому доставить.
Проверим резервное копирование вашей 1С на PostgreSQL восстановлением: прочитаем каждую копию до конца, поднимем базу из свежей копии в тестовой среде и покажем, за сколько дней у вас на самом деле есть целые копии. Поставим чистку по заполнению, вынесем копии с сервера базы и настроим сигнал, если копия не снялась или оборвалась.
Ещё по теме
- 10 ГБdf показывает 27 из 30 ГБ занято (92%), а файлы занимают только 17 ГБ
- 4Заказ был один — интерфейс к записям звонков. Нашли ещё четыре отказа
- 1,9 ТБ1,9 ТБ бэкапа при 20 ГБ занятых данных: как NetFlow раздувал инкременты
- 0Zabbix не переносит историю между СУБД. Перевезли 4.2 → 7.0 с MySQL на PostgreSQL — без потерь и без простоя