Come determinare master in mysql master-slave


17

Sto configurando la replica MySQL Master-slave e sto cercando di capire come gestire la situazione di failover in cui promuovo lo slave a master (nel caso in cui il master si interrompa).

Il mio server delle applicazioni deve indirizzare tutte le scritture al master corrente, ma non posso usare l'HA a livello di server tra master e slave (heartbeat, keepalived) poiché i due server db si trovano su subnet completamente diverse in posizioni fisiche diverse.

Penso che questo sia qualcosa che devo gestire a livello di applicazione. Posso interrogare i due server e chiedere quale è un master, quindi eseguire tutte le query su quello.

Esiste una query in MySQL per vedere se il server corrente è un master in una replica master-slave?


Quale versione di MySQL stai usando ???
RolandoMySQLDBA

Questo è un output mysqlServer version: 5.5.23 MySQL Community Server (GPL)
Ethan Hayon,

Risposte:


13

@RolandoMySQLDBA ha risposto alla domanda in modo accurato ... ma ha anche sottolineato che la sua soluzione era "veloce e sporca".

E questa è un'affermazione molto vera. :)

La cosa che mi interessa qui non è con quella risposta, ma piuttosto è che la domanda originale sembra fare un'ipotesi errata:

Posso interrogare i due server e chiedere quale è un master, quindi eseguire tutte le query su quello.

Il problema è che nella replica di MySQL il master non è mai veramente consapevole di essere il master.

Il concetto di "promozione da padroneggiare" non è in realtà un concetto nella replica asincrona di MySQL. "Promuovere" un server MySQL per il ruolo principale è qualcosa che accade "esterno ai" server MySQL, al contrario di qualcosa che accade "interno" ai server MySQL.

La "promozione da master" non viene eseguita da alcun tipo di provisioning del server, poiché, tecnicamente parlando, ogni server MySQL con la registrazione binaria abilitata è un master, anche se non ha mai uno slave. SHOW MASTER STATUSfunziona esattamente allo stesso modo e restituisce esattamente lo stesso risultato, slave o no, e un master con 2 slave non è più o meno un master di un master con 1 slave o 0 slave. Allo stesso modo, un maestro i cui schiavi sono tutti offline è ancora altrettanto un maestro, perché quando gli schiavi tornano online, riprenderanno replicando da dove avevano interrotto.

In un certo senso, l'unica "consapevolezza" da parte di entrambi i server non è se si tratta di un master, ma piuttosto se si tratta di uno slave (o "non").

Ecco cosa chiede la soluzione di Rolando: "sei uno schiavo?" Se la risposta è no, allora il presupposto è che questo deve essere il padrone ... che ha anche indicato come presupposto imperfetto se STOP SLAVE;viene rilasciato. Ma uno schiavo fermo è ancora uno schiavo, quindi "non uno schiavo" (in qualsiasi momento nel tempo) non equivale a "essere un maestro".

Un test simile potrebbe essere eseguito sul presunto master:

SELECT COUNT(1) FROM information_schema.processlist
 WHERE user = 'the_username_used_by_the_slave';

o

SELECT COUNT(1) FROM information_schema.processlist
 WHERE command = 'binlog dump';

Se il valore è zero, il thread IO dello slave non è collegato. Questo test ha un difetto simile, nel senso che se lo slave viene disconnesso amministrativamente, isolato o fallito, non verrà collegato. Quindi neanche questo risolve nulla.

Peggio ancora (per uno di questi scenari) la "tabella" information_schema.processlist è una tabella virtuale che si materializza ogni volta che viene selezionata, e ciò richiede tempo e risorse in termini di costi. Più occupato è il tuo server, più costa, perché l'attività di ogni thread deve essere scrupolosa.

Una soluzione più leggera sarebbe:

SELECT @@global.read_only;

Su uno slave, è possibile / impostare la variabile globale in read_onlymodo che gli utenti senza il SUPERprivilegio non possano scriverlo involontariamente (e l'applicazione non dovrebbe avere SUPER). Se "promuovi" manualmente lo slave nel ruolo principale, devi SET GLOBAL read_only = OFFabilitare le scritture. (La replica può sempre scrivere allo slave, indipendentemente da come è impostata).

Ma questo, penso, manca ancora un punto importante:

Proporrei che l'applicazione non dovrebbe prendere questa decisione in modo euristico in una configurazione master / slave, e certamente non in base alla connessione. L'applicazione deve utilizzare un'opzione di configurazione effettiva oppure l'applicazione deve rimanere inconsapevole e la destinazione della connessione al database deve essere gestita da qualcos'altro.

O, come minimo, l'applicazione non dovrebbe mai cambiare fino a quando il master fallisce, e quindi non dovrebbe mai tornare indietro da solo.

Ecco perché dico che: una volta presa la "decisione" - da chiunque o qualunque cosa - di rendere un altro server il master, l'applicazione non può essere autorizzata per nessun motivo a tornare al master originale, anche dopo che torna in linea , senza intervento.

Diciamo che hai colpito un bug e c'è un crash forzato dal software; mysqld_safesi riavvia doverosamente mysqlde il ripristino da crash di InnoDB funziona in modo impeccabile. Ma ci vogliono alcuni minuti.

Nel frattempo, il master è inattivo, quindi l'applicazione è passata allo slave. Sono state create transazioni, ordini effettuati, fondi trasferiti, commenti pubblicati, blog modificati, qualunque cosa faccia il tuo sistema.

Ora, il master originale torna online.

Se l'applicazione ritorna al master originale, ci si trova in un mondo assoluto di sofferenza, perché la prossima cosa che probabilmente accadrà è che la replica si interrompe a causa di un'incoerenza, poiché l'applicazione ha modificato i dati sullo slave nel mezzo tempo. Ora hai due server di database con dati incoerenti che dovrai riconciliare manualmente. Se ci sono dollari o punti o crediti coinvolti, ora hai saldi non corrispondenti.

Quindi è fondamentale che l'applicazione non possa tornare al master originale senza il tuo intervento.

Aspetta, hai appena trovato il problema con questo scenario come l'ho descritto? Il master non è riuscito ma l'applicazione non utilizzerà lo slave, poiché pensa che lo slave sia ancora lo slave e non il master ... la information_schema.processlistquery sullo slave restituirà comunque un valore diverso da zero anche se il server master è spento .

Quindi non ha molto senso scoprire qualcosa nell'applicazione, dal momento che dovrai fare manualmente STOP SLAVEquel test per essere utile.

Forse un approccio migliore se si desidera che l'applicazione sia in grado di cambiare sarebbe configurare i server con replica circolare.

La replica circolare presenta problemi intrinseci propri, ma fintanto che l'applicazione scrive sempre e solo su un server alla volta, la maggior parte di questi problemi diventa non-problemi. In altre parole, entrambe le macchine sono sempre e contemporaneamente sia master che slave, in senso di replica, ma la tua applicazione, tramite qualche meccanismo, punta sempre a una sola macchina alla volta come "master" su cui può e deve scrivere .

Non è possibile distribuire strumenti HA sui server MySQL a causa della loro separazione, ma è possibile implementarlo con HAProxy in esecuzione sui server delle applicazioni. L'applicazione si collega a "MySQL" su localhost, che non è affatto MySQL, ma in realtà è HAProxy ... e inoltra la connessione TCP alla macchina MySQL appropriata.

HAProxy può testare le connessioni ai server MySQL e offrire traffico solo a una macchina MySQL che accetta connessioni e consente l'autenticazione.

La combinazione di HAProxy in esecuzione sul server delle applicazioni (la sua richiesta di risorse non sarà sostanziale rispetto a tutto ciò che il server delle applicazioni deve fare - è praticamente solo unire i socket e ignorare il loro payload) ... e la replica circolare di MySQL sarebbe l'approccio che probabilmente prenderei in questo caso, basato su ciò che è noto dalla domanda.

Oppure, per una configurazione strettamente manuale, scegli qualcosa di molto più semplice di "scoperta", come una voce nel /etc/hostsfile del server delle app con un nome host che l'applicazione utilizza per connettersi a MySQL, che potresti aggiornare manualmente, supponendo la promozione di slave master è destinato ad essere un processo manuale.

Oppure, qualcosa di più complesso, usando Percona XtraDB Cluster. Per questo, però, vorresti aggiungere un terzo server, perché con 3 nodi in PXC, se 2 server possono vedersi ma isolati da 1 server (se tutti e tre sono ancora in esecuzione) i 2 server continuano a funzionare felicemente ma il server 1 si rannicchia in una pallina e si rifiuta di fare qualsiasi cosa poiché si rende conto che deve essere quello dispari. Questo funziona perché i 2 si rendono conto che costituiscono ancora la maggioranza dei nodi che erano online prima della divisione della rete e il 1 si rende conto che non lo è. Con PXC, non importa davvero a quale server si connette la tua applicazione.

Dico tutto questo per dire "non fare in modo che l'applicazione esegua il polling dei server per vedere quale sia il master" perché ti morderà prima o poi e sgranoccherà le tue prestazioni fino al giorno in cui morde.


Prima di tutto, grazie per la risposta ben scritta. Penso che tu abbia proposto una buona soluzione. Ho pensato di utilizzare la replica circolare in passato, ma ho letto cose cattive sulla sua affidabilità. Tuttavia, molti di questi problemi possono essere prevenuti modificando auto_increment_increment, auto_increment_offset, ecc ... L'uso di HAProxy localmente sui server delle applicazioni (solo come failover) funzionerebbe bene per noi in quanto non dovremmo modificare la nostra applicazione, quindi astrarre il failover logica lontana dal livello dell'applicazione. Esaminerò la configurazione di HAProxy, grazie!
Ethan Hayon,

1
Felice di aiutare. Un voto positivo sarebbe apprezzato se non lo hai già fatto. La replica circolare è affidabile quanto master / slave (è la stessa tecnologia, va in entrambe le direzioni) purché tu capisca come funziona e lo usi in modo sensato. Finché i server sono sincronizzati correttamente e l'applicazione scrive solo su un server alla volta, non ho mai avuto problemi con esso. Le auto_increment_*variabili sono ancora buone da usare in questo scenario, "per ogni evenienza". Inoltre, ricorda di usare binlog_format= rowo mixed- not statement(anche se non stai facendo circolare).
Michael - sqlbot,

Ho modificato la risposta accettata solo perché questa spiegazione dettagliata mi ha aiutato a riprogettare il sistema per renderlo più robusto. La risposta di @RolandoMySQLDBA è ancora corretta e risolve il problema che inizialmente ho descritto. Grazie!
Ethan Hayon,

10

Se stai usando solo Master / Slave, ecco qualcosa di rapido e sporco:

SELECT COUNT(1) SlaveThreadCount
FROM information_schema.processlist
WHERE user='system user';

Cosa ti dice questo?

  • Se SlaveThreadCount= 0, hai il Master
  • Se SlaveThreadCount> 0, hai lo Slave

CAVEAT : funziona finché non si esegueSTOP SLAVE;

Un'altra cosa da provare è questa: se si disabilita la registrazione binaria sullo Slave e si esegue SHOW MASTER STATUS;, il Master fornisce il registro binario corrente. Lo schiavo non ti dà niente.


Fantastico, questo è esattamente ciò di cui ho bisogno. Pensi che questa sia una soluzione disordinata al problema? L'unico problema che posso immaginare è che entrambi i server vengano promossi come master, ma ciò non dovrebbe mai realmente accadere.
Ethan Hayon,

Se questa risposta è ciò di cui hai bisogno, contrassegnare la risposta accettata facendo clic sul segno di spunta sulla mia risposta.
RolandoMySQLDBA

Non posso contrassegnarlo come accettato per altri 5 minuti :)
Ethan Hayon,

Nessun problema. Mi ha fatto piacere poterti aiutare !!!
RolandoMySQLDBA

0

eseguire questa istruzione dal prompt
mysql mysql> show status slave;

Sullo slave mostra molti parametri e i loro valori / stato, mentre sul master mostra il set vuoto

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.