Если база данных — сердце вашего проекта, репликация на малом VDS — это страховка, производительность и контроль RPO/RTO. Разберём, как настроить репликацию MySQL/MariaDB с GTID и semi‑sync, подобрать параметры binlog и безопасно переключать роли (switchover) без потерь.
Зачем репликация на малом VDS и чего ожидать
Даже на маленьком инстансе репликация даёт три ощутимые выгоды: горячая копия для аварий, разгрузка чтения (реплика под отчёты/аналитику) и безопасное окно для обновлений. Цена — записи в binlog
, небольшой overhead фиксации транзакций и RAM под метаданные.
Цель: RPO → 0 и RTO в пределах 1–5 минут. GTID упрощает переключения, semi‑sync снижает риск потери коммитов при падении ведущего.
Топология и ограничения малого VDS
Базовая схема: один primary и одна реплика. На малом VDS критичны экономные настройки I/O и памяти. Начинайте с двух узлов в одной зоне доступности, затем по необходимости добавляйте третью реплику только для чтения. Держите узлы ближе — задержки бьют по semi‑sync.
Если выбираете конфигурацию железа под БД, ориентируйтесь на CPU/IOPS/RAM и рабочий набор данных. Полезно свериться с материалом о подборе ресурсов VDS: как выбрать план по CPU и RAM.
MySQL 8.0: включаем GTID и готовим к replication
Для MySQL 8.0 GTID — стандарт де‑факто. Он позволяет включить автопозиционирование (SOURCE_AUTO_POSITION=1
) и забыть о ручном управлении позициями binlog.
Минимальный my.cnf для малого VDS (MySQL 8.0)
[mysqld]
server_id = 101
log_bin = mysql-bin
binlog_format = ROW
binlog_row_image = FULL
binlog_expire_logs_seconds = 604800
relay_log = relay-bin
skip_name_resolve = ON
# GTID и репликация
gtid_mode = ON
enforce_gtid_consistency = ON
log_slave_updates = ON
read_only = ON
super_read_only = ON
# Долговечность и предсказуемость
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
# Память и лимиты для маленького VDS
innodb_buffer_pool_size = 512M
max_connections = 100
table_open_cache = 400
thread_cache_size = 50
performance_schema = ON
performance_schema_consumer_events_statements_history = OFF
# Устойчивость репликации
relay_log_recovery = ON
sync_relay_log = 1
sync_relay_log_info = 1
sync_master_info = 1
innodb_flush_log_at_trx_commit=1
и sync_binlog=1
минимизируют риск потерь (ценой TPS на медленном диске). Если есть semi‑sync и TPS критичен, допустим sync_binlog=0
как компромисс — но осознанно.
Пользователь для репликации
CREATE USER 'repl'@'10.0.%' IDENTIFIED BY 'S3cureP4ss!';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'10.0.%';
FLUSH PRIVILEGES;
Ограничьте доступ по сети/подсети и включайте TLS на канале репликации. Для этого используйте валидные SSL-сертификаты и шифрованные соединения между узлами.
Начальная загрузка данных
Для InnoDB используйте «горячий» дамп в рамках одной транзакции. Для GTID включите экспорт GTID:
mysqldump --single-transaction --set-gtid-purged=ON --triggers --routines --events \
--databases appdb > dump.sql
Восстановите дамп на реплике и не подключайте к ней приложение, пока не запустите репликацию.
Подключение реплики с GTID
MySQL 8.0 поддерживает новый синтаксис (SOURCE/REPLICA
) и старый (MASTER/SLAVE
), используйте подходящий для вашей версии.
-- Новый синтаксис (8.0.26+)
CHANGE REPLICATION SOURCE TO
SOURCE_HOST='10.0.0.10', SOURCE_PORT=3306,
SOURCE_USER='repl', SOURCE_PASSWORD='S3cureP4ss!',
SOURCE_AUTO_POSITION = 1,
GET_SOURCE_PUBLIC_KEY = 1;
START REPLICA;
-- Старый синтаксис
CHANGE MASTER TO
MASTER_HOST='10.0.0.10', MASTER_PORT=3306,
MASTER_USER='repl', MASTER_PASSWORD='S3cureP4ss!',
MASTER_AUTO_POSITION = 1,
GET_MASTER_PUBLIC_KEY = 1;
START SLAVE;
Проверка статуса:
SHOW REPLICA STATUS\G
-- или
SHOW SLAVE STATUS\G
Должны работать I/O и SQL потоки, задержка — секунды, ошибок нет. Формат ROW
избегает недетерминизма функций.

MariaDB: отличия GTID и настройка
В MariaDB GTID реализован с domain_id
и строгим режимом. Автопозиционирование поддерживается, но синтаксис другой.
Конфигурация MariaDB 10.6+
[mariadb]
server_id = 201
log_bin = mariadb-bin
binlog_format = ROW
binlog_row_image = FULL
expire_logs_days = 7
relay_log = relay-bin
skip_name_resolve = ON
# GTID
gtid_domain_id = 10
gtid_strict_mode = ON
log_slave_updates = ON
read_only = ON
# Надёжность
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
# Малый VDS
innodb_buffer_pool_size = 512M
max_connections = 100
table_open_cache = 400
thread_cache_size = 50
# Репликация
relay_log_recovery = ON
sync_relay_log = 1
sync_relay_log_info = 1
sync_master_info = 1
Инициализация и подключение в MariaDB
Сделайте консистентный дамп (аналогично MySQL). Для подключения укажите использование GTID:
CHANGE MASTER TO
MASTER_HOST='10.0.0.10', MASTER_PORT=3306,
MASTER_USER='repl', MASTER_PASSWORD='S3cureP4ss!',
MASTER_USE_GTID=slave_pos;
START SLAVE;
Проверьте SHOW SLAVE STATUS\G
: задержка, ошибки, отставание по GTID.
Полусинхронная репликация (semi‑sync): меньше потерь при авариях
Асинхронная репликация подтверждает коммит клиенту сразу после фиксации на ведущем — реплика может отставать. Semi‑sync ждёт ACK хотя бы от одной реплики (запись в relay‑log/журнал), что повышает шанс RPO=0 при фейловере.
Включение semi‑sync в MySQL 8.0
-- На ведущем
INSTALL PLUGIN rpl_semi_sync_source SONAME 'semisync_source.so';
SET GLOBAL rpl_semi_sync_source_enabled = ON;
SET GLOBAL rpl_semi_sync_source_timeout = 1000; -- мс ожидания ACK
SET GLOBAL rpl_semi_sync_source_wait_for_slave_count = 1;
SET PERSIST rpl_semi_sync_source_enabled = ON;
-- На реплике
INSTALL PLUGIN rpl_semi_sync_replica SONAME 'semisync_replica.so';
SET GLOBAL rpl_semi_sync_replica_enabled = ON;
SET PERSIST rpl_semi_sync_replica_enabled = ON;
В старых релизах используются плагины/переменные rpl_semi_sync_master
/rpl_semi_sync_slave
.
Включение semi‑sync в MariaDB
-- На ведущем
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = ON;
SET GLOBAL rpl_semi_sync_master_timeout = 1000;
-- На реплике
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled = ON;
Статус:
SHOW STATUS LIKE 'Rpl_semi_sync%';
Важно: при недоступности реплик semi‑sync откатывается в async — мониторьте метрики и настраивайте алерты.
Безопасный switchover (переключение роли) с GTID
Switchover — плановая замена ведущего без потерь. При GTID и semi‑sync это делается быстро и предсказуемо.
Предварительная проверка
- Реплика здорова: нет ошибок в
SHOW REPLICA/SLAVE STATUS
, задержка минимальна. - На ведущем
read_only=OFF
, на репликеread_only=ON
,super_read_only=ON
. - semi‑sync (если включён) активен, задержки сети стабильны.
Пошаговая процедура (MySQL)
- Замораживаем запись на текущем ведущем:
-- На ведущем SET GLOBAL super_read_only = ON; SET GLOBAL read_only = ON; -- (опционально) SET GLOBAL event_scheduler = OFF;
- Ждём догон по GTID. На реплике дожидаемся выполнения всех GTID ведущего:
Если вернулся 0 — реплика синхронизирована. Если -1 — истёк таймаут, разберитесь с долгими транзакциями.-- На ведущем SELECT @@GLOBAL.gtid_executed \G -- Скопируйте значение и выполните на реплике: SELECT WAIT_FOR_EXECUTED_GTID_SET('gtid_set_с_ведущего', 30);
- Останавливаем репликацию на кандидате (будущем ведущем):
-- На реплике STOP REPLICA; -- или STOP SLAVE;
- Делаем реплику ведущей:
-- На реплике (новом ведущем) SET GLOBAL super_read_only = OFF; SET GLOBAL read_only = OFF;
- Подключаем старого ведущего как реплику к новому ведущему:
-- На старом ведущем CHANGE REPLICATION SOURCE TO SOURCE_HOST='IP_нового_ведущего', SOURCE_PORT=3306, SOURCE_USER='repl', SOURCE_PASSWORD='S3cureP4ss!', SOURCE_AUTO_POSITION = 1, GET_SOURCE_PUBLIC_KEY = 1; START REPLICA; -- или START SLAVE;
- Возвращаем события/джобы, если отключали:
-- На новом ведущем SET GLOBAL event_scheduler = ON; -- если используется
- Переключаем приложение на новый ведущий (DNS/конфиг/виртуальный IP). Проверьте записи и задержку.
Для MariaDB логика аналогична. Вместо WAIT_FOR_EXECUTED_GTID_SET
используйте сравнение GTID‑позиций или дождитесь Seconds_Behind_Master=0
, затем остановите SQL‑поток и снимите read_only
.
Если что-то пошло не так
- WAIT вернул -1: ищите долгие транзакции (
SHOW PROCESSLIST
,sys.schema_table_lock_waits
), дождитесь или отмените по регламенту. - Реплика отстаёт по I/O: проверьте сеть,
relay_log
, I/O квоты диска,innodb_io_capacity
. - Ошибки DDL после промоушена: убедитесь, что
binlog_format=ROW
, триггеры/события не пишут в недоступные базы.
Failover (аварийное переключение): краткие заметки
При падении ведущего и включённом semi‑sync новая ведущая, как правило, имеет все зафиксированные транзакции. Проверьте целостность, снимите read_only
, переведите трафик. Старый ведущий поднимайте как реплику через GTID‑автопозиционирование. Избегайте split‑brain: используйте единый IP/маршрутизатор включений или строгий ручной регламент.
Тюнинг репликации и БД для малого VDS
- Память:
innodb_buffer_pool_size
50–70% RAM;max_connections
по факту нагрузки; следите заtable_open_cache
иthread_cache_size
. - Долговечность:
innodb_flush_log_at_trx_commit=1
,sync_binlog=1
для RPO≈0. При упоре в диск — батч‑записи, пулы соединений, уменьшение чата запросов. - Binlog:
ROW
,binlog_row_image=FULL
(илиMINIMAL
при понимании рисков);binlog_expire_logs_seconds
3–7 дней. - Репликация:
relay_log_recovery=ON
,sync_*_info=1
; на репликах держитеread_only=ON
иsuper_read_only=ON
. - Сеть: включите TCP keepalive на уровне ОС; на высокой задержке semi‑sync может снижать TPS — настройте
rpl_semi_sync_*_timeout
. - Диагностика:
slow_query_log=ON
, анализируйте отчёты Performance Schema; резервное копирование проверьте на стенде и автоматизируйте. Подробно о S3‑бэкапах: руководство по бэкапам.
Проверка и мониторинг
- Репликация:
SHOW REPLICA/SLAVE STATUS\G
,Seconds_Behind_*
, ошибки SQL/I/O потоков. - semi‑sync:
SHOW STATUS LIKE 'Rpl_semi_sync%'
, алерт при откате в async. - GTID: сравнивайте
@@GLOBAL.gtid_executed
/@@GLOBAL.gtid_purged
(MySQL) или позиции (MariaDB). - Диск: IOPS/latency, заполнение binlog/relay‑log, ротация логов.
Типичные ошибки
- Смешивание MySQL и MariaDB в одном контуре — не поддерживается.
- Отключённый
log_slave_updates
ломает цепочку GTID при будущих переключениях. STATEMENT
илиMIXED
формат binlog — риск дрейфа данных.- Слишком широкие права пользователя репликации (
%
без сетевых ограничений) — риск безопасности. - Отключённый
relay_log_recovery
— шанс поломки после крэша узла. - Switchover без
super_read_only
на старом ведущем — риск split‑brain.
Чек‑лист перед продом
- GTID включён на обоих узлах,
log_slave_updates=ON
,ROW
формат binlog. - semi‑sync протестирован под реальной сетевой задержкой, таймауты подобраны.
- Бэкапы и восстановление проверены на отдельной среде.
- Процедура switchover документирована и отрепетирована.
- Мониторинг репликации, binlog и диска настроен, алерты валидированы.
Итоги
Даже на малом VDS можно построить надёжную репликацию MySQL/MariaDB с GTID и semi‑sync, добиться RPO≈0 и быстро делать switchover/failover. Ключ — аккуратная настройка binlog, дисциплина процедур и постоянный мониторинг. Для миграции с минимальным простоем полезно посмотреть: переезд без простоя. Тестируйте на стенде, учитывайте задержки сети и характеристики диска — и база переживёт плановые релизы и внезапные аварии.