MySQL-Replikation - Einführung eines neuen Slaves in die Replikation

7

Ich habe kürzlich eine Systemadministratorposition übernommen und eine Gruppe von 20 (oder so) Servern verwaltet. Eine Sache, mit der ich mich vorher nicht befasst habe (außer in einer Testsituation), ist die Einführung eines neuen Slaves in die MySQL-Replikationsfarm.

Grundsätzlich ist die Replikation folgendermaßen eingerichtet:

MS -> SL1 -> SL2 (backup)
|                     SL3 (reporting)
SB2                   SL4 (loadbalanced web slave)
                      SL5 (loadbalanced web slave)
                      SL6 (loadbalanced web slave)
                      SL7 (loadbalanced web slave)

Aber im Grunde ist es ein Master mit zwei Leseslaves (einer nur für die Sicherung), einer für den Hauptlese-Slave (Master wartet, wenn Sie so wollen), mit 6 Slaves dahinter, der für eine zusätzliche Sicherung verwendet wird, 4 Web-Lesevorgänge mit Lastenausgleich Slaves und ein Server für die Berichterstellung.

Ich habe viel online gelesen und angenommen, dass das Hinzufügen eines neuen Slaves zur Umgebung (von SL1) Folgendes wäre:

  • Melden Sie sich bei SL2 an:
    • STOP SLAVE;
    • FLUSH TABLES WITH READ LOCK;
    • (Kopieren Sie das MySQL-Verzeichnis auf einen neuen Server.)
    • nach Abschluss UNLOCK TABLES;und dann START SLAVE;(alles in Ordnung bis zu diesem Zeitpunkt, SL2 kommt wieder online und holt auf)
    • Stellen Sie sicher, dass die Datenbankstruktur auf dem neuen Server korrekt ist und master.info an der richtigen Stelle zeigt (richtig auf SL1 zeigt).
    • Starten Sie MySQL auf dem neuen Server und überprüfen Sie, ob Slave SQL und E / A ausgeführt werden (ja, das ist in Ordnung).

Nach einer gewissen Zeit erhalte ich jedoch doppelte Fehler beim Einfügen von Schlüsseln aus dem Binärprotokoll:

110122 17:01:25 [ERROR] Slave SQL: Error 'Duplicate entry '2011-01-22 17:00:01' for key 'PRIMARY'' on query. Default database: 'thelm_soft'. Query: 'INSERT INTO  thm_member_views  (   member_view_ts, logged_in_members, non_members ) VALUES ( now(), '27037', '132834' )', Error_code: 1062
110122 17:01:25 [Warning] Slave: Duplicate entry '2011-01-22 17:00:01' for key 'PRIMARY' Error_code: 1062

Ist dies ein Problem mit der Tatsache, dass now () in einer Abfrage ist, die mir der gesunde Menschenverstand sagt, würde Probleme verursachen, wenn die Einfügungen in dieser Tabelle häufig genug wären ??!?! Oder habe ich den Prozess mit der Replikation falsch ausgeführt, dh an einer falschen Protokollposition begonnen?

user621
quelle

Antworten:

5

Ist dies ein Problem mit der Tatsache, dass now () in einer Abfrage ist, die mir der gesunde Menschenverstand sagt, würde Probleme verursachen, wenn die Einfügungen in dieser Tabelle häufig genug wären ??!?!

Ja, ich glaube, das ist die Ursache für Ihre Fehler. Ihre Methode zur Einführung des neuen Slaves scheint korrekt zu sein. Es ist meiner Meinung nach ziemlich seltsam, eine Tabelle mit einem DATETIME-Feld als Primärschlüssel zu definieren. Wie Sie zu Recht betont haben, erhält der Slave die replizierten Abfragen vom Master und verwendet das Schlüsselwort now () in den Abfragen, wodurch der Zeitstempel vom lokalen Server abgerufen wird.

Eigentlich sollte die Tabelle mit einem anderen Datentyp für die PK definiert werden (z. B. INT oder BIGINT), der im Gegensatz zu einem mit now () eingefügten Zeitstempel garantiert eindeutig sein kann.

Matt Healy
quelle
Vielen Dank, es scheint jetzt wirklich offensichtlich zu sein, aber das Seltsame ist, dass dies in der replizierten Umgebung seit mehr als einem Jahr ausgeführt wird (im Rückblick auf den Entwicklungscode). Wird now () auf dem Slave immer als CURRENT_DATE ausgewertet oder kann es als statisches Datum im Binärprotokoll gespeichert werden?
User621
Ich glaube schon, weil die Replikation abfragebasiert ist, was bedeutet, dass jede Abfrage, die auf den Master angewendet wird, auch auf die Slaves angewendet wird.
Matt Healy
4

AKTUALISIEREN

Hier ist eine alternative Antwort, die ich auf einer anderen StackExchange-Site geschrieben habe

Ursprüngliche Antwort

Beachten Sie beim Kopieren des MySQL-Verzeichnisses, dass Sie auch die Relay-Protokolle kopiert haben. Alle Relay-Protokolle sind mit der Server-ID des Masters gekennzeichnet. Der Master neigt dazu, einen Slave-Prozess zum "Schluckauf" zu machen, wenn zwei Slaves (Zischlaute) dieselbe Server-ID verwenden.

MySQL wird sich beschweren, wenn ein Master und ein Slave die smae server_id haben. Die MySQL-Replikation wird in diesem Fall nicht einmal gestartet. Dieses Problem ist etwas subtiler und nicht so offensichtlich. Hier ist warum:

Wenn ein Master mehrere Slaves hat und zwei oder mehr dieser Slaves dieselbe Server-ID verwenden, wird der zuerst verbundene Slave (mit der niedrigsten Prozess-ID in der Prozessliste des Masters) problemlos vom Master repliziert. Alle anderen Verbindungen von anderen Slaves mit einer Server-ID, die mit dem ersten Slave identisch ist, können und werden zeitweise unter der Haube getrennt und wieder verbunden. Dies kann den Master auch etwas verwirren, da er Zeitstempeldaten in die Relaisprotokolle schreibt. Es ist wahrscheinlich sicherer, zuerst die Relaisprotokolle zu löschen.

Anstatt die Replikation erst nach der Kopie zu starten, können Sie Folgendes versuchen:

  1. Fügen Sie überspringen-Slave-Start zu /etc/my.cnf dieses neuen Slaves hinzu
  2. Starten Sie MySQL auf dem neuen Slave
  3. Führen Sie CHANGE MASTER TO auf dem neuen Slave aus (Dadurch werden alle zuvor generierten Relais gelöscht, sodass unterschiedliche Zeitstempeldaten in Relaisprotokollen verfügbar sind.)
  4. Entfernen Sie den Skip-Slave-Start aus /etc/my.cnf dieses neuen Slaves
  5. Starten Sie MySQL neu

Ich hoffe das hilft.

RolandoMySQLDBA
quelle
Ich frage mich, warum niemand gefragt hat, welches Replikationsformat Sie verwenden. Ich sage es, weil es vom Format abhängt, wie die Abfrage beim Slave ausgeführt wurde. Es scheint, dass Sie ROW-basiert verwenden
Ankit Kapoor
4

Zu Ihrer Information: Der Aufruf now () verwendet den Zeitstempel des Masters im Replikations-Binlog. http://dev.mysql.com/doc/refman/5.5/en/replication-features-functions.html

Die Antwort über MySQL Replication - Einführung eines neuen Slaves in die Replikation ist völlig korrekt. Sie vermissen den CHANGE MASTER TO.

Warum kopieren Sie das gesamte MySQL-Verzeichnis und nicht nur die spezifischen Datenbankdateien? Wenn ich einen neuen Slave einschalte, führe ich normalerweise eine MySQL-Installation durch und bringe dann die Daten über. Sie benötigen nicht alle Relaisprotokolle des Masters und dergleichen.

Sandi
quelle
3

Führen Sie Ihren Master im binären Protokollformat auf Anweisungsebene aus? Ich bin nicht 100% sicher, ob es funktionieren würde, aber vielleicht würde das Ändern des Formats auf Zeilenebene den Fehler beheben.

Das Problem bei der Protokollierung auf Zeilenebene besteht darin, dass so viel mehr Informationen protokolliert werden, dass Sie die Festplattennutzung überwachen und Ihre Protokolle regelmäßig löschen müssen, um zu vermeiden, dass der Festplattenspeicher knapp wird.

Die Protokollierung auf gemischter Ebene wechselt möglicherweise automatisch das Protokollformat für den NOW () -Aufruf in 'row', aber ich habe es nie versucht, und in den Dokumenten wird nicht ausdrücklich angegeben, dass es für NOW () wechseln wird. Könnte etwas zu testen sein.

Derek Downey
quelle