Зачем вообще спорить: GTID vs classic в реальной эксплуатации
Репликация MySQL обычно нужна для конкретных задач: чтение с реплик, резерв на случай аварии, окна обслуживания, быстрый switchover, отчётность, тестовые стенды. И почти всегда в момент, когда реплика реально нужна, выясняется, что всё было настроено «как-нибудь»: мониторинга lag нет, реплика внезапно пишет локальные данные, а переключение превращается в ручной квест.
Выбор «GTID vs classic» в эксплуатации сводится к простому вопросу: насколько предсказуемо вы сможете пересоздать реплику, догнать мастер и переключиться под нагрузкой, когда время дорого. Classic (binlog file/position) проще концептуально, но требует дисциплины и ручных проверок. GTID добавляет удобство и автоматизацию, но вводит ограничения и типовые ошибки при миграциях и восстановлении.
Ниже — практичный разбор отличий и процедур: как жить с обоими режимами, как контролировать relay log и replication lag, где уместен semisync, и как делать switchover без потери данных.
Классическая репликация (binlog file/position): как работает и где ломается
Classic-репликация опирается на координаты источника: имя бинарного лога (binlog file) и позицию внутри него (position). Реплика получает события от источника, пишет их в relay log, затем применяет в своей базе.
Плюсы classic
- Понятная модель: «вот файл и позиция, оттуда читаем».
- Удобно для точечных разборок и работы с binlog по координатам.
- Нет GTID-ограничений: некоторые старые процедуры восстановления проще повторить один в один.
Минусы classic
- Switchover и пересоздание реплики требуют аккуратной фиксации координат, иначе легко получить пропуски/дубли.
- В каскадных схемах и при регулярных переключениях больше ручной рутины.
- Сложнее автоматизировать выбор «правильной точки» без внешних инструментов.
Самая частая проблема — человеческий фактор: бэкап сделали, а координаты не зафиксировали (или перепутали), развернули реплику, подключили — и только через сутки заметили расхождение.

GTID-репликация: что меняется
GTID (Global Transaction ID) — уникальный идентификатор транзакции вида UUID:sequence. В GTID-режиме реплика «знает», какие транзакции уже применены, и может догонять источник, ориентируясь на набор GTID, а не на конкретный файл/позицию.
Плюсы GTID
- Switchover проще: меньше ручной фиксации координат, меньше шансов ошибиться.
- Пересоздание реплики удобнее: важно корректно перенести данные и GTID-набор, а не ловить точную позицию.
- Проще поддерживать топологии с несколькими репликами и регулярными переключениями.
Минусы GTID (эксплуатационные)
- Нужна дисциплина в конфигурации:
gtid_mode,enforce_gtid_consistency, правильные настройки binlog. - Ошибки при восстановлении из бэкапа или переливе данных, если не учтён
gtid_purged. - Часть «небезопасных» практик из classic в GTID придётся заменять корректными процедурами.
Ключевые термины: relay log, replication lag и почему это не одно и то же
Relay log — локальная очередь событий на реплике. Источник пишет в binlog, реплика скачивает события в relay log, затем применяет. Очередь может расти из-за медленной сети/диска на чтении или из-за медленного применения транзакций SQL-потоком.
Replication lag — задержка реплики относительно источника. Обычно её смотрят по Seconds_Behind_Master (или аналогам в новых версиях), но важно понимать: это оценка, и в некоторых сценариях она может вводить в заблуждение.
Практическое правило: если реплики используются для чтения или как горячий резерв, мониторьте не только «секунды», но и состояние потоков, ошибки репликации и рост relay log (включая свободное место под него).
Semisync: когда он нужен и что он реально гарантирует
Semisync (полусинхронная репликация) — компромисс между async и полной синхронностью. Мастер подтверждает коммит клиенту только после того, как хотя бы одна реплика подтвердила получение события (как правило, запись в relay log), но не обязательно применение транзакции.
Что это даёт: снижает риск потерять последние транзакции при аварии мастера, но не убирает его полностью и обычно добавляет задержку записи. Важно отдельно мониторить, что semisync реально активен и не «свалился» в async.
Когда semisync уместен
- Один мастер и одна «почти горячая» реплика, хочется уменьшить RPO.
- Запись критична, а небольшая прибавка latency допустима.
- Есть мониторинг состояния semisync и понятные таймауты.
Когда semisync не спасёт
- Если реплика получила событие, но упала до применения транзакции.
- Если semisync выключился из-за таймаутов, а вы это не отловили алертами.
Отдельно и подробно разбор схем и ошибок переключения с semisync удобно держать в виде runbook: GTID, semisync и failover без потери данных.
read_only и super_read_only: защита от «случайной записи»
read_only и super_read_only — одна из самых недооценённых страховок при эксплуатации репликации. Они защищают от ситуации, когда на реплику случайно начинают писать (приложение, админская сессия, кривой балансировщик), после чего switchover становится опасным: реплика уже «не чистая» и расходится с мастером.
Базовая рекомендация для схемы «master → replica»: держать реплики в super_read_only=ON (если версия поддерживает) и открывать запись только на выбранном мастере. При переключении строго соблюдайте порядок: остановить запись на старом мастере, убедиться, что реплика догнала, промотировать реплику и только после этого открывать запись приложению.
GTID vs classic: что выбирать под ваши сценарии
Если у вас частые переключения и автоматизация
GTID обычно выигрывает: меньше ручных координат, проще логика «догнал/не догнал», проще пересоздавать реплики. Это особенно заметно, если реплик несколько и вы делаете плановые switchover для обновлений ОС/СУБД.
Если инфраструктура простая, а переключения редкие
Classic жизнеспособен, если есть железная дисциплина: бэкапы с координатами, процедуры восстановления, тестовые переключения хотя бы раз в квартал. Но как только начинается активная жизнь (миграции, частые релизы, изменения схемы, разные окружения) — GTID окупается быстрее.
Если важны разборы инцидентов и работа с binlog
Оба режима позволяют анализировать binlog. Classic привычнее по «файл/позиция», GTID даёт другой «якорь» — набор применённых транзакций. Для задач точечного восстановления (PITR) полезно держать отдельный материал и чеклист: PITR из binlog: координаты и GTID без ловушек.
Пошаговый план безопасного switchover (логика, а не магия)
Алгоритм ниже одинаково важен и для GTID, и для classic. Отличаются детали подключения репликации, но логика «остановили запись → догнали → промотировали → переподключили» почти всегда одна.
1) Подготовка: убедиться, что реплика пригодна
- Нет ошибок репликации (IO и SQL-потоки в норме).
- Lag контролируемый и объяснимый.
- На реплике включён
super_read_only, нет локальных записей. - Relay log не растёт бесконечно, диск не на грани заполнения.
2) Остановить запись на старом мастере
Идеально — на уровне приложения (maintenance mode) и дополнительно на уровне MySQL: включить read_only и (если возможно) super_read_only. Цель — чтобы ни одна «случайная» запись не проскочила после начала процедуры.
3) Дождаться полного догона реплики
Ключевой момент: убедитесь, что реплика не просто перестала получать новые события, а действительно применила всё до конца. В classic чаще всего сверяют, что запись на мастере остановлена и реплика дочитала и применила relay log. В GTID дополнительно полезно сверить GTID-набор применённых транзакций на обоих узлах.
4) Промотировать реплику в мастер
Остановить репликацию на будущём мастере, выключить read_only/super_read_only, переключить приложение на новый endpoint и проверить запись.
5) Переподключить старый мастер как реплику (если нужно)
Если это плановый switchover, бывший мастер часто разворачивают как реплику нового мастера. Важно: в момент переключения на старом мастере не должно остаться «уникальных» транзакций, которых нет на новом мастере.

Команды и проверки: минимальный набор для диагностики
Набор команд зависит от версии MySQL (и терминов master/slave vs source/replica), но смысл одинаковый: статус потоков, координаты или GTID, задержка и ошибки.
SHOW MASTER STATUS;
SHOW REPLICA STATUS\G
SHOW SLAVE STATUS\G
SHOW PROCESSLIST;
На что смотреть в первую очередь:
- Ошибки в полях
Last_IO_Error,Last_SQL_Error(и аналогах в вашей версии). - Состояние IO/SQL потоков репликации.
- Динамику relay log и свободное место на диске.
- Факт, что запись на старом мастере действительно остановлена (нет новых транзакций).
Типовые причины replication lag и что делать
1) Реплика упирается в диск/IO
Часто видно по росту relay log и I/O wait. Практичные варианты: быстрый диск под datadir, грамотный выбор storage для VDS (NVMe даёт разницу), контроль fsync-настроек и фоновых задач (бэкапы, компактификация, антивирусы на VM и т.д.). Если вы держите MySQL в облачной инфраструктуре, проще всего масштабировать диск/CPU на VDS под реальный профиль нагрузки.
2) Одна тяжёлая транзакция блокирует применение
ALTER, массовые обновления или «одна транзакция на миллион строк» создают огромный хвост: реплика скачает события быстро, но применять будет долго. Лечится практиками миграций (онлайн-схемы, дробление), мониторингом времени выполнения и контролем блокировок.
3) Недостаточно параллелизма на реплике
Если многопоточная репликация поддерживается, но не настроена, всё применяется в один поток. Включение параллельного применения (по базе/по транзакциям, в зависимости от версии) часто заметно снижает lag, но требует тестирования: неправильные настройки могут не помочь или усложнить диагностику.
4) Semisync включён «на удачу»
При нестабильной сети semisync может добавлять задержку и провоцировать накопление очереди. Его нужно мониторить отдельно: активен ли он сейчас, сколько времени мастер ждёт подтверждение, не ушёл ли он в async.
Миграции и восстановления: где чаще всего ошибаются с GTID
В GTID-режиме критично корректно перенести «историю транзакций». При восстановлении из бэкапа и подключении к мастеру важно, чтобы реплика понимала, какие GTID уже применены. Именно здесь всплывает gtid_purged: неверная установка может привести к пропуску нужных транзакций или попытке применить уже существующие.
Если не уверены в корректности GTID-набора после восстановления, прогоните процедуру на стенде и зафиксируйте её в runbook. Это дешевле, чем разбирать расхождения на продакшене.
В classic главная ошибка аналогична по смыслу: потеря или подмена координат file/position при создании реплики из дампа или снапшота.
Чеклист: перед тем как полагаться на репликацию
- Регулярная проверка: реплика догоняет, ошибок нет, relay log не растёт бесконтрольно.
- Алерты: остановка SQL/IO потоков, рост lag, нехватка места под relay log.
- Реплики защищены
super_read_onlyи корректными правами пользователей. - План switchover протестирован на практике (пусть даже на тестовой топологии).
- Есть понимание, что semisync гарантирует, а что нет, и мониторинг его состояния.
Итоги: как принять решение
Если цель — предсказуемый switchover и минимум ручных операций, GTID чаще оказывается практичнее. Если схема простая, переключения редкие, а процедуры с координатами соблюдаются железно, classic тоже работает. В обоих случаях успех определяют не «галочки» в конфиге, а дисциплина: мониторинг lag, контроль relay log, защита от записи через read_only/super_read_only и регулярные тесты переключения.
Для продакшена дополнительно полезно держать runbook и автоматизацию (хотя бы скрипт проверок). Если MySQL крутится на виртуализации, проще обеспечить предсказуемую производительность реплики и место под relay log на виртуальном хостинге или выделенных ресурсах, в зависимости от нагрузки и требований к отказоустойчивости.


