EN RU

Инкрементальная система резервного копирования с CentOS 6 на Ubuntu 24

Решение для инкрементального бэкапа с машины на CentOS 6 на удалённую машину под Ubuntu 24. Оно будет:

  • используется rsync по SSH для инкрементальных бэкапов с сохранением структуры и ссылок на неизмененные файлы,
  • автоматически монтируется целевой диск на Ubuntu (при необходимости),
  • создаются директории с датами и ссылкой last для последних бэкапов,
  • выполняется дамп MySQL-баз с CentOS и восстанавливать их в базу данных на Ubuntu под префиксом BackUp_,
  • выполняется через cron раз в сутки.

Введение

В данной инструкции представлено комплексное решение для организации ежедневного инкрементального бэкапа (резервного копирования) файловой системы и баз данных MySQL с сервера на CentOS 6 на удалённый сервер под управлением Ubuntu 24. Решение разработано с учётом требований надёжности и эффективности, ориентировано на использование старшим системным администратором.

Ключевые особенности решения:

  • Инкрементальное резервное копирование файлов с помощью rsync и жёстких ссылок: Каждый ежедневный снимок содержит только изменившиеся файлы по сравнению с предыдущим днем, неизменённые файлы представлены жёсткими ссылками на прошлые резервные копии. Это экономит место и ускоряет процесс – после первой полной синхронизации по сети объём ежедневной передачи данных минимален (передаются только изменения). Все бэкапы хранятся в виде отдельных каталогов с датой, но фактически общие файлы не дублируются на диске.
  • Резервное копирование баз данных MySQL через репликацию на удалённый сервер: Вместо сохранения дампов баз данных в файлы, на удалённом сервере настраивается сервер MySQL, в котором ежедневно обновляются копии баз данных. Для каждой исходной базы данных создаётся резервная база с префиксом BackUp_ в названии. С помощью механизмов репликации MySQL в эти резервные базы данных применяются только изменения, произошедшие за день, что позволяет избежать полной пересылки 240 ГБ данных каждый раз. По сути, удалённый сервер будет выступать в роли реплики (slave), принимая изменения от основного (master) сервера раз в сутки или в непрерывном режиме – это решается по усмотрению администратора.
  • Надёжность и целостность: Предусмотрены меры для обеспечения целостности данных – использование rsync с проверкой и включением важнейших ключей (-a для сохранения прав/атрибутов, -R для хранения путей), фильтрация исключений, очистка временных файлов перед бэкапом. Для баз данных – использование репликации обеспечивает консистентность данных без длительного блокирования, а первоначальная синхронизация выполняется аккуратно с фиксацией позиции бинарного лога.
  • Подробные комментарии и настраиваемость: Приводится полностью документированный скрипт резервного копирования с понятными именами переменных и комментариями на английском языке. Инструкции по настройке (в том числе конфигурации MySQL для репликации) – на русском. Каждое действие разъясняется, чтобы упростить сопровождение и возможную модификацию системы резервного копирования.

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


1. Настройка инкрементального бэкапа файлов с помощью rsync

Для резервного копирования файлов используется утилита rsync, которая позволяет синхронизировать директории между серверами по SSH и поддерживает создание инкрементальных бэкапов с помощью жёстких ссылок (--link-dest). В нашей схеме сервер CentOS 6 выступает в роли источника данных (файловая система, которую бэкапим), а сервер Ubuntu 24 – в роли хранилища резервных копий.

1.1. Подготовка удалённого сервера (Ubuntu 24) для хранения бэкапов:

  • Монтаж диска для бэкапов. На удалённом сервере должен быть подключён достаточный объём дискового пространства (в нашем случае объём данных ~240 ГБ). Предположительно, у вас есть отдельный диск или раздел для резервных копий. Смонтируйте этот раздел, например, в каталог /backup (или используйте путь из исходного скрипта – /3TB/backup.RSYNC/). Для повышения производительности монтируйте файловую систему с опцией noatime (отключает обновление времени доступа к файлам):
  # Пример: монтируем раздел /dev/sdc2 в /backup
  sudo mkdir -p /backup
  sudo mount /dev/sdc2 /backup -o noatime

⚠️ Примечание: Вы можете добавить запись в /etc/fstab на сервере Ubuntu, чтобы этот раздел монтировался автоматически при загрузке с опцией noatime.

  • Создание структуры каталогов резервного копирования. На удалённом сервере создайте основной каталог для резервных копий и необходимые подкаталоги. В нашем примере будем использовать /backup/RSYNC в качестве базового каталога:
  sudo mkdir -p /backup/RSYNC

Здесь будут создаваться ежедневные снимки. Также создадим внутри специальную символическую ссылку last, указывающую на последний (самый свежий) бэкап, для удобства организации инкрементных копий:

  cd /backup/RSYNC
  sudo ln -s ./dummy last
  # (создаём временную ссылку-заглушку, которую потом переназначим на первый бэкап)

Эта ссылка last будет автоматически обновляться после каждого бэкапа, указывая на папку с последней датой. rsync будет использовать её для расчёта изменений (--link-dest=../last).

  • Настройка доступа по SSH. Убедитесь, что с сервера CentOS имеется беспрепятственный SSH-доступ на сервер Ubuntu (желательно по ключам без пароля для автоматизации cron-заданий). Сгенерируйте SSH-ключ на CentOS (если ещё нет) и добавьте публичный ключ в ~/.ssh/authorized_keys пользователя, от имени которого будет выполняться бэкап на Ubuntu (например, root или выделенный пользователь резервного копирования). Проверьте, что команда входа на удалённый сервер по SSH проходит без запроса пароля:
  ssh backupuser@BackupServerHostname "echo Connection successful"
  • Подготовка файла исключений для rsync. Создайте на исходном сервере (CentOS) файл с перечнем исключённых из бэкапа путей. В оригинальном скрипте использовался файл /.rsync-filter. Можно хранить его, например, в /root/.rsync-filter или любом удобном месте. Добавьте в него шаблоны файлов и папок, которые не нужно копировать:
  # /.rsync-filter - список исключений rsync
  - /dev/**
  - /proc/**
  - /sys/**
  - /run/**
  - /mnt/**
  - /media/**
  - /tmp/**
  - /var/tmp/**
  - /var/run/**
  - /swapfile
  - /path/to/other/exclude/**

Объяснение: мы исключаем виртуальные и временные файловые системы (/dev, /proc, /sys и т.д.), временные файлы и кэши, а также любые другие каталоги, которые не нужно сохранять (например, точки монтирования внешних носителей, сам каталог резервных копий, если он примонтирован в исходной системе и т.п.). Убедитесь, что в этот список добавлены все ненужные для бэкапа пути, чтобы не копировать лишние данные и не зациклить копирование.

Совет: Если на исходном сервере каталог для бэкапа (например, /3TB или аналог) был примонтирован, обязательно исключите его из копирования, иначе rsync попытается скопировать в том числе и уже сделанные бэкапы (рекурсия). В приведённом выше шаблоне исключения мы используем - /mnt/** и - /media/** – если ваш локальный бэкап-диск монтировался, скорее всего, под эти пути. В случае сомнений явно добавьте строку вида - /3TB/** или путь, где монтировался диск, чтобы исключить его.

1.2. Скрипт резервного копирования файлов (backup_files.sh):

Ниже приведён обновлённый shell-скрипт, выполняющий инкрементальный бэкап файловой системы CentOS на удалённый Ubuntu. Скрипт необходимо разместить на исходном сервере (CentOS 6), например, в /usr/local/bin/backup_files.sh, и дать ему права на исполнение (chmod +x backup_files.sh). Код снабжён детальными комментариями:

#!/bin/bash
#
# Author: Senior SysAdmin
# Date:   2025-07-30
# Description: Incremental backup from CentOS6 to remote Ubuntu24 using rsync and hard links.
#

# === Настройки ===

# Исходный каталог для резервного копирования (корень системы)
SOURCE_DIR="/"

# Удалённый сервер и пользователь для подключения по SSH
REMOTE_USER="backupuser"                         # замените на актуальное имя пользователя на удалённом сервере
REMOTE_HOST="backup.example.com"                 # замените на адрес/имя хоста удалённого сервера

# Базовый каталог для хранения резервных копий на удалённом сервере
REMOTE_BASE_DIR="/backup/RSYNC"                  # должен совпадать с тем, что настроено на Ubuntu (см. подготовку)

# Путь к файлу с исключениями rsync (на локальном сервере)
RSYNC_EXCLUDE_FILE="/root/.rsync-filter"         # убедитесь, что файл существует и заполнен необходимыми шаблонами

# Лог-файл для сохранения вывода (опционально)
LOG_FILE="/var/log/backup_files.log"

# === Подготовка перед копированием ===

# 1. Очищаем кэши памяти, чтобы снизить нагрузку на систему во время бэкапа.
#    Это освобождает кэш диска из RAM, чтобы операция чтения не вызывала вытеснение активных данных (опционально).
echo "[$(date)] Flushing filesystem caches..." | tee -a "$LOG_FILE"
sync && echo 3 > /proc/sys/vm/drop_caches

# 2. Удаляем старые временные сессии и файлы (пример для конкретного приложения, настройте под свои нужды).
#    Эти файлы часто меняются и не несут ценности для бэкапа, их лучше очистить, чтобы не сохранять лишние данные.
echo "[$(date)] Cleaning up temporary files..." | tee -a "$LOG_FILE"
find /var/www/md/data/mod-tmp/ -maxdepth 1 -name "sess_*" -print0 | xargs -0 rm -f

# 3. Получаем текущую дату для имени папки бэкапа.
BACKUP_DATE="$(date +%Y-%m-%d)"

# 4. Определяем удалённые пути: новая папка бэкапа и ссылка 'last'.
REMOTE_TARGET_DIR="${REMOTE_BASE_DIR}/${BACKUP_DATE}"
REMOTE_LAST_LINK="${REMOTE_BASE_DIR}/last"

# === Выполнение резервного копирования через rsync ===

echo "[$(date)] Starting rsync backup for date $BACKUP_DATE ..." | tee -a "$LOG_FILE"

# Команда rsync:
rsync -av -e "ssh" \
    -R --delete \ 
    --exclude-from="$RSYNC_EXCLUDE_FILE" \
    --link-dest="../last" \
    "$SOURCE_DIR" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_TARGET_DIR}/" \
    | tee -a "$LOG_FILE"

RSYNC_STATUS=${PIPESTATUS[0]}  # статус выхода rsync (0 - успешно)

if [ $RSYNC_STATUS -ne 0 ]; then
    echo "[$(date)] ERROR: rsync encountered an issue (exit code $RSYNC_STATUS). Backup aborted." | tee -a "$LOG_FILE"
    exit $RSYNC_STATUS
fi

# === Обновление символической ссылки на последний бэкап ===

echo "[$(date)] Updating 'last' symlink on remote server to point to $BACKUP_DATE ..." | tee -a "$LOG_FILE"
ssh -o BatchMode=yes ${REMOTE_USER}@${REMOTE_HOST} "ln -nsf '${REMOTE_TARGET_DIR}' '${REMOTE_LAST_LINK}'"

if [ $? -ne 0 ]; then
    echo "[$(date)] ERROR: Unable to update 'last' symlink on remote server." | tee -a "$LOG_FILE"
    # Не прерываем выполнение, так как сама копия сделана; но логируем проблему.
fi

echo "[$(date)] File backup completed successfully." | tee -a "$LOG_FILE"

Пояснение к скрипту:

  • Блок настроек в начале скрипта позволяет легко адаптировать сценарий под вашу среду:
  • SOURCE_DIR – что именно копируем (в данном случае " / " означает весь корень файловой системы CentOS, кроме исключённых путей).
  • REMOTE_USER, REMOTE_HOST – учетные данные для подключения к удалённому серверу по SSH.
  • REMOTE_BASE_DIR – путь на удалённом сервере, где хранятся резервные копии (у нас /backup/RSYNC).
  • RSYNC_EXCLUDE_FILE – локальный файл со списком исключений для rsync.
  • LOG_FILE – путь к файлу логов на локальном сервере (опционально, можно задать или убрать вывод tee).
  • Подготовка перед копированием:
  1. Сброс кэшей (drop_caches). Это взято из оригинального скрипта – выполнение sync и очистки page cache. Данная команда не обязательна, но помогает освободить оперативную память, занятую кешированием дисковых операций. На системах с ограниченной памятью это может предотвратить влияние бэкапа на работу сервисов.
  2. Очистка временных файлов. Здесь показан пример удаления файлов сессий в директории /var/www/md/data/mod-tmp/ (т.к. оригинальный скрипт чистил sess_* там). Вам следует настроить этот шаг под свою ситуацию: удалите временные файлы, кэши приложений, логи, если они не нужны в бэкапе, и т.п. Цель – уменьшить объём изменяющихся данных, чтобы инкрементальные копии были максимально эффективны и не хранили мусор.
  3. Вычисление текущей даты BACKUP_DATE – она используется для именования папки, куда сложатся файлы бэкапа за этот день.
  4. Определение путей на удалённом сервере: переменная REMOTE_TARGET_DIR – это новый каталог (с датой) для текущего бэкапа, REMOTE_LAST_LINK – путь к символической ссылке last на стороне бэкапа.
  • Выполнение rsync:
    Используем ключи:
  • -a (--archive) – рекурсивное копирование с сохранением прав, владельцев, меток времени и т.д.
  • -v (--verbose) – для наглядности выводим, что копируется.
  • -e "ssh" – указываем, что транспорт – ssh. Можно настроить нестандартный порт, если нужно: -e "ssh -p порт".
  • -R (--relative) – важный ключ относительных путей. Он позволяет копировать с сохранением полного пути от указанных исходных каталогов. Поскольку мы передаем в rsync исходник /, ключ -R в сочетании с приведённым синтаксисом сохранит структуру каталогов. В частности, вместе с --link-dest это помогает rsync правильно сопоставлять файлы с предыдущим бэкапом.
  • --delete – включаем удаление на стороне приёмника тех файлов, которые удалены на исходной стороне. Это поддерживает актуальность зеркала. (Учтите, --delete работает совместно с --link-dest аккуратно: если файл был удалён на исходнике, то в новом снимке он не будет присутствовать, но останется в старых снимках благодаря жестким ссылкам, не удаляя историю).
  • --exclude-from="$RSYNC_EXCLUDE_FILE" – подключаем созданный ранее файл со списком исключений, чтобы rsync пропускал ненужные папки/файлы.
  • --link-dest="../last" – ключ, делающий бэкап инкрементальным. Он указывает rsync-у: для файлов, которые не изменились по сравнению с теми, что лежат в каталоге ../last, нужно не копировать данные заново, а создать жёсткую ссылку на уже существующую копию. Поскольку мы задаём путь ../last относительно каталога назначения, rsync на удалённом сервере поймёт его как /backup/RSYNC/last (что мы подготовили). Важно: первая резервная копия (когда ещё нет предыдущей) будет фактически полной, а начиная со второй --link-dest начнёт работать. Если скрипт запускается впервые и last указывает на несуществующую или пустую директорию, rsync проигнорирует --link-dest и скопирует всё заново.
  • Источник "$SOURCE_DIR" указан с заключающим слэшем и передаётся адресату user@host:${REMOTE_TARGET_DIR}/. Обратите внимание: важно прописать слэш в конце источника, чтобы rsync корректно интерпретировал содержимое корня (копировал внутрь целевой папки, а не саму папку / как имя).
  • В конце команда rsync конвейером | tee -a "$LOG_FILE" сохраняет вывод в лог-файл (это опционально, но полезно для последующей проверки, что бэкап прошёл успешно, какие файлы изменились и т.д.). После выполнения rsync мы проверяем переменную $RSYNC_STATUS – код возврата. Если rsync завершился с ошибкой (код не 0), то выводим сообщение об ошибке и прерываем скрипт с соответствующим кодом. Это нужно, чтобы в случае проблем (например, разрыв соединения, отсутствие доступа к диску и т.п.) вы сразу узнали и смогли разобраться.
  • Обновление символической ссылки:
    По завершении копирования выполняется команда:
  ssh -o BatchMode=yes ${REMOTE_USER}@${REMOTE_HOST} "ln -nsf '${REMOTE_TARGET_DIR}' '${REMOTE_LAST_LINK}'"

Она по SSH на удалённом сервере обновляет (ln -nsf) символическую ссылку last так, чтобы она указывала на вновь созданный каталог бэкапа ($BACKUP_DATE). Опции:

  • -n – не разыменовывать существующую ссылку (нужна для корректной перезаписи ссылки, а не создания внутри неё).
  • -s – создать символическую ссылку.
  • -f – принудительно заменить, если уже есть существующая. Таким образом, last всегда будет ссылаться на актуальный бэкап. В следующий запуск rsync сравнит данные именно с этим каталогом, обеспечивая инкрементальность. Скрипт логирует успех или неудачу обновления ссылки, но в случае ошибки не прерывается – поскольку сам бэкап уже сделан. Тем не менее, без обновлённой ссылки следующий инкремент не будет работать ожидаемо, поэтому важно следить, чтобы эта команда проходила успешно. Обычно ошибки могут быть, если не хватает прав на удалённом сервере или указаны неверные пути.
  • Завершение: Выводится сообщение об успешном завершении, фиксируется в лог.

Скрипт можно выполнять вручную, но для регулярного резервного копирования его следует добавить в планировщик cron. Например, чтобы запускать каждый день в 02:00 ночи, отредактируйте crontab (от пользователя root или того, кто обладает нужными правами) командой crontab -e и добавьте строку:

0 2 * * * /usr/local/bin/backup_files.sh

Это обеспечит ежедневный запуск. Убедитесь, что скрипт работает корректно в ручном режиме, особенно при первом запуске (первый бэкап может занять продолжительное время, так как копируются все ~240 ГБ). При первом запуске можно добавить флаг -P (progress) к rsync для мониторинга прогресса копирования, либо отслеживать трафик по сети.

После первого успешного бэкапа убедитесь, что на удалённом сервере:

  • В каталоге /backup/RSYNC появился подкаталог с текущей датой, содержащий резервную копию файловой системы.
  • Символическая ссылка last указывает на этот каталог.
  • Попробуйте запустить бэкап снова (например, вручную) – второй запуск должен пройти значительно быстрее, скопировав только изменения. В выходе rsync вы увидите список только изменённых/новых файлов, а общий объём переданных данных по сети должен быть небольшим.

Проверка жёстких ссылок: Можно проверить, что неизменённые файлы не дублируются, а являются жёсткими ссылками:
На удалённом сервере выполните ls -li в двух папках бэкапов (например, первого и второго дня) на один и тот же файл, который не менялся. У файлов будет одинаковый inode номер и link count, свидетельствующие о том, что это одна физическая копия данных на диске с двумя ссылками. Это подтверждает, что метод инкрементного бэкапа работает правильно.

Примечание о скорости: Сеть 1 Гбит/c обеспечивает теоретически до ~125 МБ/с пропускной способности. 240 ГБ при такой скорости могут копироваться ~ (240 000/125) ≈ 1920 секунд, то есть порядка 32 минут в идеальных условиях. На практике, учитывая накладные расходы, скорость дисков, шифрование SSH, это скорее займет несколько часов. Первая синхронизация – самая долгая. Все последующие передачи будут значительно быстрее, поскольку объём изменений за сутки обычно на порядки меньше полного объёма данных.


2. Настройка резервного копирования MySQL в удалённую базу данных

Теперь перейдём ко второй части – резервированию баз данных MySQL. В оригинальном решении базы данных каждый день дампились (mysqldump в файлы .sql) и эти файлы сохранялись на диск. Мы вместо этого организуем резервное копирование на уровень СУБД, то есть настроим на удалённом сервере MySQL точные копии баз данных, которые будут обновляться ежедневно только изменениями.

Это достигается с помощью репликации MySQL: основная (master) база данных на CentOS 6 будет отправлять все транзакции реплике (slave) на Ubuntu 24. На реплике мы создадим базы данных с такими же схемами и данными, но назовём их с префиксом BackUp_. Таким образом, например, основная база mydatabase будет иметь копию BackUp_mydatabase на удалённом MySQL. Ежедневное обновление по сути сведётся к применению накопленных изменений (бинлоги) – то есть передаваться будут только изменения (вставки, обновления, удаления строк), а не полные дампы.

Настройка репликации – ответственный процесс. Разберём его пошагово.

Замечание по совместимости: Перед началом убедитесь, что версия MySQL/MariaDB на CentOS 6 совместима с репликацией на версию MySQL/MariaDB на Ubuntu 24. Как правило, MySQL поддерживает репликацию на реплику той же или более новой версии (вплоть до пары основных версий выше). Например, MySQL 5.5 может реплицироваться на MySQL 5.7 или 8.0. Однако репликация с более новой версии на старую не поддерживается. Также убедитесь, что на мастер-сервере (CentOS) включён бинарный лог и уникальный server-id. Если на CentOS используется дистрибутивный MySQL 5.1, возможно, стоит обновить хотя бы до 5.5/5.6 или MariaDB аналогичной версии для лучшей совместимости с современной версией на Ubuntu (которая, вероятно, MySQL 8.x или MariaDB 10.x). В примере будем считать, что на CentOS установлен MySQL 5.7 (для конкретики; вы адаптируете шаги под свою версию, различия минимальны).

2.1. Подготовка основного сервера (Master, CentOS 6):

  • Включение бинарного лога и настройка server-id: Откройте на мастер-сервере конфигурационный файл MySQL (например, /etc/my.cnf или /etc/mysql/my.cnf). В секции [mysqld] добавьте (или отредактируйте) следующие параметры:
  [mysqld]
  server-id               = 1
  log_bin                 = /var/log/mysql/mysql-bin.log
  binlog_format           = ROW
  binlog_expire_logs_seconds = 604800    # (пример: автоматически удалять бинлоги старше 7 дней)

Объяснения:

  • server-id=1 – уникальный идентификатор сервера в репликации. Убедитесь, что на slave будет другой server-id.
  • log_bin – включает бинарный лог и задаёт путь к файлам бинлога. Убедитесь, что указанный путь существует и MySQL имеет права на него. В CentOS6, если MySQL 5.1, параметр может быть log-bin (через дефис). После изменения MySQL необходимо перезапустить, чтобы бинлог включился.
  • binlog_format=ROW – формат бинлога. Рекомендуется ROW (показывает построчные изменения) для максимально корректной репликации данных, особенно при репликации с перенаправлением базы (нам это важно, чтобы replicate-rewrite-db надёжно работал для DML-операций). Note: В старых версиях MySQL (до 5.1.5) опция могла отсутствовать, но там только STATEMENT. Если master – старый MySQL, он возможно поддерживает только STATEMENT/MIXED. Репликация в принципе с replicate-rewrite-db работает и с STATEMENT (но требуются строгие правила, например отсутствие USE кросс-базовых операций). В идеале, если возможно, используйте ROW.
  • binlog_expire_logs_seconds=604800 – автоматически очищает старые бинлоги старше 7 дней (604800 секунд). Это аналог команды PURGE BINARY LOGS и предотвращает бесконечный рост логов. Можно также использовать expire_logs_days = 7 для MySQL версий, поддерживающих эту опцию (в MySQL 5.1, например, используется expire_logs_days). После внесения настроек, перезапустите MySQL на CentOS:
  sudo service mysqld restart   # или systemctl restart mysql, в зависимости от системы и версии

Убедитесь, что сервис запустился корректно. Можно проверить, что бинарные логи пишутся:

  SHOW MASTER STATUS;

Этот запрос в mysql-клиенте должен показать имя текущего бинарного лога и позицию, например:

  mysql> SHOW MASTER STATUS;
  +------------------+----------+--------------+------------------+-------------------+
  | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
  +------------------+----------+--------------+------------------+-------------------+
  | mysql-bin.000001 |      154 |              |                  |                   |
  +------------------+----------+--------------+------------------+-------------------+

Если File и Position появились, бинлог включён.

  • Создание пользователя репликации: На мастер-сервере нужен специальный пользователь, под которым реплика (удалённый сервер) будет подключаться, чтобы читать бинарный лог. Войдите в MySQL (например, mysql -u root -p) и выполните:
  CREATE USER 'replicator'@'BackupServerHostname' IDENTIFIED BY 'StrongPassword';
  GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'BackupServerHostname';
  FLUSH PRIVILEGES;

Замените BackupServerHostname на IP или имя хоста удалённого сервера (Ubuntu) или используйте 'replicator'@'%' (все хосты), если сеть безопасна или если hostname может меняться. Лучше указать конкретный адрес для безопасности. Пароль подберите надёжный и сохраните – он понадобится при настройке реплики.

  • Первичное создание резервных баз на мастере: Согласно документации MySQL, репликация не будет автоматически создавать базы данных с другим именем на слейве – тем более, у нас имена меняются (будет BackUp_*). Поэтому мы заранее создадим пустые базы данных на мастер-сервере, чтобы затем переносить их дамп. Это может показаться нелогичным (зачем на мастере BackUp_ базы?), но есть причина: мы хотим воспользоваться более простым способом дампа/загрузки данных. Мы создадим пустые базы BackUp_имя на мастере, снимем с них дамп, и восстановим на слейве как тоже BackUp_имя. Либо можно сразу дампить оригинальные базы, а на слейве импортировать под новым именем – этот путь требует редактировать дамп, что сложнее. Рассмотрим первый вариант:
    Для каждой базы данных, которую вы хотите резервировать, создайте на мастере соответствующую базу BackUp_.... Например, если есть база batteryservice, создайте пустую базу BackUp_batteryservice:
  CREATE DATABASE `BackUp_batteryservice`;
  CREATE DATABASE `BackUp_stella-com-bx`;
  CREATE DATABASE `BackUp_zabbix`;
  -- и так далее для всех необходимых баз

Делать дамп с мастера можно двумя путями:

  1. Дамп оригинальной базы и последующая правка имени при импорте – сложнее, нужно править CREATE DATABASE и USE в .sql-файле.
  2. Создать на мастере копию базы с новым именем и дампить её – требует скопировать данные на мастере, может быть накладно, если базы большие. Однако, мы можем упростить: поскольку у нас уже настроен бинлог, мы можем на слейве сначала импортировать оригинальные базы, а затем переименовать их на слейве. Но MySQL не позволяет легко RENAME DATABASE. Альтернативно – импортировать сразу как BackUp_ если отредактировать дамп. Чтобы не усложнять процесс, рекомендуется использовать штатный механизм дампа и указать другое имя базы при импорте:
  • На мастере снимите дамп каждой базы данных, требующей бэкапа: mysqldump --single-transaction --databases batteryservice > /tmp/batteryservice.sql mysqldump --single-transaction --databases stella-com-bx > /tmp/stella-com-bx.sql ... (и так далее для всех баз) Опция --single-transaction позволяет получить консистентный дамп без блокировки таблиц, при условии что используются InnoDB. Если у вас MyISAM таблицы, лучше сделать это под глобальным локом (ниже).
    Эти дампы будут содержать инструкции CREATE DATABASE и USE с оригинальными именами.
  • Отредактируйте каждый дамп-файл, заменив упоминания имени базы на вариант с префиксом BackUp_. Это можно сделать, например, командой sed: sed -i 's/CREATE DATABASE `/CREATE DATABASE `BackUp_/g' /tmp/batteryservice.sql sed -i 's/USE `/USE `BackUp_/g' /tmp/batteryservice.sql Приведённая команда добавит префикс BackUp_ ко всем встречам CREATE DATABASE \имя`иUSE `имя«. Будьте внимательны: она может сработать на подстроки, поэтому лучше точно указать старое имя: sed -i 's/CREATE DATABASE `batteryservice`/CREATE DATABASE `BackUp_batteryservice`/' /tmp/batteryservice.sql sed -i 's/USE `batteryservice`/USE `BackUp_batteryservice`/' /tmp/batteryservice.sql Повторите для остальных файлов, заменяя на соответствующие имена.
  • Альтернативный путь: можно было бы настроить репликацию сразу, и тогда использовать mysqldump утилиту на слейве с опцией --replicate-rewrite-db, но проще сделать статически.
  • Остановка приложений (опционально): Если возможно, на время съёма дампа данных желательно остановить активность, записывающую в базу (например, веб-сервер или приложения), либо выполняйте дампы поздно ночью при минимальной нагрузке. Это снизит вероятность несогласованности, особенно если не используете глобальный лок.
  • (Опционально) Глобальный лок на время дампа: Чтобы гарантировать абсолютно точную копию состояния всех баз на один момент, можно воспользоваться: FLUSH TABLES WITH READ LOCK; SHOW MASTER STATUS; Скопировать данные (дампы) и затем выполнить: UNLOCK TABLES; Но это блокирует запись во все таблицы, что может повлиять на сервисы. Если downtime неприемлем, лучше делать по одной базе с --single-transaction (как выше), что обычно достаточно для InnoDB.
  • Важный момент – фиксация позиции бинарного лога: После того как дампы сделаны, нам нужно знать координаты (имя файла бинлога и позиция), с которых начать репликацию на слейве, чтобы не потерять ни одну транзакцию. Если вы использовали FLUSH TABLES WITH READ LOCK и SHOW MASTER STATUS – выпишите значения File и Position оттуда. Если же без глобального лока, тогда сразу после дампов выполните на мастере:
  FLUSH LOGS;
  SHOW MASTER STATUS;

Команда FLUSH LOGS откроет новый бинарный лог; команды SHOW MASTER STATUS вернёт координаты начала нового лога – используйте эти значения. Например, запишите:

  File: mysql-bin.000002
  Position: 154

Это будет точкой старта для репликации (все изменения после дампа пойдут начиная с этого лога/позиции).

ℹ️ Почему после дампа? – Потому что дамп содержит состояние на момент завершения транзакций (в случае --single-transaction, момент начала дампа для каждой базы). Чтобы консистентно реплицировать изменения, нужно начать с первой транзакции, которая не попала в дамп. Проще всего открыть новый лог сразу после дампов; тогда все дальнейшие изменения будут в новом файле, и его с первой позиции можно подавать на реплику.

  • Перенос дампов на слейв: Скопируйте полученные файлы .sql на удалённый сервер (Ubuntu). Это можно сделать безопасно через scp:
  scp /tmp/*.sql backupuser@backup.example.com:/tmp/

Убедитесь, что место на удалённом сервере позволяет временно разместить эти дампы (суммарно размер равен сумме размеров баз данных). По возможности, после импорта их можно удалить.

2.2. Настройка реплики (Slave, Ubuntu 24):

Теперь настроим MySQL на удалённом сервере для приёма репликации.

  • Установка MySQL (если не установлен): На Ubuntu 24 установите пакет mysql-server или mariadb-server (в зависимости от предпочтений). Предположим, установлен MySQL 8.x (из стандартного репозитория Ubuntu). Убедитесь, что вы знаете root-пароль на этом сервере.
  • Настройка server-id и репликационных параметров на слейве: Откройте /etc/mysql/my.cnf (или /etc/mysql/mysql.conf.d/mysqld.cnf – актуальный для Ubuntu путь) и добавьте:
  [mysqld]
  server-id = 2
  log_bin   = /var/log/mysql/mysql-bin.log    # (не обязательно, но можно включить, если планируется цепочка репликаций; можно отключить)
  binlog_format = ROW                        # желательно тот же формат, что на мастере, но слейв сам формат логов мастера воспроизводит.
  # Репликационные фильтры:
  replicate-rewrite-db = batteryservice->BackUp_batteryservice
  replicate-rewrite-db = stella-com-bx->BackUp_stella-com-bx
  replicate-rewrite-db = zabbix->BackUp_zabbix
  ... (повторите для всех баз, которые реплицируем)
  replicate-ignore-db = mysql
  replicate-ignore-db = information_schema
  replicate-ignore-db = performance_schema
  replicate-ignore-db = sys

Объяснения:

  • server-id=2 – отличное от мастера значение.
  • log_bin – включать ли бинарный лог на слейве. Это не обязательно, если слейв не будет сам источником для другой реплики. Можно оставить включённым для возможности позже превратить этот сервер в мастер при аварии (failover), но тогда стоит также log_slave_updates поставить, чтобы он писал транзакции, полученные от мастера, в свой бинлог.
  • replicate-rewrite-db – ключевой параметр, реализующий переименование базы при репликации. Формат: old_name->new_name. Указываем оригинальное имя базы на мастере стрелка имя базы на слейве. Для всех баз, которые нужно копировать, добавьте такие строки. После настройки, MySQL, применяя репликацию, будет транслировать изменения: например, транзакции для database='batteryservice' он будет применять в базе BackUp_batteryservice.
    • Важно: перед запуском репликации, база BackUp_batteryservice на слейве должна существовать (иначе при попытке применения изменений слейв выдаст ошибку «unknown database»). Мы создадим их чуть позже.
    • Обратите внимание на особенность: replicate-rewrite-db не применится к командам CREATE DATABASE, DROP DATABASE – поэтому такие операции, если вдруг выполните на мастере, нужно вручную дублировать на слейве, либо избегать их (в продакшене, как правило, список баз статичен). Мы на мастере новые базы не создаём ежедневно, так что это не проблема.
  • replicate-ignore-db – мы перечислили системные базы, которые не хотим реплицировать (MySQL служебные, информация схем и т.д.). Таким образом, только пользовательские базы будут реплицироваться. Note: Фильтр replicate-ignore-db в комбинации с ROW-репликацией означает, что любые изменения в таблицах баз, указанных в ignore, не применятся. Это избавит от копирования служебной информации. Список можно расширить или скорректировать при необходимости.
  • Сохраните конфигурацию и перезапустите MySQL на слейве: sudo systemctl restart mysql
  • Импорт начальных данных на слейв: Используя дампы, перенесённые со старого сервера, восстановим данные в резервные базы:
  • Сначала создайте на слейве пустые базы с префиксом BackUp_ (если вы не сделали этого на мастере/не перенесли их): CREATE DATABASE BackUp_batteryservice; CREATE DATABASE BackUp_stella-com-bx; CREATE DATABASE BackUp_zabbix; ... и т.д. для всех. (Если вы редактировали дамп, добавляя CREATE DATABASE BackUp_*, то базы могут создаться при импорте автоматически. Но я рекомендую создать явно, чтобы убедиться, что нет ошибок с именами.)
  • Теперь импортируем каждый файл дампа в соответствующую базу: mysql -u root -p BackUp_batteryservice < /tmp/batteryservice.sql mysql -u root -p BackUp_stella-com-bx < /tmp/stella-com-bx.sql ... Если в дамп-файле присутствуют CREATE DATABASE/USE, которые вы правили, и вы запускаете импорт, указав базу после -p, то USE внутри файла может быть проигнорирован (так как CLI уже зашёл в указанную базу). Поэтому, если вы не убирали USE из дампов, лучше импортировать без указания базы: mysql -u root -p < /tmp/batteryservice.sql Тогда CREATE DATABASE BackUp_batteryservice из файла создаст базу (если не создана) и USE BackUp_batteryservice направит последующие CREATE TABLE/INSERT в неё. Убедитесь только, что файл отредактирован правильно. Следите за сообщениями об ошибках при импорте – их быть не должно. После импорта проверьте, что в базах BackUp_* на слейве появились таблицы и примерно соответствующее количество записей, как в оригинале.
  • Настройка связи репликации (START SLAVE): Когда данные на слейве загружены, можно запускать репликацию с нужной позиции. Для этого в mysql-консоли на слейве выполните команду CHANGE MASTER TO ...:
  STOP SLAVE;  -- на всякий случай, остановим, если запущен
  CHANGE MASTER TO
      MASTER_HOST='CentOS6_host_or_ip',
      MASTER_USER='replicator',
      MASTER_PASSWORD='StrongPassword',
      MASTER_LOG_FILE='mysql-bin.000002',
      MASTER_LOG_POS=154;
  START SLAVE;

Подставьте:

  • MASTER_HOST – адрес основного сервера (CentOS).
  • MASTER_USER и MASTER_PASSWORD – учётные данные пользователя репликации, созданного ранее.
  • MASTER_LOG_FILE и MASTER_LOG_POS – ту самую пару, что мы сохранили на мастере после дампа (SHOW MASTER STATUS). Обратите внимание, MASTER_LOG_FILE – имя файла с кавычками, должно точно соответствовать, и позиция – как число. После успешного START SLAVE; репликация запустится.
  • Проверка статуса репликации: Выполните на слейве команду:
  SHOW SLAVE STATUS\G

Она выдаст длинный список параметров. Нас сейчас интересуют:

  • Slave_IO_Running: Yes
  • Slave_SQL_Running: Yes
  • Seconds_Behind_Master: X (цифра, ideally 0 или небольшая, если репликация успела догнать)
  • Last_IO_Error и Last_SQL_Error должны быть пустыми. Если Slave_IO_Running или Slave_SQL_Running = No, либо есть ошибки, необходимо их устранить:
  • Если вы видите ошибку типа «Unknown database ‘…’ «, значит на слейве нет базы, куда пытается примениться транзакция – проверьте, созданы ли все BackUp_ базы и не опечатались ли в конфиге replicate-rewrite-db.
  • Если Seconds_Behind_Master большое и не уменьшается, значит слейв применяет большой объём изменений – подождите некоторое время, он должен догнать. В нашем случае, если мы сразу после дампа запустили, изменений будет немного.
  • Если появились ошибки из-за несовместимости SQL (например, разные версии, или слейв отклонил какую-то команду), нужно разбираться индивидуально. Часто проблемы возникают, если на мастере используется MySQL 5.x, а на слейве MySQL 8 – например, deprecated типы или charset. Такие случаи выходят за рамки инструкции, но решаемы (например, обновлением мастера или настройкой режимов совместимости). При штатной работе, SHOW SLAVE STATUS\G через некоторое время должен показывать Seconds_Behind_Master: 0 и оба потока Running: Yes. Это означает, что репликация настроена и слейв синхронизирован с мастером.
  • Ежедневное обновление данных: В отличие от файлового бэкапа, репликация MySQL может работать непрерывно, применяя изменения в режиме реального времени. Вы можете оставить слейв постоянно запущенным – тогда изменения будут поступать сразу после фиксации на мастере. Это даже более надёжно, т.к. в случае сбоя мастера у вас будет актуальная копия данных практически без отставания. Если же по каким-то причинам требуется обновлять данные раз в сутки (например, чтобы снизить нагрузку, хотя обычно реплика бездействует большую часть времени, если нет потока изменений), можно организовать следующий подход:
  • Оставлять слейв остановленным и запускать его синхронизацию по расписанию. Например, остановить после актуализации и на следующий день перед бэкапом снова запустить. Однако, это нетипичный подход. Проще и надёжнее – держать репликацию постоянно запущенной. Суточный объём изменений скорее всего не перегрузит ни сеть, ни диск.
  • Если решили запускать раз в сутки, можно в cron на слейве прописать START SLAVE в начале дня, а STOP SLAVE после окончания окна. Но убедитесь, что за отведённое время слейв успевает применить все накопившиеся изменения. Такой режим сложнее мониторить и потенциально опаснее (можно забыть включить). Рекомендация: Держите репликацию постоянно включённой. Это обеспечит минимум потерь данных и всегда актуальную резервную копию. Суточное окно не даёт выигрыша, зато рискуете отставанием.
  • Проверка резервных баз на слейве: После успешной настройки репликации на слейве в MySQL вы увидите все базы с префиксом BackUp_.... Они должны содержать идентичные данные, что на мастере (с небольшим запаздыванием, если данные меняются постоянно). Можно выполнить на слейве выборку из нескольких таблиц, чтобы убедиться. Важно: Не вносите изменения на слейве вручную в эти базы – это нарушит репликацию. Базы BackUp_* должны считаться read-only копиями. В MySQL 8 можно настроить слейв как super_read_only=ON для безопасности (это предотвратит нежелательные записи).

2.3. Резервное копирование MySQL – итоги и дополнительные шаги:

Теперь на удалённом сервере Ubuntu у вас есть действующая копия всех нужных баз данных (с другим именем). Ежедневно (или постоянно) она обновляется только за счёт изменений – экономно по сети и оперативно.

Несколько моментов для завершающей настройки и обслуживания:

  • Автостарт репликации: Убедитесь, что при перезапуске MySQL на слейве он автоматически начинает репликацию. Обычно, если CHANGE MASTER TO выполнен и START SLAVE выполнен хотя бы раз, эти настройки сохраняются. Проверить можно, перезапустив MySQL на Ubuntu и посмотрев SHOW SLAVE STATUS – если Slave_IO_Running и Slave_SQL_Running снова Yes, значит всё хорошо. Если нет – возможно, нужно добавить START SLAVE в init-скрипт или как систематическое задание. Но обычно не требуется.
  • Мониторинг репликации: Настройте оповещения или хотя бы периодически проверяйте, что Seconds_Behind_Master не растёт постоянно. В идеале = 0. Если, например, репликация остановится (по ошибке или из-за потери соединения), важно это обнаружить и исправить. Можно написать скрипт, который раз в день проверяет статус и отсылает e-mail при проблемах. Либо использовать готовые инструменты мониторинга (Zabbix, PMM от Percona, etc.), если они есть.
  • Purge старых бинарных логов на мастере: В оригинальном скрипте присутствовала строка:
  mysql -e 'PURGE MASTER LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);'

Это очищало бинарные логи старше 7 дней на мастере. Мы также в конфиге задали expire_logs_days или binlog_expire_logs_seconds. Очень важно: не удалять логи, которые ещё не применены на слейве! Обычно, если слейв в режиме реального времени, 7 дней – с запасом (он сразу применяет и не отстаёт на недели). Но если слейв отстал, а логи на мастере удалились – слейв не сможет догнать (придётся заново копировать базу). Поэтому:

  • Регулярно проверяйте, что слейв не отстаёт больше чем на период, по истечении которого логи удаляются.
  • Лучше настроить expire_logs_days=7 (или соотв. опцию) на мастере, чтобы он сам чистил. Если хотите вручную, можно оставить команду purge в скрипте бэкапа файлов (после того, как убедились, что репликация в порядке). Но предпочтительнее – автоматическое управление через config, чтобы не зависеть от выполнения скрипта.
  • Резервное копирование самих данных слейва (вторичный бэкап): Имейте в виду, что теперь резервные копии баз данных существуют в виде копий на слейве. Можно рассмотреть дополнительный уровень бэкапа – например, снимать дамп BackUp_* баз раз в неделю в файлы, или делать снимок (snapshot) диска, на котором лежит база на Ubuntu. Это как страховка на случай, если на обоих серверах случится серьёзная проблема. Однако, учитывая, что мы уже скопировали на отдельную машину, это не первоочередная задача. Тем не менее, не лишним будет сохранять хотя бы раз в неделю полный дамп всех BackUp_ баз на удалённый носитель или облачное хранилище (off-site backup). Например, можно на Ubuntu настроить cron с mysqldump --single-transaction --all-databases (или перебором BackUp_ баз) в файлы + сжатие, чтобы иметь долгосрочный архив.
  • Тестирование восстановления: Любой план резервного копирования бесполезен, если вы не уверены, что из бэкапов можно восстановиться. Поэтому:
  • Периодически тестируйте восстановление файлов: смонтируйте резервный снимок (можно прямо на Ubuntu, так как это обычные файлы) и попытайтесь развернуть какой-либо сервис или открыть файлы, убедитесь в их целостности.
  • Тестируйте восстановление баз: можно развернуть временную копию базы из BackUp_ – например, на том же слейве копировать BackUp_mydb в restore_test_mydb (через mysqldump и загрузку, либо clone если MySQL8 поддерживает). Это чтобы убедиться, что данные не повреждены и репликация корректно отрабатывает.
  • Обслуживание: Со временем, вы будете иметь на диске много каталогов с ежедневными бэкапами файлов. Поскольку мы используем инкремент с жесткими ссылками, удалять старые копии нужно аккуратно: удаляйте целиком старый каталог датой. Это безопасно удалит файлы, которых нет в более новых снимках (потому что ссылок больше не останется). Новые каталоги останутся нетронутыми. Можно автоматизировать, например, удаление бэкапов старше N дней. Пример для cron (удалять каталоги старше 30 дней):
  find /backup/RSYNC -maxdepth 1 -type d -name "20*" -mtime +30 -exec rm -rf {} \;

(Будьте очень осторожны с этой командой, протестируйте без -exec rm сначала!). Она пройдётся по каталогам вида 20XX-YY-ZZ и удалит старые.

Сами базы BackUp_ на слейве хранят весь актуальный объем данных, очистка у них не требуется кроме стандартной оптимизации (проверяйте, хватает ли места, растут ли файловые логи, etc.). Они постоянно перезаписываются свежими изменениями.


3. Дополнительные улучшения (опционально)

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

  • Отправка отчётов об изменениях по почте: В оригинальном скрипте были примечания о формировании файла different.txt с перечнем различий (через diff -r) между текущим состоянием и последним бэкапом, и отправке этого списка на e-mail. Это может быть полезно, чтобы иметь ежедневный отчёт, какие файлы изменялись. Однако, сравнение больших директорий командой diff -r может быть ресурсоёмким. Альтернатива – использовать лог rsync (он уже показывает изменённые файлы). Если нужна более наглядная сводка, можно:
  • В скрипте после rsync добавить: rsync -av --dry-run --delete --exclude-from="$RSYNC_EXCLUDE_FILE" \ "$SOURCE_DIR" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_BASE_DIR}/last/" > /tmp/changes.txt с опцией --dry-run и направлением вывода в файл. Это смоделирует синхронизацию между источником и последней копией (которая была после обновления last), выводя список отличий (файлы на удаление, добавление, обновление). Этот список можно отформатировать и отправить на e-mail через sendmail или mailx.
    Либо использовать утилиты, как rdiff-backup (но мы остаёмся на rsync, чтобы не вносить новые зависимости).
  • Логирование и ротация логов: Файл /var/log/backup_files.log будет расти. Имеет смысл настроить его ротацию (logrotate) или ежемесячно обнулять/архивировать. В логах храните хотя бы пару недель для отладки.
  • Безопасность: Так как бэкап затрагивает конфиденциальные данные, убедитесь, что доступы по SSH ограничены (например, по IP, через файрвол), а пользователь replicator на MySQL имеет доступ только из нужного хоста. Также можно настроить шифрование потока репликации (MySQL 5.7+/8.0 позволяют репликацию по SSL). Если данные чувствительные, рассмотрите эти меры.
  • Обновление ПО: CentOS 6 – устаревшая система, MySQL на ней, вероятно, старый. Планируйте обновление или миграцию на более новый ОС/MySQL. Текущее решение способно облегчить миграцию – вы уже скопировали данные на Ubuntu. При необходимости можно поменять роли (сделать Ubuntu основным сервером), но это выходит за рамки данной инструкции.

4. Заключение

Мы разработали решение, обеспечивающее сохранение 240 ГБ данных с минимальной нагрузкой на сеть и хранение. Инкрементальные бэкапы файлов позволяют иметь историю изменений по дням, быстро восстанавливать как отдельные файлы, так и всю систему на конкретную дату. Репликация баз данных обеспечивает актуальную копию данных с точностью до транзакции, избавляя от необходимости ежедневного переноса огромных SQL-дампов – вместо этого передаются только изменения.

Следуя данной инструкции, вы настроите надёжный процесс резервного копирования. Всегда документируйте изменения, держите пароли (SSH, MySQL) в безопасном месте. Регулярно проверяйте, что резервные копии действительно создаются и пригодны для восстановления:

  • Автоматизация хороша, но контроль качества бэкапа ещё важнее. Хотя бы раз в неделю просматривайте логи rsync на наличие ошибок (они будут в /var/log/backup_files.log), а статус репликации MySQL – на предмет отставания или остановок.
  • Периодически устраивайте тест восстановления (например, восстановите один файл из вчерашнего бэкапа, или поднимите копию базы из BackUp_ на отдельном порту) – это лучшая проверка, что в случае ЧП вы будете готовы.

Данный подход обеспечивает баланс между сохранением истории, использованием дискового пространства и скоростью резервирования. Он построен на проверенных средствах (rsync, mysqldump/репликация) и не требует сложного ПО бэкапа. В то же время, мы уделили внимание всем важным деталям: фильтрации ненужных данных, сохранению прав, очистке старых логов, мониторингу.

Следуя этим рекомендациям, вы получите профессионально настроенную систему бэкапов, которая защитит вашу инфраструктуру и данные от потери, а также облегчит администрирование благодаря автоматизации и понятности структуры.

Разработка и продвижение сайтов webseed.ru
Прокрутить вверх