Акция Панель управления ispmanager для VDS — первый месяц бесплатно
до 31.07.2026 Подробнее
Выберите продукт

Backup 3-2-1 для MySQL и PostgreSQL: RPO/RTO, retention и restore test

Практическое руководство по backup 3-2-1 для MySQL и PostgreSQL: какие копии хранить локально и offsite, как связать стратегию с RPO/RTO, настроить retention и PITR через binlog/WAL. Отдельно — как организовать restore test и что именно проверять.
Backup 3-2-1 для MySQL и PostgreSQL: RPO/RTO, retention и restore test

Почему «у нас есть бэкапы» часто означает «восстановиться не сможем»

Резервное копирование почти всегда «работает» ровно до первого реального инцидента. В панели всё зелёное, задачи выполняются, но в день X внезапно выясняется, что копии неполные, зашифрованные архивы не расшифровать (ключи потеряны), точки восстановления не совпадают с ожиданиями бизнеса, а процедура восстановления не запускалась годами.

Подход backup 3-2-1 полезен тем, что заставляет мыслить не «куда складывать дампы», а «как гарантировать восстановление при разных типах отказов». Дальше разберём практичную схему: где хранить копии, как выбирать retention, как привязать всё к RPO/RTO и как поставить регулярный restore test так, чтобы он не превратился в ручную пытку.

Правило 3-2-1: что именно означают цифры

Классическая формулировка:

  • 3 копии данных: рабочая + минимум две резервные.
  • 2 разных типа носителей/хранилищ: например, локальный диск и удалённое объектное хранилище; либо разные storage-классы/провайдеры; либо снапшоты и файловые архивы.
  • 1 копия вне основной площадки (offsite): переживает пожар/потерю узла/удаление данных/сбой СХД/«случайный rm -rf».

В 2025-м «носители» чаще означают не ленты и HDD, а разные домены риска: разные учётки и ключи доступа, разные механизмы хранения (дампы vs физические бэкапы vs журналы), разные зоны отказа.

3-2-1 не отменяет здравый смысл

Если данные критичны, правило расширяют до 3-2-1-1-0: дополнительная неизменяемая копия (immutability/WORM) и 0 ошибок по результатам верификации. Но начинать проще всего с 3-2-1 и дисциплины restore test.

Схема правила 3-2-1: рабочие данные, локальная копия и offsite-хранилище

RPO и RTO: переводим «хочу надёжно» в измеримые цифры

Два параметра задают рамки стратегии:

  • RPO (Recovery Point Objective) — сколько данных вы готовы потерять по времени. Пример: RPO=15 минут означает, что после аварии допустима потеря изменений не более чем за 15 минут.
  • RTO (Recovery Time Objective) — за сколько времени сервис должен вернуться в строй. Пример: RTO=60 минут — через час после инцидента система должна работать.

Если RPO и RTO не зафиксированы, вы почти неизбежно строите «бэкап ради бэкапа»: он будет либо слишком дорогим, либо не выдержит ожиданий бизнеса.

Как RPO влияет на тип бэкапа для баз данных

Для MySQL и PostgreSQL RPO напрямую определяет, хватит ли периодических «полных» копий или нужен журнал изменений:

  • RPO в часы: часто достаточно ежедневной полной копии (дамп или физический бэкап).
  • RPO в минуты: почти всегда нужен PITR (point-in-time recovery) через журналы: binlog для MySQL и WAL-архивация для PostgreSQL.
  • RPO близкий к нулю: нужна репликация, но репликация не заменяет бэкап (она тиражирует и ошибку/порчу данных).

Если вы только начинаете, полезно зафиксировать «целевой RPO» и «переходный RPO». Например: сейчас RPO=24 часа (пока только ночной дамп), цель через месяц — RPO=30 минут (дамп + журналы).

Как RTO влияет на формат хранения и автоматизацию

Даже при одинаковом RPO, RTO может сильно отличаться. Для RTO=15–30 минут обычно нужно заранее иметь:

  • быстрый доступ к «последнему полному» бэкапу (локально или в пределах одной сети);
  • отработанную процедуру восстановления с заранее подготовленными конфигами, правами, секретами;
  • проверенные шаги переключения приложения на восстановленную БД (DNS/строка подключения/балансировщик).

Если RTO «день-два», можно использовать более дешёвые и медленные уровни хранения. Но это не отменяет регулярного restore test.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Retention: сколько хранить и почему «30 дней» — почти всегда случайная цифра

Retention — политика хранения копий: сколько держим ежедневных, недельных, месячных, иногда годовых. Её нельзя выбирать «по привычке»: она должна отвечать на два разных типа инцидентов.

  • Операционные сбои: случайно удалили таблицу, выкатили миграцию с ошибкой, испортили данные импортом. Тут нужны частые точки восстановления за последние дни/недели.
  • Долгоживущие инциденты: тихая порча данных, компрометация, вредоносная правка, обнаруженная через месяц. Тут помогают недельные/месячные копии и отдельный offsite.

Стартовый шаблон retention для небольших проектов:

  • ежедневные: 14–30;
  • еженедельные: 8–12;
  • ежемесячные: 6–12.

Но корректнее идти от требований: «какую самую старую ошибку мы реально хотим уметь откатить» и «сколько стоит хранение». Для баз данных объём растёт быстро, поэтому заранее продумайте, какие типы копий будут полными, а какие — инкрементальными (или основанными на журналах).

Архитектура 3-2-1 на практике: минимальная рабочая схема

Ниже — вариант, который хорошо масштабируется и закрывает типовые риски.

Копия №1: локальный быстрый слой (для RTO)

Цель слоя — быстрое восстановление при «обычных» проблемах: неудачный релиз, ошибочная миграция, человеческий фактор. Обычно здесь хранят:

  • последние полные бэкапы;
  • инкременты/журналы для PITR (если нужен малый RPO);
  • короткий retention (например, 7–14 дней), чтобы не забить диск.

Важный принцип: локальный слой не должен быть единственным. Он уязвим к тем же событиям, что и прод.

Копия №2: удалённое хранилище (offsite)

Это «парашют», который должен переживать потерю узла/площадки и часть сценариев компрометации. Практики, которые действительно работают:

  • отдельные ключи доступа и отдельная учётка, по возможности в другом контуре;
  • минимальные права (для загрузки — без массового удаления);
  • сетевые ограничения;
  • по возможности неизменяемость (WORM/immutability) или хотя бы версионирование.

Если проект живёт на виртуальных машинах, offsite удобно организовать на отдельном узле/площадке: например, выделить отдельную VDS под приём бэкапов и периодические restore test (с ограниченным доступом и раздельными ключами).

«2 разных хранилища» как разные домены отказа

Формально выполнить правило легко: «локальный диск и удалённый диск». Но если оба завязаны на один аккаунт и одну пару ключей, это не разные домены риска. Разные домены — это когда одно событие не уничтожает всё сразу: другая учётка, другой провайдер, другой независимый storage-слой, отдельная политика доступа.

Процесс restore test: восстановление базы и чек-лист проверок целостности

Restore test: единственный способ доказать, что бэкап существует

Restore test — регулярная проверка восстановления. Не «проверка, что файл есть», а полный цикл: скачать, проверить целостность, расшифровать, развернуть, поднять сервис и выполнить контрольные проверки.

Рекомендованная частота (как ориентир):

  • критичная БД: еженедельно (частичный тест) + ежемесячно полный прогон;
  • обычные проекты: ежемесячно;
  • после изменений в схеме бэкапа, ключах/правах, версиях СУБД: внепланово.

Что именно проверять в restore test

  • архив скачивается и проходит проверку целостности (checksum);
  • ключи/пароли доступны по аварийной процедуре;
  • восстановление заканчивается успешным стартом СУБД;
  • данные «похожи на правду»: размеры, количество таблиц, контрольные выборки;
  • приложение может подключиться (в тестовой среде);
  • RTO реально достижим: измеряете время по шагам.

«Бэкап успешен» без restore test означает только одно: скрипт отработал без ошибок. О восстановлении это может не говорить ничего.

MySQL: практический набор для 3-2-1 (дамп + binlog для RPO в минуты)

Для MySQL распространены две логики: логический дамп (mysqldump) и/или физический бэкап. В базовом универсальном варианте можно стартовать с «дамп + binlog», чтобы получить PITR между дампами.

Включаем binlog и задаём срок хранения

Проверьте, что бинарные логи включены (обычно параметр log_bin), и настройте удержание. Для MySQL 8 ключевой параметр — binlog_expire_logs_seconds:

mysql -e "SHOW VARIABLES LIKE 'log_bin%';"
mysql -e "SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';"

Идея простая: срок хранения binlog должен перекрывать интервал между полными бэкапами с запасом, иначе PITR окажется невозможен.

Если вам важен предсказуемый PITR, полезно отдельно разобраться с GTID и восстановлением по binlog (с практическими сценариями): PITR в MySQL/MariaDB через binlog и GTID.

Дамп + компрессия + шифрование (пример)

Шифруйте бэкапы до отправки в offsite. Ниже — пример потока «дамп → сжатие → шифрование». В примере используется gpg (ключ/получатель замените на ваш).

mkdir -p /backups/mysql
mysqldump --single-transaction --routines --events --triggers --all-databases | gzip -1 > /backups/mysql/mysql-$(date +%F).sql.gz
gpg --batch --yes --encrypt --recipient backup@company.example /backups/mysql/mysql-$(date +%F).sql.gz

Локально держите короткий retention, а в offsite — полный срок по политике хранения. Важно: «ключи бэкапов» должны жить по отдельному регламенту, иначе одна потеря секретов отменит всю стратегию.

Restore test для MySQL (в тестовой VM)

Минимально полезная проверка: развернуть чистый инстанс, залить дамп, выполнить контрольные запросы. Примерный скелет команд:

gpg --batch --yes --decrypt /backups/mysql/mysql-2025-12-25.sql.gz.gpg > /tmp/mysql.sql.gz
gzip -d -c /tmp/mysql.sql.gz > /tmp/mysql.sql
mysql -uroot -p -e "SELECT 1;"
mysql -uroot -p < /tmp/mysql.sql
mysql -uroot -p -e "SHOW DATABASES;"

Если у вас заявлен RPO «в минуты», вы обязаны периодически тестировать восстановление «дамп + binlog» до выбранной точки времени (PITR), иначе это только декларация на бумаге.

PostgreSQL: практический набор для 3-2-1 (base backup + WAL для PITR)

В PostgreSQL путь к малому RPO — базовый бэкап плюс WAL-архивация. Тогда можно восстановиться на конкретное время (PITR) между полными копиями.

Проверяем, включена ли WAL-архивация

Ключевые параметры: wal_level, archive_mode, archive_command. Быстро посмотреть:

psql -c "SHOW wal_level;"
psql -c "SHOW archive_mode;"
psql -c "SHOW archive_command;"

archive_command должен надёжно сохранять WAL в отдельное место. Критично: команда должна возвращать успешный код только если WAL действительно сохранён, иначе вы получите «дырки» и невозможность PITR.

Базовый бэкап (pg_basebackup) как «полная точка»

pg_basebackup — базовый инструмент. Пример создания полной копии в каталог:

mkdir -p /backups/pg/base
pg_basebackup -D /backups/pg/base/$(date +%F) -Fp -Xs -P -R

Дальше каталог обычно упаковывают, шифруют и отправляют в offsite. Для крупных баз часто применяют специализированные решения, но логика 3-2-1 и restore test не меняется.

Restore test для PostgreSQL: проверяем старт и контрольные запросы

Частая проблема: файлы восстановили, но сервер не стартует из-за прав, несовместимой версии, отсутствия WAL или неверных параметров. Поэтому тест должен включать именно запуск.

sudo -u postgres pg_ctl -D /var/lib/postgresql/restored start
psql -c "SELECT now();"
psql -c "SELECT count(*)" FROM pg_catalog.pg_class;"

Если вы делаете PITR, добавьте отдельный тест восстановления на указанное время и проверку «ожидаемого состояния» (например, наличие записей после контрольной транзакции).

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Безопасность бэкапов: шифрование, доступы, ключи

Бэкапы обычно содержат всё: персональные данные, токены, коммерческую информацию. Потеря бэкапов по последствиям часто хуже, чем потеря прод-сервера. Минимальные правила:

  • Шифруйте до отправки в удалённое хранилище. Само хранилище не должно быть «последним рубежом» безопасности.
  • Разделяйте права: аккаунт, который пишет бэкапы, не должен иметь возможность массово удалить историю. Где возможно — делайте режим «только запись», а удаление по retention выполняйте отдельным контуром.
  • Ключи шифрования храните в управляемом контуре (vault/менеджер секретов) и держите офлайн-резерв по регламенту.
  • Логируйте операции: кто запустил, что создал, куда выгрузил, что удалил, сколько заняло времени.

Отдельно проверьте защиту каналов доступа к БД (внутренний TLS, доверенные CA, ротация сертификатов): TLS для MySQL/PostgreSQL: CA, сертификаты и проверка клиента.

Автоматизация: как не утонуть в скриптах и не потерять контроль

Автоматизация часто начинается с cron, но зрелая схема почти всегда добавляет три вещи: наблюдаемость, безопасную ротацию и тест восстановления.

Наблюдаемость: метрики, алерты, отчёты

Минимальный набор сигналов:

  • последний успешный бэкап (timestamp);
  • размер бэкапа (резкие изменения — тревожный признак);
  • время выполнения;
  • ошибки выгрузки в offsite;
  • результаты restore test (успешно/неуспешно).

Цель простая: узнать о проблеме раньше, чем о ней узнает продакшен-инцидент.

Ротация по retention без «rm -rf и молимся»

Удаление старых копий должно быть:

  • детерминированным (понятно, какие файлы удаляются и почему);
  • безопасным (защита от удаления «не того»);
  • логируемым (что удалили, сколько освободили).

Практичный подход: структура каталогов по датам, отдельный manifest со списком копий и checksum, удаление только того, что есть в manifest и подходит под retention.

Чек-лист 3-2-1 для MySQL/PostgreSQL

  1. Определены RPO/RTO для базы и согласованы с владельцем сервиса.
  2. Есть минимум 3 копии данных (prod + 2 бэкапа).
  3. Используются 2 разных домена хранения/риска (не «два каталога на одном диске»).
  4. Есть 1 offsite копия, переживающая отказ площадки и ошибки администратора.
  5. Настроена понятная retention (дни/недели/месяцы) и безопасная ротация.
  6. Бэкапы шифруются, ключи доступны по аварийному регламенту.
  7. Выполняется регулярный restore test с запуском СУБД и контрольными проверками.
  8. Замеряется фактический RTO по шагам восстановления и периодически пересматривается.

Типовые ошибки, которые ломают стратегию

  • Бэкап на тот же сервер без offsite: при потере диска вы потеряете всё.
  • Одинаковые ключи к продакшену и к хранилищу бэкапов: компрометация одного контура тянет второй.
  • Нет PITR при требовании малого RPO: ежедневный дамп не даст RPO=15 минут.
  • Нет restore test: «зелёные джобы» не равны восстановлению.
  • Retention без смысла: храните много, но не те точки восстановления, которые реально нужны.

Как начать, если сейчас бэкапы хаотичные

План внедрения, который даёт эффект быстро:

  1. Зафиксируйте RPO/RTO (хотя бы грубо) для 1–2 ключевых баз.
  2. Сделайте одну надёжную полную копию + offsite (начните с простого).
  3. Добавьте retention и безопасную ротацию.
  4. Внедрите restore test в отдельной тестовой среде.
  5. Если нужен малый RPO — включайте PITR: MySQL binlog, PostgreSQL WAL.

Главное — не пытайтесь сразу «идеально». Лучше стабильно выполнять 3-2-1 с проверкой восстановления, чем иметь сложную систему, которой никто не доверяет.

Поделиться статьей

Вам будет интересно

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: mount: wrong fs type, bad option, bad superblock — как быстро найти и исправить причину

Ошибка mount: wrong fs type, bad option, bad superblock в Debian/Ubuntu может означать и простую опечатку в имени раздела, и пробл ...
Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: XFS metadata corruption и emergency read-only — пошаговое восстановление

Если XFS-раздел внезапно стал доступен только для чтения, а сервер ушёл в emergency mode, главное — не спешить. Разберём безопасны ...
Debian/Ubuntu: как исправить Failed to fetch при apt update OpenAI Статья написана AI (GPT 5)

Debian/Ubuntu: как исправить Failed to fetch при apt update

Ошибка Failed to fetch при apt update в Debian и Ubuntu обычно связана не с самим APT, а с DNS, сетью, зеркалом, прокси, временем ...