В любой живой базе неизбежны окна обслуживания: миграции схемы, перестройка индексов, обновления движка, слепки данных. Главный риск — случайные записи со стороны приложений или людей с привилегиями. В MySQL для защиты есть три ключевых рычага: read_only, super_read_only и сессионный флаг sql_log_bin. Вместе они позволяют строить «супер‑режим» безопасного обслуживания, когда записи блокируются корректно, а вспомогательные операции не расползаются по репликации.
Что делают read_only, super_read_only и sql_log_bin
read_only — глобальный флаг, запрещающий записи для всех пользователей, кроме тех, у кого есть привилегия SUPER (в MySQL 8.0 заменена на SYSTEM_VARIABLES_ADMIN и др.) и потоков репликации. С включённым read_only обычные приложения перестают модифицировать данные, но администратор с привилегиями всё ещё может писать, как и репликационный аплаер.
super_read_only — усиливает политику: запрещает записи даже пользователям с SUPER, оставляя «окно» только для внутреннего репликационного потока. Это именно то, что нам нужно для по‑настоящему «замороженного» мастера или стойко защищённой реплики.
sql_log_bin — сессионный переключатель, управляющий записью выполняемых команд в бинарный лог. Его типичный кейс: нужно что-то сделать локально (например, на реплике или на мастере перед переключением ролей), но не хотим, чтобы операция ушла по репликации. Тогда в этой сессии включаем sql_log_bin=0. Важно: это именно сессионный флаг, глобально установить его нельзя.
Репликационный поток в MySQL имеет иммунитет к
read_onlyиsuper_read_only. Это позволяет держать реплики в постоянном «read‑only» без риска остановки аплая.
Дополнения и тонкости
super_read_onlyсуществует в MySQL 5.7+; в старых версиях его нет и защиту суперпользователя придётся обеспечивать процессом и доступами.- Создание временных таблиц пользователями возможно и при
read_only=ON— учитывайте место на диске. - С
super_read_only=ONблокируются и изменения системной БДmysql(например,GRANT), что хорошо для безопасности в окне работ. - Для MySQL 8.0+ можно использовать
SET PERSIST, но для временных окон обслуживания чаще не следует сохранять флаги на диск.
Базовые операции: как включить и проверить
# Включить «супер‑режим» (сначала read_only, затем super_read_only)
SET GLOBAL read_only = ON;
SET GLOBAL super_read_only = ON;
# Проверить состояние
SHOW GLOBAL VARIABLES LIKE 'read_only';
SHOW GLOBAL VARIABLES LIKE 'super_read_only';
# Снять ограничения (сначала super_read_only, затем read_only)
SET GLOBAL super_read_only = OFF;
SET GLOBAL read_only = OFF;
Порядок важен, чтобы не оставлять щелей для записей пользователей с высокими привилегиями между переключениями. Перед включением ограничений стоит дождаться завершения долгих транзакций записи. Минимальный чек:
SELECT trx_id, trx_started, trx_state, trx_rows_modified
FROM information_schema.innodb_trx
WHERE trx_operation_state IS NOT NULL;
SHOW PROCESSLIST;
Если видите долгие изменения, корректно завершаем или откатываем их согласно регламенту обслуживания.
Если вы делаете файловый снимок (snapshot), помните: FLUSH TABLES WITH READ LOCK даёт глобальный блок на таблицы MyISAM и стоп/квиктюны метаданных, но для InnoDB на современных версиях лучше использовать LOCK INSTANCE FOR BACKUP — он мягче для нагрузки. Комбинация с super_read_only снижает шанс несогласованности во время окна. Для восстановления до точки времени и общего подхода к журналам см. материал PITR по binlog и GTID.
# Пример краткого окна для снимка
SET GLOBAL read_only = ON;
SET GLOBAL super_read_only = ON;
LOCK INSTANCE FOR BACKUP;
-- делаем снимок ФС
UNLOCK INSTANCE;
SET GLOBAL super_read_only = OFF;
SET GLOBAL read_only = OFF;

«Супер‑режим» для одиночного сервера
Сценарий: у вас один инстанс MySQL, нужно безопасно провести схему‑миграцию или короткий бэкап с консистентной точкой.
- Проверяем активные записи и блокировки, уведомляем приложение о предстоящем окне.
- Включаем
read_onlyиsuper_read_only. - Проверяем, что новые транзакции записи начали падать с ошибками, а чтения работают.
- Выполняем операции: DDL, экспорт метаданных, снимок LVM или файловой системы, проверяем целостность.
- Выключаем
super_read_only, потомread_only, возвращаем трафик.
Мастер и реплики: правильные политики
Реплики
Реплики разумно держать в защищённом состоянии постоянно: read_only=ON, super_read_only=ON. Это предотвращает случайные записи через консоль и скрипты. При этом поток репликации применяет события как обычно.
# my.cnf для реплики
[mysqld]
read_only = ON
super_read_only = ON
Если на реплике включён бинарный лог (например, это промежуточный узел в цепочке), для локальных технических действий пользуемся сессионным sql_log_bin=0, чтобы операции не ушли дальше:
-- Только в текущей сессии!
SET SESSION sql_log_bin = 0;
-- Если включён GTID, безопаснее явно анонсировать анонимные транзакции
SET SESSION gtid_next = 'ANONYMOUS';
-- локальные операции, не для репликации
ANALYZE TABLE mydb.t1;
OPTIMIZE TABLE mydb.t2;
SET SESSION gtid_next = 'AUTOMATIC';
SET SESSION sql_log_bin = 1;
Такой подход особенно полезен для операций обслуживания вроде ANALYZE, перезаписи статистики, перестроения вторичных индексов с ALGORITHM=INPLACE/INSTANT, которые вы не хотите транслировать вниз по топологии.

Мастер
На мастере read_only и super_read_only обычно выключены. Но для короткого и предсказуемого окна работ можно включить их вместе, предварительно убедившись, что реплики догнали мастера.
- Проверяем задержку реплик и длинные транзакции на мастере.
- Включаем
read_onlyиsuper_read_only. Приложение начинает получать ошибки на запись — окно должно быть минимальным. - Делаем нужные действия: фиксация контрольной точки для бэкапа, подготовка к failover, критичный DDL с недопустимой рассинхронизацией.
- Отключаем флаги в обратном порядке и возвращаем трафик.
Если ваш пайплайн подразумевает переключение ролей (promote реплики), то перед promote убедитесь, что старый мастер находится в «супер‑режиме» и не принимает запись, иначе будет split‑brain. Полезно автоматизировать проверку флагов в оркестрации. Про сценарии переключений с GTID и политику semi-sync см. статью GTID и semi-sync failover.
Производственные кластеры удобнее держать на изолированных серверах или виртуалках; если нужна гибкая топология и быстрый апгрейд CPU/IO, рассмотрите VDS с выделенными ресурсами.
sql_log_bin: безопасные локальные операции
sql_log_bin — сессионный. Он не изменяет глобальную политику и не снимает read_only/super_read_only. Это именно про контроль записи в бинарный лог для текущей сессии. Типичные кейсы:
- Локальное обслуживание на реплике, которая транзитом ретранслирует события дальше.
- Однократные фиксы метаданных, которые не должны попасть в другие узлы.
- Проверочные операции и инспекции, которые затрагивают служебные таблицы, но не должны попадать в репликацию.
При включённом GTID используйте связку
SET SESSION sql_log_bin = 0иSET SESSION gtid_next = 'ANONYMOUS', затем вернитеgtid_nextв'AUTOMATIC'. Это предотвращает ошибки согласованности и «дыры» в последовательности.
Важно помнить: такие операции не попадут в бинарный лог и не будут реплицированы, поэтому их последствия останутся только на текущем узле. Это ожидаемое поведение — учитывайте это в регламентах и документации.
Шаблоны процедур: от простого к продвинутому
Короткое окно для DDL с риском блокировок
-- Проверяем активные записи
SELECT COUNT(*) FROM information_schema.innodb_trx WHERE trx_rows_modified > 0;
-- Включаем режим
SET GLOBAL read_only = ON;
SET GLOBAL super_read_only = ON;
-- Делаем DDL
ALTER TABLE app.users ADD COLUMN flags INT NOT NULL DEFAULT 0, ALGORITHM=INPLACE, LOCK=NONE;
-- Выключаем режим
SET GLOBAL super_read_only = OFF;
SET GLOBAL read_only = OFF;
Если DDL всё же потребовал блокировок (например, перестройка первичного ключа), окно лучше выносить на период минимальной нагрузки и иметь план отката.
Подготовка к failover
- Убедиться, что все реплики догнали мастера (задержка нулевая).
- На мастере включить
read_onlyиsuper_read_only. - Снять контрольный слепок состояния (позиция в binlog/GTID), зафиксировать метрики.
- Promote реплику и перевести трафик.
- Старый мастер оставить в
super_read_onlyдо полной ресинхронизации и переинициализации как реплики.
Обслуживание на промежуточной реплике
-- Реплика постоянно в read-only/super-read-only
-- Для локальной операции не для репликации
SET SESSION sql_log_bin = 0;
SET SESSION gtid_next = 'ANONYMOUS';
ANALYZE TABLE analytics.events;
SET SESSION gtid_next = 'AUTOMATIC';
SET SESSION sql_log_bin = 1;
Частые ошибки и ловушки
- Включили только
read_only. Пользователь с SUPER всё ещё может писать. Итог — «дырка» в защите. Используйте оба флага. - Сняли флаги в неверном порядке. Сначала выключайте
super_read_only, затемread_only, чтобы не получить короткий момент, когда SUPER может писать. - Забыли вернуть
sql_log_bin. Дальнейшие действия останутся вне бинарного лога, нарушится предсказуемость. Работайте в отдельной сессии и закрывайте её сразу после операции. - Игнорирование длинных транзакций. Включение read‑only посреди долгих записей ведёт к таймаутам и ретраям на приложении. Лучше дождаться завершения или принудительно остановить согласно регламенту.
- Несогласованность GTID. При GTID и
sql_log_bin=0не забудьтеgtid_next='ANONYMOUS'и возврат в'AUTOMATIC'. - События планировщика и триггеры. В «супер‑режиме» они тоже не должны писать, но проверяйте бизнес‑триггеры и отложенные задания — возможно, их стоит временно отключить на уровне приложения.
Наблюдаемость во время окна
Поддерживайте видимость состояния:
SHOW GLOBAL STATUS: метрики соединений, ошибок, откатов.SHOW ENGINE INNODB STATUS: блокировки и ожидания.SHOW SLAVE STATUSилиSHOW REPLICA STATUS: задержка репликации, номера журналов.- Проверка версий переменных:
SELECT @@global.read_only, @@global.super_read_only;
Имеет смысл вывести состояние в мониторинг заранее, чтобы дашборд «краснел» предсказуемо и не тревожил смену понапрасну.
Политики по умолчанию
- Реплики:
read_only=ON,super_read_only=ONв конфиге. Временные исключения — только сессионные и только под регламент. - Мастер: оба флага OFF. На время обслуживания включаем оба, минимизируем окно, держим план отката.
- Сессионные операции: только через отдельные подключения с явным
sql_log_bin=0и возвратом в дефолт, желательно с ролевой сегрегацией доступа.
Чек‑лист безопасного окна
- Уведомили приложение и стейкхолдеров, подготовили таймбокс и обратный план.
- Проверили длинные транзакции, задержку реплик, состояние блокировок.
- Включили
read_onlyиsuper_read_onlyв нужной последовательности. - Выполнили операции, требующие заморозки записи, при необходимости использовали
LOCK INSTANCE FOR BACKUP. - Выключили флаги, проверили метрики, провели функциональные прогоны.
- Задокументировали изменения и артефакты (позиции binlog/GTID, версии схемы).
Короткий FAQ
Можно ли навсегда держать мастер в read_only и просто выдавать SUPER приложению? Нет. Это нарушает модель безопасности и усложняет анализ инцидентов. Используйте принцип наименьших привилегий.
Чем FLUSH TABLES WITH READ LOCK отличается от super_read_only? FTWRL — глобальная блокировка на уровне сервера, влияющая на метаданные и MyISAM; super_read_only — политика запрета записи транзакций пользователями. Для InnoDB‑нагрузки «супер‑режим» обычно мягче и достаточен, FTWRL нужен для специфических задач.
Будет ли реплика писать при super_read_only=ON? Да, поток репликации применяет события независимо, и это ожидаемо.
Нужно ли включать sql_log_bin=0 при всех сервисных операциях? Нет. Только там, где вы осознанно не хотите реплицировать эффект. По умолчанию лучше оставлять бинарный лог включенным.
Итоги
Правильная комбинация read_only, super_read_only и аккуратного использования sql_log_bin превращает окна обслуживания MySQL в предсказуемую и безопасную процедуру. «Супер‑режим» жестко отсекает любые записи, кроме репликации, а сессионное отключение бинарного лога помогает выполнять локальные задачи без сторонних эффектов. Добавьте мониторинг, чек‑листы и дисциплину — и даже непростые миграции пройдут без сюрпризов.


