@RolandoMySQLDBA ответил на вопрос точно ... но он также указал, что его решение было «быстрым и грязным».
И это очень верное утверждение. :)
Дело в том, что меня здесь интересует не тот ответ, а скорее то, что первоначальный вопрос, кажется, делает неверное предположение:
Я могу запросить два сервера и спросить, какой из них является главным, а затем выполнить все запросы к этому.
Проблема в том, что в репликации MySQL мастер никогда не осознает, что он мастер.
Понятие «продвижение к мастеру» на самом деле не является понятием в асинхронной репликации MySQL. «Продвижение» сервера MySQL на главную роль - это то, что происходит «внешне» по отношению к серверам MySQL, а не «внутренне» по отношению к серверам MySQL.
«Повышение до мастерства» не выполняется никаким видом серверной подготовки, потому что, технически говоря, каждый сервер MySQL, для которого включена двоичная регистрация, является мастером, даже если у него никогда не было ведомого устройства. SHOW MASTER STATUS
работает точно так же и возвращает точно такой же результат, ведомые или нет, и мастер с 2 рабами не более или менее мастер, чем мастер с 1 рабом или 0 рабами. Точно так же мастер, все рабы которого находятся в автономном режиме, все еще является тем же мастером, потому что, когда рабы возвращаются в оперативный режим, они начинают репликацию там, где они остановились.
В некотором смысле, единственное «осознание» со стороны любого из серверов заключается не в том, является ли он ведущим, а в том, является ли он подчиненным (или «нет»).
Вот что говорит Роландо: «Ты раб?» Если ответ «нет», то предполагается, что это должен быть мастер ..., который он также указал как ошибочное предположение, если STOP SLAVE;
оно выпущено. Но остановленный раб по-прежнему остается рабом, поэтому «не раб» (в любой момент времени) не означает «быть хозяином».
Подобный тест может быть выполнен на предполагаемом мастере:
SELECT COUNT(1) FROM information_schema.processlist
WHERE user = 'the_username_used_by_the_slave';
или
SELECT COUNT(1) FROM information_schema.processlist
WHERE command = 'binlog dump';
Если значение равно нулю, то поток ввода-вывода ведомого не подключен. Этот тест имеет аналогичный дефект в том, что если ведомое устройство отключено административно, изолировано или не выполнено, оно не будет подключено. Так что это тоже ничего не решает.
Что еще хуже (для любого из этих сценариев) «таблица» information_schema.processlist представляет собой виртуальную таблицу, которая материализуется каждый раз, когда ее выбирают, и это требует времени и затрат ресурсов. Чем занят ваш сервер, тем больше он стоит, потому что активность каждого потока должна быть одноранговой.
Более легкое решение будет:
SELECT @@global.read_only;
На ведомом устройстве вы можете / должны установить глобальную переменную read_only
так, чтобы пользователи без SUPER
привилегий не могли непреднамеренно писать в нее (а ваше приложение не должно иметь этого SUPER
). Если вы вручную «продвигаете» подчиненное устройство к ведущей роли, вам SET GLOBAL read_only = OFF
нужно включить запись. (Репликация всегда может писать на ведомое устройство, независимо от того, как это установлено).
Но это все же, я думаю, упускает важный момент:
Я хотел бы предложить, чтобы приложение не принимало это решение эвристически в настройке «ведущий / ведомый» и, конечно, не на основе соединения за соединением. Прикладная программа должна использовать либо параметр жесткой конфигурации, либо приложение должно оставаться неосведомленным и иметь назначение для подключения к базе данных, обрабатываемое чем-то другим.
Или, как минимум, приложение никогда не должно переключаться, пока мастер не выйдет из строя, и тогда оно никогда не должно переключаться обратно самостоятельно.
Вот почему я говорю это: после того, как «кем бы то ни было» принято решение сделать главный сервер другим сервером, приложению по какой-либо причине не разрешается переключаться на первоначальный мастер, даже после того, как он возвращается в оперативный режим. без вмешательства.
Допустим, вы обнаружили ошибку и произошел программный сбой; mysqld_safe
покорно перезагружается mysqld
, и восстановление после сбоя InnoDB выполняется безупречно. Но это занимает несколько минут.
Тем временем мастер не работает, поэтому ваше приложение переключилось на подчиненное устройство. Были созданы транзакции, размещены заказы, переведены средства, опубликованы комментарии, отредактированы блоги, что бы ни делала ваша система.
Теперь оригинальный мастер возвращается в онлайн.
Если ваше приложение переключается обратно на исходный мастер, вы находитесь в абсолютном мире вреда, потому что следующее, что может произойти, это то, что репликация останавливается из-за несогласованности, потому что ваше приложение в среднем изменило данные на ведомом устройстве. время. Теперь у вас есть два сервера базы данных с противоречивыми данными, которые вам придется согласовывать вручную. Если задействованы доллары, баллы или кредиты, теперь у вас несоответствующие балансы.
Поэтому очень важно, чтобы приложение не могло переключиться обратно на первоначальный мастер без вашего вмешательства.
Подождите, вы только что обнаружили проблему с этим сценарием, как я описал его? Мастер отказал, но ваше приложение не будет использовать ведомое устройство, потому что оно считает, что подчиненное устройство все еще является ведомым, а не ведущим ... information_schema.processlist
запрос на ведомом устройстве все равно будет возвращать ненулевое значение, даже если мастер-сервер выключен ,
Таким образом, нет ничего особенного в том, что приложение обнаруживает что-либо, так как вам придется вручную, STOP SLAVE
чтобы этот тест был полезным.
Возможно, лучшим подходом, если вы хотите, чтобы приложение могло переключаться, было бы настроить серверы с циклической репликацией.
Циркулярная репликация имеет свои собственные проблемы, но пока ваше приложение всегда всегда выполняет запись только на один сервер за один раз, большинство из этих проблем не возникает. Другими словами, обе машины всегда и одновременно являются и главными, и подчиненными, в смысле репликации, но ваше приложение через некоторый механизм всегда указывает только на одну машину за раз как «мастер», на который она может и должна записывать ,
Вы не можете развернуть инструменты HA на серверах MySQL из-за их разделения, но вы можете реализовать их с HAProxy, работающим на серверах приложений. Приложение подключается к «MySQL» на localhost, который вообще не является MySQL, но на самом деле является HAProxy ... и перенаправляет TCP-соединение на соответствующую машину MySQL.
HAProxy может тестировать соединения с серверами MySQL и предлагать трафик только к машине MySQL, которая принимает соединения и разрешает аутентификацию.
Комбинация HAProxy, работающего на сервере приложений (его потребность в ресурсах не будет существенной по сравнению со всем остальным, что должен делать сервер приложений - это просто объединение сокетов и игнорирование их полезной нагрузки) ... и циклическая репликация MySQL был бы подход, который я, вероятно, использовал бы в этом случае, основываясь на том, что известно из вопроса.
Или, для строго ручной настройки, используйте что-то намного более простое, чем «обнаружение», например запись в /etc/hosts
файле сервера приложений с именем хоста, которое приложение использует для подключения к MySQL, которое вы можете обновить вручную - при условии продвижения подчиненного к мастер предназначен для ручного процесса.
Или что-то более сложное, используя Percona XtraDB Cluster. Для этого, однако, вы хотите добавить третий сервер, потому что с 3 узлами в PXC, если 2 сервера могут видеть друг друга, но изолированы от 1 сервера (если все три еще работают), 2 сервера продолжают работать счастливо, но 1 сервер скручивается в маленький шарик и отказывается что-либо делать, поскольку понимает, что он должен быть нечетным. Это работает, потому что 2 понимают, что они все еще составляют большинство узлов, которые были в сети до разделения сети, а 1 понимает, что это не так. С PXC не имеет значения, к какому серверу подключается ваше приложение.
Я говорю, что все это означает, что «приложение не должно опрашивать серверы, чтобы определить, какой из них является главным», потому что оно рано или поздно укусит вас и откусит вашу производительность вплоть до того дня, когда оно укусит.