Бэкап, который никто не проверял
Ночной скрипт восемь месяцев завершался с кодом 0 и писал в лог «backup ok, 1.8 GB». Проверок не было ни одной — до момента, когда понадобилось восстановить базу.
Что оказалось не так
- Копия была неполной. Скрипт делал дамп основной базы, но не трогал вторую, где лежали настройки.
- Дамп снимался без блокировки. Формально валидный, но восстановление падало на несогласованных таблицах.
- Размер рос, место кончалось. Ротация удаляла самые старые копии, а половина места уходила на «успешные» копии битой базы.
Минимальный набор проверок
Восстановление в отдельную директорию раз в неделю — самый дешёвый способ узнать правду. Не «файл существует», а «данные читаются»:
set -e
pg_restore --clean --if-exists -d restore_check /backup/latest.dump
psql -d restore_check -c 'select count(*) from events;' | tail -1
psql -d restore_check -c 'select max(created_at) from events;'
Две последние строки важнее первой: они показывают, что данные не просто импортировались, а дошли до сегодняшнего дня. Дамп, который восстанавливается за март, — это тоже отказ, только обнаруженный позже.
Что изменили
| Было | Стало |
|---|---|
| Лог «backup ok» | Метрика «возраст последней проверенной копии» с алертом на 36 часов |
| Одна копия в той же сети | Две площадки, вторая — только на чтение |
| Ротация по дате | Ротация по дате плюс контроль свободного места до старта |
Что бы сделал иначе
- Восстановление — в первый же день, до того как скрипт попадёт в cron.
- Проверка должна быть автоматической: ручная «раз в квартал» превращается в «никогда».
- Алерт не на «копия не создана», а на «копия не проверена»: первое ловит падение скрипта, второе — тихую деградацию.