Ich richte die MySQL Master-Slave-Replikation ein und versuche herauszufinden, wie ich mit der Failover-Situation umgehen kann, in der ich den Slave zum Master befördere (für den Fall, dass der Master ausfällt).
Mein Anwendungsserver muss alle Schreibvorgänge an den aktuellen Master leiten, aber ich kann die Serverebene HA zwischen Master und Slave (Heartbeat, Keepalived) nicht verwenden, da sich die beiden Datenbankserver in völlig unterschiedlichen Subnetzen an verschiedenen physischen Standorten befinden.
Ich denke, das ist etwas, was ich auf Anwendungsebene behandeln muss. Ich kann die beiden Server abfragen und fragen, welcher ein Master ist, und dann alle Abfragen an diesen durchführen.
Gibt es in MySQL eine Abfrage, ob der aktuelle Server ein Master in einem Master-Slave-Replikat ist?
quelle
Server version: 5.5.23 MySQL Community Server (GPL)
Antworten:
@RolandoMySQLDBA hat die Frage genau beantwortet ... aber er wies auch darauf hin, dass seine Lösung "schnell und schmutzig" war.
Und das ist eine sehr wahre Aussage. :)
Was mich hier beschäftigt, ist nicht diese Antwort, sondern die Tatsache, dass die ursprüngliche Frage eine falsche Annahme zu machen scheint:
Das Problem ist, dass der Master bei der MySQL-Replikation nie wirklich weiß, dass er der Master ist.
Das Konzept der "Beförderung zum Master" ist in der asynchronen Replikation von MySQL eigentlich kein Konzept. Das "Heraufstufen" eines MySQL-Servers zur Masterrolle geschieht "außerhalb" von MySQL-Servern und nicht "innerhalb" von MySQL-Servern.
Die "Beförderung zum Master" wird von keiner Serverbereitstellung durchgeführt, da technisch gesehen jeder MySQL-Server, auf dem die binäre Protokollierung aktiviert ist, ein Master ist, auch wenn er niemals einen Slave hat.
SHOW MASTER STATUS
Arbeitet genau so und gibt genau das gleiche Ergebnis zurück, ob Slaves oder nicht, und ein Master mit 2 Slaves ist nicht mehr oder weniger ein Master als ein Master mit 1 Slave oder 0 Slaves. Ebenso ist ein Master, dessen Slaves alle offline sind, immer noch genauso ein Master, denn wenn die Slaves wieder online sind, wiederholen sie sich dort, wo sie aufgehört haben.In gewisser Weise besteht die einzige "Erkenntnis" beider Server nicht darin, ob es sich um einen Master handelt, sondern ob es sich um einen Slave handelt (oder nicht).
Das ist, was Rolando Lösung fragt: "Bist du ein Sklave?" Wenn die Antwort nein ist, dann ist die Annahme, dass dies der Meister sein muss ... was er auch als fehlerhafte Annahme bezeichnet, wenn
STOP SLAVE;
ausgegeben wird. Aber ein angehaltener Sklave ist immer noch ein Sklave, so dass "kein Sklave" (zu jedem Zeitpunkt) nicht mit "ein Meister sein" gleichzusetzen ist.Ein ähnlicher Test könnte am vermuteten Master durchgeführt werden:
oder
Wenn der Wert Null ist, ist der IO-Thread des Slaves nicht verbunden. Dieser Test weist einen ähnlichen Fehler auf: Wenn der Slave administrativ getrennt, isoliert oder ausgefallen ist, wird keine Verbindung hergestellt. Das löst also auch nichts.
Schlimmer noch (für eines dieser Szenarien): Die "Tabelle" information_schema.processlist ist eine virtuelle Tabelle, die bei jeder Auswahl materialisiert wird. Dies kostet Zeit und Ressourcen. Je geschäftiger Ihr Server ist, desto höher sind die Kosten, da in die Aktivitäten jedes Threads eingesehen werden muss.
Eine leichtere Lösung wäre:
Auf einem Slave könnten / sollten Sie die globale Variable
read_only
so einstellen , dass Benutzer ohne dieSUPER
Berechtigung nicht unbeabsichtigt darauf schreiben können (und Ihre Anwendung sollte dies nicht habenSUPER
). Wenn Sie den Slave manuell in die Master-Rolle "befördern", müssen SieSET GLOBAL read_only = OFF
Schreibvorgänge aktivieren. (Die Replikation kann immer in den Slave schreiben, egal wie dies eingestellt ist).Aber ich denke, das geht noch an einem wichtigen Punkt vorbei:
Ich würde vorschlagen, dass die Anwendung diese Entscheidung nicht heuristisch in einem Master / Slave-Setup und erst recht nicht verbindungsweise treffen sollte. Die Anwendung sollte entweder eine feste Konfigurationsoption verwenden, oder die Anwendung sollte nichts davon wissen und das Datenbankverbindungsziel von etwas anderem behandeln lassen.
Oder zumindest sollte die Anwendung niemals umschalten, bis der Master ausfällt, und dann sollte sie niemals von selbst zurückschalten.
Hier ist der Grund, warum ich das sage: Sobald die "Entscheidung" - von wem oder was auch immer - getroffen wurde, einen anderen Server zum Master zu machen, kann die Anwendung aus keinem Grund zum ursprünglichen Master zurückkehren, selbst nachdem sie wieder online ist , ohne einzugreifen.
Angenommen, Sie haben einen Fehler gefunden und es kommt zu einem Absturz, der durch Software erzwungen wird.
mysqld_safe
Der Neustart vonmysqld
InnoDB ist pflichtgemäß und die Wiederherstellung nach einem Absturz funktioniert einwandfrei. Das dauert aber ein paar Minuten.In der Zwischenzeit ist der Master heruntergefahren, sodass Ihre Anwendung auf den Slave umgeschaltet hat. Transaktionen wurden erstellt, Bestellungen aufgegeben, Gelder überwiesen, Kommentare gepostet, Blogs bearbeitet, was auch immer Ihr System tut.
Jetzt ist der ursprüngliche Master wieder online.
Wenn Ihre Anwendung auf den ursprünglichen Master zurückschaltet, befinden Sie sich in einer Welt voller Verletzungen, da die Replikation als Nächstes wahrscheinlich aufgrund einer Inkonsistenz gestoppt wird, da Ihre Anwendung in der Zwischenzeit Daten auf dem Slave geändert hat Zeit. Sie haben jetzt zwei Datenbankserver mit inkonsistenten Daten, die Sie manuell abgleichen müssen. Wenn es sich um Dollars, Punkte oder Guthaben handelt, sind die Kontostände nicht mehr aufeinander abgestimmt.
Daher ist es wichtig, dass die Anwendung nicht ohne Ihr Zutun zum ursprünglichen Master zurückkehren kann.
Warten Sie, haben Sie gerade das Problem mit diesem Szenario gefunden, wie ich es beschrieben habe? Der Master ist ausgefallen, aber Ihre Anwendung verwendet den Slave nicht, da sie denkt, der Slave sei immer noch der Slave und nicht der Master. Die
information_schema.processlist
Abfrage auf dem Slave wird immer noch ungleich Null zurückgegeben, auch wenn der Master-Server ausgeschaltet ist .Es macht also nicht viel Sinn, wenn die Anwendung etwas entdeckt, da Sie
STOP SLAVE
diesen Test manuell durchführen müssen , um ihn zu nutzen.Ein besserer Ansatz, wenn Sie möchten, dass die Anwendung wechseln kann, besteht darin, die Server mit zirkulärer Replikation zu konfigurieren.
Die zirkuläre Replikation weist eigene Probleme auf. Solange Ihre Anwendung jedoch immer nur auf einen Server gleichzeitig schreibt, sind die meisten dieser Probleme keine Probleme. Mit anderen Worten, beide Maschinen sind im Sinne der Replikation immer und gleichzeitig Master und Slave, aber Ihre Anwendung zeigt über einen Mechanismus immer nur auf eine Maschine zu einem Zeitpunkt als den "Master", auf den sie schreiben kann und sollte .
Sie können HA-Tools aufgrund ihrer Trennung nicht auf den MySQL-Servern bereitstellen, aber Sie können sie mit HAProxy implementieren, das auf den Anwendungsservern ausgeführt wird. Die Anwendung stellt eine Verbindung zu "MySQL" auf localhost her, das überhaupt nicht MySQL ist, sondern eigentlich HAProxy ... und leitet die TCP-Verbindung an den entsprechenden MySQL-Rechner weiter.
HAProxy kann die Verbindungen zu den MySQL-Servern testen und nur Datenverkehr zu einem MySQL-Computer anbieten, der Verbindungen akzeptiert und die Authentifizierung zulässt.
Die Kombination aus HAProxy, das auf dem Anwendungsserver ausgeführt wird (sein Ressourcenbedarf ist im Vergleich zu allem, was der Anwendungsserver zu tun hat, nicht wesentlich - es bindet einfach Sockets zusammen und ignoriert deren Nutzlast) ... und MySQL-Umlaufreplikation wäre der Ansatz, den ich wahrscheinlich in diesem Fall wählen würde, basierend auf dem, was aus der Frage bekannt ist.
Oder gehen Sie für eine streng manuelle Einrichtung mit etwas viel Einfacherem als "Erkennen" vor, wie einem Eintrag in der
/etc/hosts
Datei des App-Servers mit einem Hostnamen, den die Anwendung verwendet, um eine Verbindung zu MySQL herzustellen, den Sie manuell aktualisieren könnten - vorausgesetzt, Sie befördern den Slave zu Master soll ein manueller Prozess sein.Oder etwas Komplexeres mit Percona XtraDB Cluster. Hierfür möchten Sie jedoch einen dritten Server hinzufügen, da bei 3 Knoten in PXC, wenn 2 Server sich sehen können, aber von 1 Server isoliert sind (wenn alle drei Server noch ausgeführt werden), die 2 Server weiterhin problemlos ausgeführt werden Der 1 Server rollt sich zu einem kleinen Ball zusammen und weigert sich, etwas zu tun, da er feststellt, dass es der seltsame sein muss. Dies funktioniert, weil die 2 erkennen, dass sie immer noch die Mehrheit der Knoten darstellen, die vor dem Aufteilen des Netzwerks online waren, und die 1 erkennt, dass dies nicht der Fall ist. Bei PXC spielt es keine Rolle, zu welchem Server Ihre Anwendung eine Verbindung herstellt.
Ich sage das alles, um zu sagen: "Lassen Sie die Server nicht von der Anwendung abfragen, um herauszufinden, welcher der Master ist", weil er Sie früher oder später beißt und Ihre Leistung bis zu dem Tag beeinträchtigt, an dem er beißt.
quelle
auto_increment_*
Variablen sind in diesem Szenario "nur für den Fall" noch gut zu verwenden. Denken Sie auch daran,binlog_format
=row
odermixed
- nicht zu verwendenstatement
(auch wenn Sie kein Zirkelzeichen verwenden).Wenn Sie nur Master / Slave verwenden, ist hier etwas schnelles und schmutziges:
Was sagt dir das?
SlaveThreadCount
= 0, haben Sie den MasterSlaveThreadCount
> 0, haben Sie den SlaveCAVEAT : Dies funktioniert, solange Sie nicht ausgeführt werden
STOP SLAVE;
Eine andere Sache, die Sie versuchen sollten, ist folgende: Wenn Sie die Binärprotokollierung auf dem Slave deaktivieren und ausführen
SHOW MASTER STATUS;
, zeigt der Master das aktuelle Binärprotokoll an. Der Sklave gibt dir nichts.quelle
Führen Sie diese Anweisung über die mysql-Eingabeaufforderung
mysql> show slave status aus.
Auf dem Slave werden viele Parameter und deren Werte / Status angezeigt, während auf dem Master der leere Satz angezeigt wird
quelle