Горячий бэкап MySQL с Percona XtraBackup
В отличие от mysqldump, Percona XtraBackup создаёт резервные копии InnoDB без блокировки таблиц и остановки сервера. Незаменим для баз данных от 10 ГБ.
Установка XtraBackup
# Для Ubuntu/Debian (MySQL 8.0)
wget https://repo.percona.com/apt/percona-release_latest.generic_all.deb
dpkg -i percona-release_latest.generic_all.deb
percona-release setup pdps-80
apt update && apt install percona-xtrabackup-80Полный бэкап
# Создание полного бэкапа
xtrabackup --backup \
--user=root \
--password='YourPass' \
--target-dir=/backup/full
# Подготовка бэкапа к восстановлению
xtrabackup --prepare --target-dir=/backup/fullИнкрементальный бэкап
# Инкрементальный бэкап на основе полного
xtrabackup --backup \
--user=root \
--password='YourPass' \
--target-dir=/backup/inc1 \
--incremental-basedir=/backup/full
# Подготовка: сначала базовый, потом инкрементальный
xtrabackup --prepare --apply-log-only --target-dir=/backup/full
xtrabackup --prepare --apply-log-only \
--target-dir=/backup/full \
--incremental-dir=/backup/inc1
# Финальная подготовка
xtrabackup --prepare --target-dir=/backup/fullВосстановление из бэкапа
# Остановить MySQL
systemctl stop mysql
# Очистить datadir
rm -rf /var/lib/mysql/*
# Скопировать данные
xtrabackup --copy-back --target-dir=/backup/full
# Установить права
chown -R mysql:mysql /var/lib/mysql
# Запустить MySQL
systemctl start mysqlАвтоматизация через cron
#!/bin/bash
# /etc/cron.d/xtrabackup — каждое воскресенье полный, остальные дни инкремент
DATE=$(date +%Y%m%d)
BACKUP_DIR=/backup
if [ $(date +%u) -eq 7 ]; then
# Полный бэкап
xtrabackup --backup --user=root --password='Pass' \
--target-dir=$BACKUP_DIR/full_$DATE
else
# Инкрементальный
LAST_FULL=$(ls -td $BACKUP_DIR/full_* | head -1)
xtrabackup --backup --user=root --password='Pass' \
--target-dir=$BACKUP_DIR/inc_$DATE \
--incremental-basedir=$LAST_FULL
fi--compress и шифруйте с --encrypt=AES256 перед передачей на удалённое хранилище.Типичные ошибки XtraBackup
| Ошибка | Причина | Решение |
|---|---|---|
| Failed to connect to MySQL server: Access denied for user | У пользователя нет прав RELOAD, PROCESS, LOCK TABLES, REPLICATION CLIENT | Выдать GRANT RELOAD, PROCESS, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'backup_user'@'localhost'; |
| innodb_log_file_size in backup config differs from server | При --prepare сервер сравнивает размер лога бэкапа с текущим my.cnf | Не менять innodb_log_file_size между бэкапом и восстановлением, либо готовить бэкап с явным указанием параметра |
| PXB will not copy .frm files for non-InnoDB tables | В базе есть таблицы MyISAM, которые XtraBackup копирует иначе (не потоково, с кратковременной блокировкой) | Учитывать при расчёте времени бэкапа смешанных баз, см. разницу движков ниже |
Почему XtraBackup не блокирует InnoDB, но блокирует MyISAM
XtraBackup копирует файлы InnoDB напрямую с диска, одновременно читая redo log, и в конце «дописывает» изменения, накопленные во время копирования — таблицы остаются доступны на запись всё время бэкапа. Для таблиц MyISAM (и других не-InnoDB движков) такого журнала нет, поэтому XtraBackup берёт FLUSH TABLES WITH READ LOCK на короткое время в конце процесса, чтобы скопировать их консистентно. На базах, где почти все таблицы — InnoDB, эта блокировка длится секунды; если в базе много крупных таблиц MyISAM, блокировка может быть заметна приложению.
Когда XtraBackup не подходит
Для баз меньше нескольких гигабайт разница в производительности с обычным mysqldump непринципиальна, а mysqldump проще восстанавливать частично — на уровне отдельных таблиц или строк, чего XtraBackup не умеет: он всегда восстанавливает весь каталог данных целиком. XtraBackup также требует, чтобы версия сервера и версия утилиты были совместимы (Percona поддерживает соответствие major-версиям MySQL/MariaDB) — при обновлении сервера нужно проверить, что установленный percona-xtrabackup поддерживает новую версию, иначе --prepare завершится ошибкой.
Проверка целостности бэкапа после восстановления
# Убедиться, что сервер поднялся и видит все базы
mysql -u root -p -e "SHOW DATABASES;"
# Сверить количество таблиц с исходным сервером
mysql -u root -p -e "
SELECT table_schema, COUNT(*) AS tables
FROM information_schema.tables
GROUP BY table_schema;"
# Проверить состояние InnoDB после восстановления — не должно быть recovery-предупреждений
SHOW ENGINE INNODB STATUS\G
# Прогнать контрольный запрос с ожидаемым количеством строк
mysql -u root -p mydb -e "SELECT COUNT(*) FROM orders;"Сравнение количества строк и таблиц с показателями до бэкапа — обязательный шаг, а не формальность: XtraBackup молча завершится с кодом 0, даже если один из файлов скопировался не полностью из-за обрыва диска, и это выяснится только при первом обращении к повреждённой таблице. Логическую альтернативу с построчным дампом описывает статья про mysqldump и восстановление, а про перенос изменений после полного бэкапа — статья про восстановление на момент времени через binlog.