Решение для инкрементального бэкапа с машины на 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).- Подготовка перед копированием:
- Сброс кэшей (
drop_caches). Это взято из оригинального скрипта – выполнениеsyncи очистки page cache. Данная команда не обязательна, но помогает освободить оперативную память, занятую кешированием дисковых операций. На системах с ограниченной памятью это может предотвратить влияние бэкапа на работу сервисов. - Очистка временных файлов. Здесь показан пример удаления файлов сессий в директории
/var/www/md/data/mod-tmp/(т.к. оригинальный скрипт чистилsess_*там). Вам следует настроить этот шаг под свою ситуацию: удалите временные файлы, кэши приложений, логи, если они не нужны в бэкапе, и т.п. Цель – уменьшить объём изменяющихся данных, чтобы инкрементальные копии были максимально эффективны и не хранили мусор. - Вычисление текущей даты
BACKUP_DATE– она используется для именования папки, куда сложатся файлы бэкапа за этот день. - Определение путей на удалённом сервере: переменная
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`;
-- и так далее для всех необходимых баз
Делать дамп с мастера можно двумя путями:
- Дамп оригинальной базы и последующая правка имени при импорте – сложнее, нужно править
CREATE DATABASEиUSEв .sql-файле. - Создать на мастере копию базы с новым именем и дампить её – требует скопировать данные на мастере, может быть накладно, если базы большие. Однако, мы можем упростить: поскольку у нас уже настроен бинлог, мы можем на слейве сначала импортировать оригинальные базы, а затем переименовать их на слейве. Но 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: YesSlave_SQL_Running: YesSeconds_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/репликация) и не требует сложного ПО бэкапа. В то же время, мы уделили внимание всем важным деталям: фильтрации ненужных данных, сохранению прав, очистке старых логов, мониторингу.
Следуя этим рекомендациям, вы получите профессионально настроенную систему бэкапов, которая защитит вашу инфраструктуру и данные от потери, а также облегчит администрирование благодаря автоматизации и понятности структуры.