it-swarm.com.de

Wie man Master in MySQL Master-Slave bestimmt

Ich richte die MySQL-Master-Slave-Replikation ein und versuche herauszufinden, wie ich mit der Failover-Situation umgehen soll, in der ich den Slave zum Master befördere (falls der Master ausfällt).

Mein Anwendungsserver muss alle Schreibvorgänge an den aktuellen Master leiten, ich kann jedoch keine HA auf Serverebene zwischen Master und Slave verwenden (Heartbeat, Keepalived), da sich die beiden Datenbankserver in völlig unterschiedlichen Subnetzen an unterschiedlichen physischen Standorten befinden.

Ich denke, das ist etwas, das ich auf Anwendungsebene behandeln muss. Ich kann die beiden Server abfragen und fragen, welcher ein Master ist, und dann alle Abfragen an diesen ausführen.

Gibt es in MySQL eine Abfrage, ob der aktuelle Server ein Master in einem Master-Slave-Replikat ist?

18
Ethan Hayon

@ RolandoMySQLDBA hat die Frage genau beantwortet ... aber er wies auch darauf hin, dass seine Lösung "schnell und schmutzig" sei.

Und das ist eine sehr wahre Aussage. :) :)

Was mich hier betrifft, ist nicht diese Antwort, sondern dass die ursprüngliche Frage eine falsche Annahme zu machen scheint:

Ich kann die beiden Server abfragen und fragen, welcher ein Master ist, und dann alle Abfragen an diesen ausführen.

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 MySQL-Replikation nicht wirklich ein Konzept. Das "Heraufstufen" eines MySQL-Servers in die Hauptrolle geschieht "außerhalb" von "MySQL-Servern", im Gegensatz zu etwas, das "intern" bei MySQL-Servern geschieht.

"Heraufstufung zum Master" wird von keiner Serverbereitstellung durchgeführt, da technisch gesehen jeder MySQL-Server, für den die binäre Protokollierung aktiviert ist, ein Master ist, auch wenn er niemals einen Slave hat. SHOW MASTER STATUS Funktioniert genauso und gibt genau das gleiche Ergebnis zurück, 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. In ähnlicher Weise ist ein Master, dessen Slaves alle offline sind, immer noch genauso ein Master, denn wenn die Slaves wieder online sind, werden sie dort replizieren, wo sie aufgehört haben.

In gewissem Sinne ist das einzige "Bewusstsein" seitens eines Servers nicht, ob es ein Master ist, sondern ob es ein Slave ist (oder "nicht").

Das ist, was Rolandos Lösung fragt: "Bist du ein Sklave?" Wenn die Antwort nein ist, dann ist die Annahme, dass dies der Master sein muss ... was er auch als fehlerhafte Annahme herausstellte, wenn STOP SLAVE; Ausgegeben wird. Aber ein gestoppter Sklave ist immer noch ein Sklave, also bedeutet "kein Sklave" (zu jedem Zeitpunkt) nicht "ein Meister sein".

Ein ähnlicher Test könnte für den mutmaßlichen Master durchgeführt werden:

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

oder

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

Wenn der Wert Null ist, ist der Thread IO] des Slaves nicht verbunden. Dieser Test weist einen ähnlichen Fehler auf: Wenn der Slave administrativ getrennt, isoliert oder fehlgeschlagen ist, wird dies nicht der Fall sein verbunden sein. Das löst also auch nichts.

Schlimmer noch (für jedes dieser Szenarien) ist die information_schema.processlist "table" eine virtuelle Tabelle, die bei jeder Auswahl materialisiert wird. Dies kostet Zeit und kostet Ressourcen. Je geschäftiger Ihr Server ist, desto mehr kostet er, da die Aktivitäten jedes Threads überprüft werden müssen.

Eine leichtere Lösung wäre:

SELECT @@global.read_only;

Auf einem Slave können/sollten Sie die globale Variable read_only Setzen, damit Benutzer ohne das Privileg SUPER nicht unbeabsichtigt darauf schreiben können (und Ihre Anwendung sollte nicht SUPER haben). Wenn Sie den Slave manuell in die Master-Rolle "befördern", müssen Sie SET GLOBAL read_only = OFF Schreibvorgänge aktivieren. (Die Replikation kann immer auf den Slave schreiben, egal wie dies eingestellt ist).

Aber ich denke, dies übersieht immer noch einen wichtigen Punkt:

Ich würde vorschlagen, dass die Anwendung diese Entscheidung nicht heuristisch in einem Master/Slave-Setup treffen sollte, und schon gar nicht auf Verbindungsbasis. Die Anwendung sollte entweder eine feste Konfigurationsoption verwenden, oder die Anwendung sollte sich dessen nicht bewusst sein und das Datenbankverbindungsziel von etwas anderem behandeln lassen.

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 Folgendes sage: Sobald die "Entscheidung" getroffen wurde - von wem oder was auch immer -, einen anderen Server zum Master zu machen, kann die Anwendung aus keinem Grund wieder zum ursprünglichen Master wechseln, selbst nachdem sie wieder online ist ohne Intervention.

Angenommen, Sie haben einen Fehler gefunden und es kommt zu einem durch Software erzwungenen Absturz. mysqld_safe Startet mysqld pflichtbewusst neu und die Wiederherstellung nach einem InnoDB-Absturz funktioniert einwandfrei. Das dauert aber ein paar Minuten.

In der Zwischenzeit ist der Master ausgefallen, sodass Ihre Anwendung auf den Slave umgestellt hat. Es wurden Transaktionen erstellt, Bestellungen aufgegeben, Geld überwiesen, Kommentare veröffentlicht, Blogs bearbeitet, was auch immer Ihr System tut.

Jetzt ist der ursprüngliche Master wieder online.

Wenn Ihre Anwendung wieder zum ursprünglichen Master wechselt, befinden Sie sich in einer absoluten Welt voller Verletzungen, da das nächste, was wahrscheinlich passiert, ist, dass die Replikation aufgrund einer Inkonsistenz gestoppt wird, da Ihre Anwendung im Durchschnitt die 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 Gutschriften handelt, haben Sie jetzt nicht übereinstimmende Guthaben.

Daher ist es wichtig, dass die Anwendung ohne Ihr Eingreifen nicht zum ursprünglichen Master zurückkehren darf.

Warten Sie, haben Sie gerade das Problem mit diesem Szenario gefunden, wie ich es beschrieben habe? Der Master ist fehlgeschlagen, aber Ihre Anwendung verwendet den Slave nicht, da er denkt, der Slave ist immer noch der Slave und nicht der master ... Die Abfrage information_schema.processlist auf dem Slave gibt auch dann noch ungleich Null zurück, wenn der Master-Server ausgeschaltet ist.

Es macht also nicht viel Sinn, wenn die Anwendung etwas entdeckt, da Sie manuell STOP SLAVE Müssen, damit dieser Test nützlich ist.

Ein besserer Ansatz, wenn die Anwendung wechseln soll, ist möglicherweise die Konfiguration der Server mit zirkulärer Replikation.

Die zirkuläre Replikation weist eigene Probleme auf. Solange Ihre Anwendung jedoch immer nur auf einen Server gleichzeitig schreibt, werden die meisten dieser Probleme zu Problemen. Mit anderen Worten, beide Maschinen sind im Replikationssinn immer und gleichzeitig sowohl Master als auch Slave, aber Ihre Anwendung zeigt über einen bestimmten Mechanismus immer nur auf eine Maschine gleichzeitig 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, was überhaupt nicht MySQL ist, sondern tatsächlich HAProxy ... und leitet die TCP - Verbindung an den entsprechenden MySQL-Computer 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 von HAProxy, das auf dem Anwendungsserver ausgeführt wird (der Ressourcenbedarf ist im Vergleich zu allem, was der Anwendungsserver sonst noch zu tun hat, ist nicht wesentlich - es geht so ziemlich nur darum, Sockets zusammenzubinden und ihre Nutzdaten zu ignorieren) ... und MySQL Circular Replication wäre der Ansatz, den ich wahrscheinlich in diesem Fall verfolgen würde, basierend auf dem, was aus der Frage bekannt ist.

Oder verwenden Sie für eine streng manuelle Einrichtung etwas viel Einfacheres als "Erkennung", z. B. einen 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önnen. - Die Annahme, dass der Slave zum Master befördert wird, soll ein manueller Prozess sein.

Oder etwas komplexeres mit Percona XtraDB Cluster. Zu diesem Zweck möchten Sie jedoch einen dritten Server hinzufügen, da bei 3 Knoten in PXC, wenn sich 2 Server sehen können, aber von 1 Server isoliert werden (wenn alle drei noch ausgeführt werden), die 2 Server weiterhin zufrieden sind Der 1 Server rollt sich zu einem kleinen Ball zusammen und weigert sich, irgendetwas zu tun, da er merkt, dass es der seltsame sein muss. Dies funktioniert, weil die 2 erkennen, dass sie immer noch einen Großteil der Knoten ausmachen, die vor der Aufteilung des Netzwerks online waren, und die 1 erkennt, dass dies nicht der Fall ist. Bei PXC spielt es keine Rolle, mit welchem ​​Server Ihre Anwendung eine Verbindung herstellt.

Ich sage, all dies bedeutet, dass die Anwendung die Server nicht abfragen muss, um festzustellen, welcher der Master ist. Dies wird Sie früher oder später beißen und Ihre Leistung bis zu dem Tag, an dem sie beißt, beeinträchtigen.

15

Wenn Sie nur Master/Slave verwenden, ist hier etwas schnelles und schmutziges:

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

Was sagt dir das?

  • Wenn SlaveThreadCount = 0 ist, haben Sie den Master
  • Wenn SlaveThreadCount> 0 ist, haben Sie den Slave

EINSCHRÄNKUNG : Dies funktioniert, solange Sie nicht STOP SLAVE; ausführen.

Eine andere Sache, die Sie versuchen sollten, ist folgende: Wenn Sie die binäre Protokollierung auf dem Slave deaktivieren und SHOW MASTER STATUS; Ausführen, gibt Ihnen der Master das aktuelle binäre Protokoll. Der Sklave gibt dir nichts.

10
RolandoMySQLDBA

führen Sie diese Anweisung über die MySQL-Eingabeaufforderung aus
mysql> Sklavenstatus anzeigen;

Auf dem Slave werden viele Parameter und deren Werte/Status angezeigt, während auf dem Master Leerer Satz angezeigt wird

0
akrai48