@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
потрібно включити запис. (Реплікацію завжди можна записати на раба, незалежно від того, як це встановлено).
Але це все одно, я думаю, пропускає важливий момент:
Я б запропонував, щоб програма не приймала це рішення евристично в режимі master / slave, і, звичайно, не на основі з'єднання за з'єднанням. Додаток повинен використовувати або жорсткий варіант конфігурації, або додаток повинен залишатися невідомим, а призначення з'єднання бази даних обробляти чимось іншим.
Або, як мінімум, програма ніколи не повинна перемикатися, поки майстер не виходить з ладу, і тоді він ніколи не повинен перемикатися самостійно.
Ось чому я кажу, що: як тільки хтось чи що завгодно прийме «рішення» зробити іншим сервером майстром, додаток не може бути дозволено з будь-якої причини повернутися до початкового майстра, навіть після того, як він повернеться в Інтернет , без втручання.
Скажімо, ви потрапили в помилку, і сталася аварія з програмним забезпеченням; 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. Для цього, хоча б, ви хочете додати третій сервер, оскільки з 3-ма вузлами в PXC, якщо два сервери можуть бачити один одного, але ізолюватися від 1-го сервера (якщо всі три тривають і досі), два сервери продовжують працювати успішно, але 1 сервер згортається на маленьку кульку і відмовляється робити що-небудь, оскільки зрозуміє, що це повинен бути непарний. Це працює, тому що два розуміють, що вони все ще складають більшість вузлів, які були в Інтернеті до розколу мережі, а 1 розуміє, що це не так. З PXC це не має значення, до якого сервера підключається ваше додаток.
Я кажу, що все це полягає в тому, щоб сказати, "не майте програми опитувати сервери, щоб побачити, хто з них є господарем", тому що він буде кусати вас рано чи пізно, і він буде гризти при вашому виконанні аж до дня, коли він кусається.