Перенести базу данных MySQL на другой сервер без простоя — задача с несколькими правильными решениями. Какое из них подходит, зависит от объёма базы и допустимого downtime: для базы в 2 ГБ хватит mysqldump за 10 минут, для продакшн-проекта на 100 ГБ нужна репликация master–slave или Percona XtraBackup. В этом руководстве — все три метода с реальными командами, разбором ошибок и чеклистом на финале.
Почему «просто скопировать файлы» не работает
Распространённая ошибка при переезде на новый сервер — скопировать директорию /var/lib/mysql/ через rsync или scp, пока MySQL запущен. Результат — повреждённая база или silent data corruption, который обнаружится не сразу, а через несколько дней в виде битых записей. Для тех, кто переезжает с виртуального хостинга, есть отдельное руководство: как перенести сайт на VPS пошагово.
Что будет с InnoDB при «горячем» копировании
InnoDB держит в памяти буфер пула (InnoDB buffer pool), redo log и незафиксированные транзакции. Файлы .ibd на диске в любой момент могут быть в промежуточном состоянии — страницы записаны частично, WAL-лог не применён. Когда вы копируете такие файлы и запускаете MySQL на новом сервере, движок начинает recovery и обнаруживает несоответствие — база либо не стартует, либо стартует с потерей данных.
Когда допустима остановка сервиса
Если база используется для разработки или на тестовом стенде — остановить MySQL, скопировать /var/lib/mysql/, запустить на новом сервере. Быстро и без риска при условии совпадения версий MySQL.
Для продакшн-проекта с SLA остановка неприемлема. Здесь нужен один из методов ниже: mysqldump с --single-transaction, репликация или XtraBackup.
Метод 1. mysqldump — надёжно для баз до 10 ГБ
mysqldump создаёт логический дамп: SQL-файл с командами CREATE TABLE и INSERT, который воспроизводит структуру и данные на любом сервере. Плюсы — кросс-версионность и простота. Минус — при импорте больших баз MySQL построчно выполняет INSERT’ы, что на 50 ГБ займёт несколько часов. Полная официальная документация mysqldump — на сайте MySQL.
Дамп с минимальной блокировкой (—single-transaction)
mysqldump -u root -p \
--single-transaction \
--routines \
--triggers \
--events \
--hex-blob \
имя_базы > /tmp/backup.sql
Что делает каждый ключ:
- —single-transaction — открывает транзакцию с изоляцией REPEATABLE READ, снимает консистентный снимок без блокировки таблиц. Работает только для InnoDB. Для MyISAM нужен
--lock-tables. - —routines — включает хранимые процедуры и функции
- —triggers — включает триггеры (без этого ключа они не попадут в дамп)
- —events — включает запланированные события
- —hex-blob — BLOB-поля в hex-формате, защита от проблем с кодировкой
Передача дампа на новый сервер
Вариант 1 — scp для небольших файлов:
scp /tmp/backup.sql user@new-server:/tmp/
Вариант 2 — пайп через SSH без промежуточного файла. Экономит дисковое место и ускоряет перенос больших дампов:
mysqldump -u root -p --single-transaction \
--routines --triggers имя_базы \
| gzip | ssh user@new-server "gunzip | mysql -u root -p имя_базы"
На новом сервере база должна быть создана заранее: CREATE DATABASE имя_базы CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Восстановление и проверка целостности
# Импорт дампа
mysql -u root -p имя_базы < /tmp/backup.sql
# Проверка всех таблиц
mysqlcheck -u root -p --all-databases
# Контрольные проверки после импорта
mysql -u root -p -e "SHOW TABLE STATUS FROM имя_базы;"
mysql -u root -p -e "SELECT COUNT(*) FROM имя_базы.важная_таблица;"
Метод 2. Репликация master–slave — миграция без остановки для больших баз

Для баз объёмом более 10 ГБ или проектов с требованием к минимальному downtime — репликация. Схема: новый сервер становится slave и догоняет master в реальном времени. Когда Seconds_Behind_Master = 0, переключаем приложение. Суммарный downtime — 30–120 секунд.
Подготовка master: binary log и пользователь репликации
# /etc/mysql/mysql.conf.d/mysqld.cnf (или my.cnf) — добавить в [mysqld]
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = имя_базы
expire_logs_days = 7
После изменения конфига — systemctl restart mysql. Затем создаём пользователя репликации:
CREATE USER 'repl'@'IP_SLAVE' IDENTIFIED BY 'сложный_пароль';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'IP_SLAVE';
FLUSH PRIVILEGES;
Снятие консистентного дампа с позицией binlog
mysqldump -u root -p \
--single-transaction \
--master-data=2 \
--routines --triggers \
имя_базы > /tmp/master_dump.sql
Флаг --master-data=2 добавляет в начало дампа закомментированную строку CHANGE MASTER TO с координатами binlog — файлом и позицией в момент снятия дампа. Это ключевой момент: slave будет реплицировать с этой точки, не пропуская и не дублируя транзакции.
Настройка slave и запуск репликации
На новом сервере — отдельный server-id в конфиге, затем импортируем дамп и настраиваем репликацию:
# Импорт дампа на slave
mysql -u root -p имя_базы < /tmp/master_dump.sql
# Настройка репликации (координаты берём из начала master_dump.sql)
CHANGE MASTER TO
MASTER_HOST='IP_MASTER',
MASTER_USER='repl',
MASTER_PASSWORD='сложный_пароль',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=12345;
START SLAVE;
SHOW SLAVE STATUS\G
В выводе SHOW SLAVE STATUS смотрим три поля: Slave_IO_Running: Yes, Slave_SQL_Running: Yes и Seconds_Behind_Master. Последнее должно уменьшаться — slave догоняет master. Когда достигнет 0 — можно переключать.
Переключение приложения — момент X
Когда Seconds_Behind_Master = 0:
- Включить режим обслуживания в приложении (или переключить DNS на время)
- Выполнить на новом сервере:
STOP SLAVE; - Сменить строку подключения к БД в конфиге приложения на IP нового сервера
- Выключить режим обслуживания, проверить работу
Оставьте старый сервер в режиме standby ещё сутки — на случай если понадобится откат.
Метод 3. Percona XtraBackup — горячий физический бэкап для InnoDB
XtraBackup делает физическую копию файлов InnoDB без остановки MySQL и без блокировки таблиц. Главное преимущество перед mysqldump: восстановление базы 100 ГБ занимает 15–20 минут против 2–4 часов при импорте SQL-дампа — потому что файлы просто копируются, а не воспроизводятся INSERT'ами. Подробности — в документации Percona XtraBackup.
Установка и создание бэкапа
# Установка на Debian/Ubuntu
apt install percona-xtrabackup-80
# Создание бэкапа
xtrabackup --backup \
--user=root \
--password=пароль \
--target-dir=/tmp/xtrabackup/
# Подготовка (применяет redo log, делает файлы консистентными)
xtrabackup --prepare --target-dir=/tmp/xtrabackup/
Этап --prepare обязателен: без него файлы бэкапа несогласованны — часть транзакций не применена. После prepare директория содержит консистентный снимок базы, готовый к копированию.
Восстановление на новом сервере
# Остановить MySQL на новом сервере
systemctl stop mysql
# Скопировать бэкап (директория /var/lib/mysql должна быть пустой или чистой)
rsync -avz --progress /tmp/xtrabackup/ user@new-server:/var/lib/mysql/
# На новом сервере: выставить права
ssh user@new-server "chown -R mysql:mysql /var/lib/mysql"
# Запустить MySQL
ssh user@new-server "systemctl start mysql"
XtraBackup работает только при совпадении мажорной версии MySQL — бэкап с 8.0 не восстановится на 5.7. Для кросс-версионной миграции — только mysqldump.
Сравнение методов — что выбрать

| Метод | Размер базы | Downtime | Сложность | Кросс-версионность |
|---|---|---|---|---|
| mysqldump | До 10 ГБ | Минуты–часы | Низкая | Да |
| Репликация master–slave | Любой | 30–120 сек | Средняя | Да (осторожно) |
| Percona XtraBackup | Более 10 ГБ InnoDB | Секунды | Средняя | Нет (та же версия) |
Частые ошибки при переносе MySQL
Разные версии MySQL — несовместимый формат
Дамп из MySQL 8.0 не всегда корректно импортируется в 5.7: в 8.0 появились зарезервированные слова (RANK, GROUPS, SYSTEM), которые в 5.7 воспринимаются как имена столбцов. Редакция рекомендует переносить на ту же или более новую версию. Если нужна кросс-версионная миграция — проверяйте дамп на тестовом стенде.
Кодировка: utf8 vs utf8mb4
Если на старом сервере база создана с utf8 (в MySQL это псевдоним для utf8mb3, не поддерживает emoji и некоторые китайские символы), а на новом — utf8mb4, данные импортируются, но COLLATION таблиц и столбцов может не совпасть. Проверить:
SHOW CREATE TABLE имя_таблицы\G
Если CHARSET=utf8 — при импорте на новый сервер принудительно указать нужную кодировку или сконвертировать таблицы после переноса через ALTER TABLE.
Забытые хранимые процедуры и триггеры
Вызов mysqldump без --routines --triggers не включает процедуры, функции и триггеры в дамп. Приложение после переноса работает, но теряет бизнес-логику, зашитую в БД. Проверить перед дампом:
SHOW PROCEDURE STATUS WHERE Db = 'имя_базы';
SHOW TRIGGERS FROM имя_базы;
Права доступа пользователей не переносятся автоматически
Таблица mysql.user не дампится при стандартном вызове с указанием конкретной базы. Права приложения на новом сервере нужно воссоздать вручную или дополнительно дампить системную базу:
# Экспорт прав всех пользователей (MySQL 8.0+)
mysqldump -u root -p mysql user db tables_priv > /tmp/users_grants.sql
# Или на старом сервере собрать GRANT-запросы вручную
SHOW GRANTS FOR 'пользователь'@'%';
Переключение DNS и проверка после переноса
После переключения приложения на новый сервер — стандартный набор проверок:
- Тестовые запросы к базе: операции чтения и записи
- Логи ошибок MySQL:
tail -f /var/log/mysql/error.log - Активные процессы:
SHOW PROCESSLIST;— нет ли висящих запросов - Если оставили репликацию активной — мониторинг
Seconds_Behind_Masterна случай отката - Мониторинг производительности:
SHOW STATUS LIKE 'Innodb_buffer_pool%';
После переноса базы следующий шаг — настройка окружения на сервере с нуля: читайте руководство как настроить VPS с нуля.
VPS для MySQL: что важно в характеристиках
RAM для MySQL важнее CPU: InnoDB buffer pool должен вмещать рабочий набор данных. Стандартная рекомендация — 50–70% оперативной памяти под buffer pool. При базе 20 ГБ нужно минимум 8–16 ГБ RAM.
По дискам: NVMe vs SATA SSD — разница принципиальная для write-heavy нагрузки. NVMe даёт 3–5 Гбайт/с последовательной записи против 500–600 Мбайт/с у SATA SSD. Для высоконагруженных баз с частыми UPDATE/INSERT — только NVMe. Подробный разбор: NVMe vs SSD для сервера.
Провайдеры с NVMe-дисками и подходящими конфигурациями для MySQL: Aeza и Selectel. Сравнить по гео, RAM и типу диска можно по фильтрам каталога VPS в России. Если нужны конкретные конфигурации — сравнить конфигурации в каталоге.
Ну и в заключение: чеклист переноса MySQL — 10 шагов
- Снять тестовый дамп заранее — убедиться, что mysqldump проходит без ошибок, на старом сервере ещё до начала переноса
- Зафиксировать версию MySQL на старом сервере:
mysql --version - Проверить наличие процедур и триггеров:
SHOW PROCEDURE STATUS,SHOW TRIGGERS - Выбрать метод по объёму базы и допустимому downtime (см. таблицу выше)
- Создать базу на новом сервере с нужной кодировкой (
utf8mb4) - Перенести данные выбранным методом
- Воссоздать права пользователей — не забыть про application user
- Проверить целостность:
mysqlcheck --all-databases, контрольные COUNT(*) - Включить режим обслуживания, переключить строку подключения в конфиге приложения
- Выключить режим обслуживания, проверить логи MySQL и логи приложения в течение 15–30 минут
Если старый сервер тормозит MySQL из-за нехватки RAM или SATA-дисков — в каталоге VPS-хостингов можно подобрать конфигурацию с NVMe и от 4 ГБ RAM под задачи баз данных. Там же — фильтр по локации и провайдеру.