Kapitel 6. Replikation bei MySQL

Inhaltsverzeichnis

6.1. Einführung in die Replikation
6.2. Replikation: Implementation
6.3. Zeilenbasierte Replikation
6.4. Replikation: Implementationsdetails
6.4.1. Thread-Zustände des Replikationsmasters
6.4.2. I/O-Thread-Zustände von Replikationsslaves
6.4.3. SQL-Thread-Zustände von Replikationsslaves
6.4.4. Relay- und Statusdateien bei der Replikation
6.5. Wie man eine Replikation aufsetzt
6.6. Replikation: Kompatibilität zwischen MySQL-Versionen
6.7. Upgrade eines Replikationssetups
6.7.1. Replikation: Upgrade auf 5.0
6.8. Replikation: Features und bekannte Probleme
6.9. Replikationsoptionen in my.cnf
6.10. Wie Server Replikationsregeln auswerten
6.11. Replikation: häufig gestellte Fragen
6.12. Vergleich zwischen anweisungsbasierter und zeilenbasierter Replikation
6.13. Replikation: Problemlösungen
6.14. Berichten von Replikationsfehlern und -problemen
6.15. Auto-Increment in der Multi-Master-Replikation

Dieses Kapitel beschreibt die verschiedenen Replikationsfunktionen in MySQL. Es stellt Replikationskonzepte vor, erläutert die Konfiguration von Replikationsservern und dient als Referenz der verfügbaren Replikationsoptionen. Ferner vorhanden ist eine Liste mit häufig gestellten Fragen (und den zugehörigen Antworten) sowie Hilfestellung zur Behebung von Replikationsproblemen.

Eine Beschreibung der Syntax replikationsspezifischer SQL-Anweisungen finden Sie in Abschnitt 13.6, „SQL-Befehle in Bezug auf Replikation“.

6.1. Einführung in die Replikation

MySQL unterstützt die unidirektionale, asynchrone Replikation, bei der ein Server als Master agiert, während mehrere andere Server die Rolle der Slaves erfüllen. Dies steht im Gegensatz zur synchronen Replikation, die ein Kennzeichen von MySQL Cluster ist (siehe auch Kapitel 16, MySQL Cluster).

Bei der Single-Master-Replikation schreibt der Master-Server Updates in seine Binärlogdateien und führt zudem einen Index dieser Dateien, um den Überblick über die Logrotation zu behalten. Die Binärlogdateien dienen als Datenspeicher für Updates, die an alle Slave-Server gesendet werden. Wenn ein Slave eine Verbindung zu seinem Master herstellt, nennt er dem Master die Position, bis zu der er die Logdateien beim letzten erfolgreichen Update gelesen hat. Der Slave empfängt daraufhin alle Änderungen, die seit jenem Zeitpunkt durchgeführt wurden. Nachfolgend wechselt er in den Leerlauf und wartet darauf, dass der Master ihn über neue Aktualisierungen in Kenntnis setzt.

Ein Slave-Server kann seinerseits als Master agieren, um beispielsweise eine Verkettung von Replikationsservern realisieren zu können.

Die Multi-Master-Replikation ist zwar auch möglich, aber hierbei können Probleme auftreten, die bei der Single-Master-Replikation ausgeschlossen sind. Siehe auch Abschnitt 6.15, „Auto-Increment in der Multi-Master-Replikation“.

Sofern Sie die Replikation verwenden, sollten alle Änderungen an Tabellen, die repliziert werden, auf dem Master-Server durchgeführt werden. Andernfalls müssen Sie nämlich immer sorgfältig darauf achten, Konflikte zwischen von Benutzern vorgenommenen Änderungen an den Tabellen auf dem Master und solchen Änderungen zu vermeiden, die an Tabellen auf dem Slave vorgenommen werden. Beachten Sie ferner, dass Updates auf der Slave-Seite abhängig davon, ob Sie eine anweisungs- oder eine datensatzbasierte Replikation verwenden, unterschiedlich verarbeitet werden können. Betrachten Sie einmal das folgende Szenario, bei dem ein Datensatz auf dem Slave eingefügt wird, gefolgt von einer Anweisung auf Master-Seite, die die Tabelle leert:

slave> INSERT INTO tbl VALUES (1);
master> DELETE FROM tbl;

Der Master weiß nichts über die INSERT-Operation auf dem Slave-Server. Bei der anweisungsbasierten Replikation wird tbl auf dem Master und dem Slave geleert, sobald der Slave auf den Stand des Masters gebracht wird, weil der Master seine DELETE-Anweisung dann an den Slave sendet. Infolgedessen hat tbl nachfolgend auf beiden Servern den gleichen Inhalt. Bei der datensatzbasierten Replikation ist die Wirkung von DELETE auf den Slave eine andere. Der Master schreibt nämlich jeden aus der Tabelle zu löschenden Datensatz in sein Binärlog. Der Slave löscht daraufhin nur diejenigen Datensätze, die dort erscheinen – und nicht denjenigen, der direkt auf dem Slave eingefügt worden war. Hieraus ergeben sich unterschiedliche Inhalte der Tabellen auf dem Master und dem Slave, was zu Replikationsproblemen führen kann.

Informationen zur datensatzbasierten Replikation finden Sie in Abschnitt 6.3, „Zeilenbasierte Replikation“.

Die Replikation bietet Vorteile in puncto Robustheit, Geschwindigkeit und Systemadministration:

  • Die Robustheit wird durch eine Master/Slave-Konfiguration erhöht. Im Fall von Problemen auf dem Master können Sie auf den Slave als Sicherungskopie umschalten.

  • Eine verbesserte Reaktionszeit lässt sich für Clients erzielen, indem die Last bei der Verarbeitung von Clientabfragen auf die Master- und Slave-Server verteilt wird. SELECT-Abfragen können an einen Slave geschickt werden, um die Verarbeitungsbelastung des Masters zu senken. Allerdings sollten Anweisungen, die Daten verändern, in jedem Fall an den Master geschickt werden, damit die Synchronisation zwischen Master und Slaves erhalten bleibt. Die Lastverteilungsstrategie ist effizient, wenn in erster Linie nichtändernde Abfragen abgesetzt werden – aber dies ist auch der Normalfall.

  • Ein weiterer Vorteil der Replikation besteht darin, dass Sie Datenbanksicherungen über einen Slave-Server durchführen können, ohne den Master zu stören. Der Master verarbeitet dann weiterhin alle Aktualisierungen auch während der Erstellung des Backups. Siehe auch Abschnitt 5.10.1, „Datenbank-Datensicherungen“.

6.2. Replikation: Implementation

Die MySQL-Replikation basiert darauf, dass der Master-Server alle Änderungen an Ihren Datenbanken (Updates, Löschvorgänge usw.) in seinen Binärlogs vermerkt. Aus diesem Grund müssen Sie das binäre Loggen auf dem Master-Server aktivieren. Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.

Alle Slave-Server erhalten vom Master die gespeicherten Änderungen, die der Master in seinem Binärlog vermerkt hat, sodass jeder Slave dieselben Änderungen an seiner Kopie der Daten vornehmen kann.

Es ist extrem wichtig, sich klar zu machen, dass das Binärlog nichts anderes als eine Aufzeichnung darstellt, die zu genau dem Zeitpunkt beginnt, an dem Sie das binäre Loggen aktivieren. Insofern benötigen alle zu konfigurierenden Slaves Kopien der Master-Datenbank mit ihrem Aussehen zum Zeitpunkt der Aktivierung der Binärlogs auf dem Master. Wenn Sie Ihre Slaves mit Datenbanken starten, die nicht hundertprozentig denselben Status haben wie der Master beim Aktivieren der Binärlogs, dann werden höchstwahrscheinlich Probleme auftreten.

Eine Möglichkeit, die Daten des Masters auf den Slave zu kopieren, besteht im Absetzen der LOAD DATA FROM MASTER-Anweisung. Allerdings funktioniert LOAD DATA FROM MASTER nur, wenn alle Tabellen auf dem Master die MyISAM-Speicher-Engine verwenden. Ferner erwirkt die Anweisung eine globale Lesesperre, d. h., während die Tabellen auf den Slave übertragen werden, sind keine Updates auf dem Master möglich. Sobald wir die Funktion für sperrenfreie Tabellenbackups im laufenden Betrieb implementiert haben, wird diese globale Lesesperre nicht mehr erforderlich sein.

Aufgrund dieser Einschränkungen empfehlen wir Ihnen bis auf weiteres, LOAD DATA FROM MASTER nur dann zu verwenden, wenn die Datenmenge auf dem Master relativ gering oder eine längere Lesesperre auf dem Master hinnehmbar ist. Zwar kann die tatsächliche Geschwindigkeit von LOAD DATA FROM MASTER von System zu System variieren, aber als Faustregel können Sie eine Übertragungsrate von 1 Mbyte Daten/Sekunde erwarten. Dies ist ein grober Anhaltspunkt, der aber recht genau sein sollte, wenn sowohl Master als auch Slave über 700-MHz-Pentium-Prozessoren verfügen und über ein Netzwerk mit einer Übertragungsrate von 100 Mbit/s miteinander verbunden sind.

Nachdem auf dem Slave eine Kopie der Master-Daten installiert wurde, stellt er eine Verbindung zum Master her und wartet auf Updates, die er verarbeiten kann. Fällt der Master aus oder verliert der Slave die Verbindung zu ihm, dann versucht er in regelmäßigen Abständen, die Verbindung neu herzustellen, bis der Empfang von Updates wieder möglich ist. Die Option --master-connect-retry steuert das Intervall, in dem die Neuverbindung versucht wird. Voreingestellt sind 60 Sekunden.

Jeder Slave vermerkt die Position, an der das Lesen beim letzten Update vom Master-Server beendet wurde. Der Master selbst weiß nicht, wie viele Slaves an ihn angeschlossen sind oder welche Slaves zu einem gegebenen Zeitpunkt aktuell sind.

6.3. Zeilenbasierte Replikation

Die Replikationsfunktionen in MySQL basierten ursprünglich auf der Weitergabe von SQL-Anweisungen vom Master an den Slave. Dies bezeichnete man als anweisungsbasierte Replikation (Statement-Based Replication, SBR). Seit MySQL 5.1.5 gibt es noch eine andere Basis für die Replikation: die datensatzbasierte Replikation (Row-Based Replication, RBR). Statt die SQL-Anweisungen an den Slave zu senden, schreibt der Master alle Ereignisse, die angeben, wie einzelne Datensätze in der Tabelle geändert werden, in sein Binärlog.

Bei der klassischen anweisungsbasierten Replikation kann es Probleme mit der Replikation gespeicherter Routinen geben. Diese Probleme können Sie umgehen, indem Sie stattdessen die datensatzbasierte Replikation benutzen. Eine umfassende Liste möglicher Probleme finden Sie unter Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“.

Wenn Sie MySQL aus dem Quellcode erstellen, steht die datensatzbasierte Replikation nur dann zur Verfügung, wenn Sie configure mit der Option --with-row-based-replication aufrufen.

MySQL Server verwendet standardmäßig auch dann die anweisungsbasierte Replikation, wenn MySQL mit Unterstützung der datensatzbasierten Replikation konfiguriert wurde. Wenn Sie die datensatzbasierte Replikation verwenden wollen, starten Sie den Server mit der Option --binlog-format=row, um die datensatzbasierte Replikation global (d. h. für alle Clientverbindungen) zu aktivieren. Die Option aktiviert automatisch auch innodb_locks_unsafe_for_binlog, was bei der datensatzbasierten Replikation sicher zu verwenden ist.

Die anweisungsbasierte Replikation kann beim Serverstart entweder durch Angabe von --binlog-format=statement oder durch vollständiges Weglassen der Option --binlog-format ausgewählt werden.

Die datensatzbasierte Replikation bewirkt, dass die meisten Änderungen unter Verwendung des datensatzbasierten Formats in das Binärlog geschrieben werden. Allerdings müssen einige Änderungen auch als Anweisungen in das Binärlog geschrieben werden:

  • ANALYZE TABLE

  • REPAIR TABLE

  • OPTIMIZE TABLE

Die Option --binlog-row-event-max-size ist für Server verfügbar, die die datensatzbasierte Replikation unterstützen. Datensätze werden in Blöcken von einer Größe in das Binärlog geschrieben, die den Wert dieser Option nicht übersteigt. Der Wert muss ein Vielfaches von 256 sein, Standard ist 1024.

6.4. Replikation: Implementationsdetails

Die MySQL-Replikation wird unter Verwendung von drei Threads implementiert: einem auf dem Master und zweien auf dem Slave. Wenn eine START SLAVE-Anweisung auf einem Slave-Server abgesetzt wird, erstellt der Slave einen I/O-Thread, der eine Verbindung zum Master herstellt und ihn auffordert, die in seinen Binärlogs aufgezeichneten Änderungen zu senden. Der Master erstellt daraufhin einen Thread, um die Inhalte des Binärlogs an den Slave zu senden. Dieser Thread erscheint als Binlog Dump in der Ausgabe von SHOW PROCESSLIST auf dem Master. Der Slave-I/O-Thread liest die Aktualisierungen, die der Binlog Dump-Thread des Masters sendet, und kopiert diese in lokale Dateien, die Relay-Logs heißen und sich im Datenverzeichnis des Slaves befinden. Der dritte Thread ist der SQL-Thread, den der Slave erstellt, um die Relay-Logs zu lesen und die enthaltenen Aktualisierungen auszuführen.

In der vorhergehenden Beschreibung wurden drei Threads pro Master/Slave-Verbindung beschrieben. Ein Master, der mehrere Slaves hat, erstellt einen Thread pro aktuell angeschlossenem Slave, und jeder Slave hat seine eigenen I/O- und SQL-Threads.

Der Slave verwendet zwei Threads, d. h., das Lesen der Updates vom Master und ihre Ausführung können auf zwei unabhängige Tasks verteilt werden. Auf diese Weise wird der Task zum Lesen der Anweisungen auch dann nicht verlangsamt, wenn die Anweisungsausführung selbst langsam erfolgt. Wenn beispielsweise der Slave-Server eine Zeit lang nicht ausgeführt wurde und dann gestartet wird, kann sein I/O-Thread schnell alle Inhalte des Binärlogs vom Master holen – und zwar auch dann, wenn der SQL-Thread nicht mitkommt. Sollte der Slave beendet werden, bevor der SQL-Thread alle erhaltenen Anweisungen ausgeführt hat, so hat der I/O-Thread zumindest alles abgerufen, d. h., eine sichere Kopie der Anweisungen ist lokal in den Relay-Logs auf dem Slave gespeichert und kann beim nächsten Start des Servers direkt ausgeführt werden. Auf diese Weise kann der Master-Server seine Binärlogs schneller bereinigen, da er nicht mehr warten muss, bis der Slave die Inhalte abgerufen hat.

Die SHOW PROCESSLIST-Anweisung vermittelt Informationen dazu, welche replikationsbezogenen Vorgänge auf Master und Slave ablaufen. Das folgende Beispiel veranschaulicht, wie die drei Threads in der Ausgabe von SHOW PROCESSLIST erscheinen.

Auf dem Master-Server sieht die Ausgabe von SHOW PROCESSLIST wie folgt aus:

  mysql> SHOW PROCESSLIST\G
  *************************** 1. row ***************************
  Id: 2
  User: root
  Host: localhost:32931
  db: NULL
  Command: Binlog Dump
  Time: 94
  State: Has sent all binlog to slave; waiting for binlog to
  be updated
  Info: NULL

Hierbei ist Thread 2 ein Binlog Dump-Replikations-Thread für einen angeschlossenen Slave. State gibt an, dass alle anhängigen Aktualisierungen an den Slave gesendet wurden und der Master darauf wartet, dass neue Änderungen stattfinden. Wenn keine Binlog Dump-Threads auf einem Master vorhanden sind, bedeutet dies, dass die Replikation nicht ausgeführt wird, d. h., es sind derzeit keine Slaves angebunden.

Auf dem Slave-Server sieht die Ausgabe von SHOW PROCESSLIST wie folgt aus:

  *************************** 1. row ***************************
  Id: 10
  User: system user
  Host:
  db: NULL
  Command: Connect
  Time: 11
  State: Waiting for master to send event
  Info: NULL
  *************************** 2. row ***************************
  Id: 11
  User: system user
  Host:
  db: NULL
  Command: Connect
  Time: 11
  State: Has read all relay log; waiting for the slave I/O
  thread to update it
  Info: NULL

Hieraus ist ersichtlich, dass Thread 10 der I/O-Thread ist, der mit dem Master-Server kommuniziert. Thread 11 ist der SQL-Thread, der die Updates verarbeitet, die in den Relay-Logs gespeichert sind. Zum Zeitpunkt der Ausführung von SHOW PROCESSLIST waren beide Threads beschäftigungslos und warteten auf weitere Aktualisierungen.

Der Wert in der Spalte Time zeigt ggf., wie groß der Rückstand zwischen Slave und Master ist. Siehe auch Abschnitt 6.11, „Replikation: häufig gestellte Fragen“.

6.4.1. Thread-Zustände des Replikationsmasters

Die folgende Liste zeigt die häufigsten Statusangaben, die in der Spalte State für den Binlog Dump-Thread des Masters erscheinen können. Wenn keine Binlog Dump-Threads auf einem Master vorhanden sind, bedeutet dies, dass die Replikation nicht ausgeführt wird, d. h., es sind derzeit keine Slaves angebunden.

  • Sending binlog event to slave

    Binärlogs enthalten Ereignisse, wobei ein Ereignis normalerweise eine Änderung sowie zugehörige Informationen umfasst. Der Thread hat ein Ereignis aus dem Binärlog gelesen und sendet dieses nun an den Slave.

  • Finished reading one binlog; switching to next binlog

    Der Thread hat das Lesen einer Binärlogdatei beendet und öffnet die nächste, um sie an den Slave zu senden.

  • Has sent all binlog to slave; waiting for binlog to be updated

    Der Thread hat alle anhängigen Updates aus den Binärlogs gelesen und an den Slave gesendet. Er ist nun untätig und wartet auf neue Ereignisse, die aufgrund von Änderungen am Master in das Binärlog geschrieben werden.

  • Waiting to finalize termination

    Eine nur ganz kurz angezeigte Statusangabe, die besagt, dass der Thread gerade beendet wird.

6.4.2. I/O-Thread-Zustände von Replikationsslaves

Die folgende Liste zeigt die häufigsten Statusangaben, die in der Spalte State für den I/O-Thread auf dem Slave-Server erscheinen können. Dieser Status erscheint auch in der Spalte Slave_IO_State, die von SHOW SLAVE STATUS angezeigt wird. Sie können also mit dieser Anweisung einen guten Eindruck davon erhalten, was gerade passiert.

  • Connecting to master

    Der Thread versucht, eine Verbindung zum Master herzustellen.

  • Checking master version

    Eine Statusangabe, die nur ganz kurz angezeigt wird, nachdem die Verbindung zum Master erfolgreich hergestellt werden konnte.

  • Registering slave on master

    Eine Statusangabe, die nur ganz kurz angezeigt wird, nachdem die Verbindung zum Master erfolgreich hergestellt werden konnte.

  • Requesting binlog dump

    Eine Statusangabe, die nur ganz kurz angezeigt wird, nachdem die Verbindung zum Master erfolgreich hergestellt werden konnte. Der Thread fordert beim Master die Inhalte der Binärlogs beginnend bei der angegebenen Binärlogdatei und Position an.

  • Waiting to reconnect after a failed binlog dump request

    Wenn die Anforderung des Binärlogs fehlgeschlagen ist (etwa aufgrund eines Verbindungsabbruchs), dann wechselt der Thread in diesen Status, solange er schläft, versucht aber in regelmäßigen Abständen, die Verbindung wiederherzustellen. Das Intervall zwischen den Verbindungsversuchen kann mit der Option --master-connect-retry angegeben werden.

  • Reconnecting after a failed binlog dump request

    Der Thread versucht, erneut eine Verbindung zum Master herzustellen.

  • Waiting for master to send event

    Der Thread hat die Verbindung zum Master hergestellt und wartet auf das Eintreffen von Binärlogereignissen. Dies kann recht lange dauern, wenn der Master untätig ist. Dauert der Wartevorgang länger als slave_read_timeout Sekunden, dann tritt eine Zeitüberschreitung auf. Der Thread geht dann davon aus, dass die Verbindung abgebrochen ist, und versucht, sie neu herzustellen.

  • Queueing master event to the relay log

    Der Thread hat ein Ereignis gelesen und kopiert es in sein Relay-Log, damit der SQL-Thread es verarbeiten kann.

  • Waiting to reconnect after a failed master event read

    Ein Lesefehler ist aufgetreten (aufgrund eines Verbindungsabbruchs). Der Thread schläft für master-connect-retry Sekunden und versucht dann, die Verbindung neu herzustellen.

  • Reconnecting after a failed master event read

    Der Thread versucht, erneut eine Verbindung zum Master herzustellen. Wenn die Verbindung wiederhergestellt werden konnte, wechselt der Status zu Waiting for master to send event.

  • Waiting for the slave SQL thread to free enough relay log space

    Sie verwenden einen relay_log_space_limit-Wert ungleich null. Die Relay-Logs sind in ihrer Summe auf eine Größe angewachsen, die diesen Wert überschreitet. Der I/O-Thread wartet, bis der SQL-Thread durch die Verarbeitung von Relay-Log-Inhalten genug Speicher freigegeben hat, sodass Relay-Logs gelöscht werden können.

  • Waiting for slave mutex on exit

    Eine Statusangabe, die beim Beenden des Threads ganz kurz angezeigt wird.

6.4.3. SQL-Thread-Zustände von Replikationsslaves

Die folgende Liste zeigt die häufigsten Statusangaben, die in der Spalte State für den SQL-Thread auf dem Slave-Server erscheinen können.

  • Reading event from the relay log

    Der Thread hat ein Ereignis aus dem Relay-Log gelesen, sodass dieses Ereignis verarbeitet werden kann.

  • Has read all relay log; waiting for the slave I/O thread to update it

    Der Thread hat alle Ereignisse in den Relay-Log-Dateien verarbeitet und wartet nun darauf, dass der I/O-Thread neue Ereignisse in das Relay-Log schreibt.

  • Waiting for slave mutex on exit

    Eine nur ganz kurz angezeigte Statusangabe, die besagt, dass der Thread gerade beendet wird.

Die Spalte State für den I/O-Thread kann auch den Text einer Anweisung anzeigen. Das bedeutet, dass der Thread ein Ereignis aus dem Relay-Log gelesen und die Anweisung daraus extrahiert hat und diese nun ausführt.

6.4.4. Relay- und Statusdateien bei der Replikation

Standardmäßig haben Dateinamen von Relay-Logs die Form host_name-relay-bin.nnnnnn. Hierbei ist host_name der Name des Slave-Serverhosts und nnnnnn eine Sequenznummer. Aufeinander folgende Relay-Log-Dateien werden mit laufenden Sequenznummern beginnend bei 000001 erstellt. Der Slave verwendet eine Indexdatei, um die Übersicht über die derzeit verwendeten Relay-Log-Dateien zu behalten. Der Standardname der Relay-Log-Indexdatei lautet host_name-relay-bin.index. Standardmäßig erstellt der Slave-Server die Relay-Log-Dateien in seinem Datenverzeichnis. Die Standarddateinamen können mit den Serveroptionen --relay-log und --relay-log-index außer Kraft gesetzt werden. Siehe auch Abschnitt 6.9, „Replikationsoptionen in my.cnf“.

Relay-Logs haben dasselbe Format wie Binärlogs und können mit mysqlbinlog gelesen werden. Der SQL-Thread löscht eine Relay-Log-Datei automatisch, sobald er alle Ereignisse in dieser Datei ausgeführt hat und sie nicht mehr benötigt. Es gibt keine dedizierte Methode zum Löschen von Relay-Logs – der SQL-Thread kümmert sich selbst darum. Allerdings rotiert FLUSH LOGS die Relay-Logs, was Auswirkungen darauf hat, wann der SQL-Thread sie löscht.

Ein Slave-Server erstellt unter den folgenden Bedingungen eine neue Relay-Log-Datei:

  • bei jedem Start des I/O-Threads

  • wenn die Logs – beispielsweise mit FLUSH LOGS oder mysqladmin flush-logs – synchronisiert werden

  • wenn die aktuelle Relay-Log-Datei zu groß wird. Die Bedeutung von „zu groß“ ermitteln Sie wie folgt:

    • Wenn der Wert von max_relay_log_size größer als 0 ist, gibt er die maximale Größe einer Relay-Log-Datei an.

    • Wenn der Wert von max_relay_log_size 0 ist, bestimmt max_binlog_size die maximale Größe einer Relay-Log-Datei.

Ein Slave-Replikationsserver erstellt zwei weitere kleine Dateien im Datenverzeichnis. Diese Statusdateien heißen standardmäßig master.info und relay-log.info. Die Namen können mit den Optionen --master-info-file und --relay-log-info-file geändert werden. Siehe auch Abschnitt 6.9, „Replikationsoptionen in my.cnf“.

Die beiden Statusdateien enthalten Informationen wie die in der Ausgabe der Anweisung SHOW SLAVE STATUS gezeigte (siehe auch Abschnitt 13.6.2, „SQL-Anweisungen für die Steuerung von Slave-Servern“). Weil die Statusdateien auf der Festplatte gespeichert sind, überdauern sie das Herunterfahren des Slave-Servers. Beim nächsten Start des Servers liest er die beiden Dateien dann aus, um zu ermitteln, wie weit er beim Lesen der Binärlogs vom Master und bei der Verarbeitung der eigenen Relay-Logs gekommen ist.

Der I/O-Thread aktualisiert die Datei master.info. Die folgende Tabelle zeigt die Entsprechungen zwischen den Zeilen in der Datei und den von SHOW SLAVE STATUS angezeigten Spalten.

ZeileBeschreibung
1Anzahl der Zeilen in der Datei
2Master_Log_File
3Read_Master_Log_Pos
4Master_Host
5Master_User
6Passwort (wird von SHOW SLAVE STATUS nicht angezeigt)
7Master_Port
8Connect_Retry
9Master_SSL_Allowed
10Master_SSL_CA_File
11Master_SSL_CA_Path
12Master_SSL_Cert
13Master_SSL_Cipher
14Master_SSL_Key

Der SQL-Thread aktualisiert die Datei relay-log.info. Die folgende Tabelle zeigt die Entsprechungen zwischen den Zeilen in der Datei und den von SHOW SLAVE STATUS angezeigten Spalten.

ZeileBeschreibung
1Relay_Log_File
2Relay_Log_Pos
3Relay_Master_Log_File
4Exec_Master_Log_Pos

Wenn Sie die Daten des Slaves sichern, sollten Sie neben den Relay-Log-Dateien auch diese beiden Statusdateien sichern. Sie werden stets benötigt, um die Replikation nach Wiederherstellung der Daten auf dem Slave fortzusetzen. Wenn Sie die Relay-Logs verlieren, aber noch über die Datei relay-log.info verfügen, können Sie ermitteln, wie weit der SQL-Thread die Binärlogs des Masters bereits ausgeführt hatte. Dann können Sie den Slave durch Absetzen von CHANGE MASTER TO mit den Optionen MASTER_LOG_FILE und MASTER_LOG_POS anweisen, die Binärlogs von diesem Punkt an erneut zu lesen. (Dies setzt natürlich voraus, dass die Binärlogs noch auf dem Master-Server vorhanden sind.)

Wenn Ihr Slave Gegenstand der Replikation von LOAD DATA INFILE-Anweisungen ist, sollten Sie auch alle SQL_LOAD-*-Dateien sichern, die in dem vom Slave zu diesem Zweck verwendeten Verzeichnis vorhanden sind. Der Slave benötigt diese Dateien, um die Replikation unterbrochener LOAD DATA INFILE-Operationen fortzusetzen. Die Verzeichnisposition wird mit der Option --slave-load-tmpdir angegeben. Wird die Option nicht angegeben, dann bezeichnet der Wert der Systemvariablen tmpdir die Verzeichnisposition.

6.5. Wie man eine Replikation aufsetzt

Dieser Abschnitt beschreibt kurz, wie man die vollständige Replikation eines MySQL Servers konfiguriert. Es wird angenommen, dass Sie alle Datenbanken auf dem Master replizieren wollen und die Replikation zuvor noch nicht konfiguriert haben. Sie müssen Ihren Master-Server kurz herunterfahren, um die beschriebenen Schritte vollständig durchführen zu können.

Beschrieben wird der Vorgang für die Konfiguration eines einzelnen Slaves; mehrere Slaves können Sie konfigurieren, indem Sie die entsprechenden Schritte wiederholen.

Zwar ist diese Vorgehensweise die direkteste zur Konfiguration eines Slaves, sie ist aber nicht die einzige. Wenn Sie beispielsweise eine Momentaufnahme der Daten auf dem Master haben und auf diesem bereits die Serverkennung eingestellt und das binäre Loggen aktiviert ist, dann können Sie einen Slave konfigurieren, ohne den Master herunterzufahren oder auch nur Aktualisierungen zu unterbinden. Weitere Informationen finden Sie unter Abschnitt 6.11, „Replikation: häufig gestellte Fragen“.

Wenn Sie eine MySQL-Replikationskonfiguration administrieren wollen, sollten Sie dieses Kapitel vollständig lesen und alle Anweisungen ausprobieren, die in Abschnitt 13.6.1, „SQL-Anweisungen für die Steuerung von Master-Servern“, und Abschnitt 13.6.2, „SQL-Anweisungen für die Steuerung von Slave-Servern“, beschrieben sind. Ferner sollten Sie sich mit den Replikationsstartoptionen vertraut machen, die in Abschnitt 6.9, „Replikationsoptionen in my.cnf“, erläutert werden.

Hinweis: Diese Methode und einige der replikationsspezifischen SQL-Anweisungen, die in späteren Abschnitten beschrieben werden, erfordern die Berechtigung SUPER.

  1. Vergewissern Sie sich, dass die auf dem Master und dem Slave installierten MySQL-Versionen kompatibel im Sinne der in Abschnitt 6.6, „Replikation: Kompatibilität zwischen MySQL-Versionen“, aufgeführten Tabelle sind. Im Idealfall sollten Sie die jeweils aktuellste MySQL-Version sowohl auf dem Master als auch auf dem Slave verwenden.

    Wenn Sie auf ein Problem stoßen, melden Sie dieses bitte erst als Bug, nachdem Sie sich vergewissert haben, dass es auch im aktuellen MySQL-Release vorhanden ist.

  2. Konfigurieren Sie ein Konto auf dem Master-Server, über das der Slave eine Verbindung herstellen kann. Dieses Konto benötigt die Berechtigung REPLICATION SLAVE. Wenn das Konto ausschließlich zur Replikation verwendet wird (was wir empfehlen), dann brauchen Sie keine weiteren Berechtigungen zu gewähren.

    Nehmen wir nun an, dass Ihre Domäne mydomain.com heißt und dass Sie ein Konto mit dem Benutzernamen repl erstellen wollen, das Slave-Server unter Angabe des Passworts slavepass von einem beliebigen Host in Ihrer Domäne aus für den Zugriff auf den Master verwenden kann. Dieses Konto erstellen Sie mit folgender GRANT-Anweisung:

    mysql> GRANT REPLICATION SLAVE ON *.*
        -> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
    

    Beabsichtigen Sie, die Anweisungen LOAD TABLE FROM MASTER oder LOAD DATA FROM MASTER auf dem Slave-Host zu verwenden, dann müssen Sie diesem Konto weitere Berechtigungen gewähren:

    • Gewähren Sie dem Konto die globalen Berechtigungen SUPER und RELOAD.

    • Gewähren Sie die Berechtigung SELECT für alle Tabellen, die Sie laden wollen. Alle Master-Tabellen, für die das Konto keine SELECT-Berechtigung hat, werden von LOAD DATA FROM MASTER ignoriert.

    Weitere Informationen zur Konfiguration von Benutzerkonten und Berechtigungen finden Sie in Abschnitt 5.9, „MySQL-Benutzerkontenverwaltung“.

  3. Synchronisieren Sie alle Tabellen und unterbinden Sie Schreibanweisungen, indem Sie eine FLUSH TABLES WITH READ LOCK-Anweisung ausführen:

    mysql> FLUSH TABLES WITH READ LOCK;
    

    Beachten Sie, dass FLUSH TABLES WITH READ LOCK bei InnoDB-Tabellen auch COMMIT-Operationen sperrt. Wenn Sie eine globale Lesesperre erwirkt haben, können Sie eine Dateisystem-Momentaufnahme Ihrer InnoDB-Tabellen erstellen. Intern (d. h. innerhalb der InnoDB-Speicher-Engine) ist diese Momentaufnahme nicht konsistent, weil die InnoDB-Caches nicht synchronisiert wurden, aber dies ist nicht weiter problematisch, weil InnoDB dieses Problem beim Start beseitigt und ein konsistentes Ergebnis abliefert. Das bedeutet, dass bei InnoDB die Wiederherstellung von Daten nach einem Absturz verlustfrei möglich ist, wenn der Neustart auf der Basis dieser Momentaufnahme erfolgt. Allerdings gibt es keine Möglichkeit, den MySQL Server zu beenden und gleichzeitig eine konsistente Momentaufnahme Ihrer InnoDB-Tabellen zu gewährleisten.

    Lassen Sie den Client laufen, von dem aus Sie die FLUSH TABLES-Anweisung absetzen, damit die Lesesperre aktiv bleibt. (Wenn Sie den Client beenden, wird die Sperre aufgehoben.) Erstellen Sie nun eine Momentaufnahme der Daten auf Ihrem Master-Server.

    Die einfachste Möglichkeit zur Erstellung einer Momentaufnahme ist die Verwendung eines Archivierungsprogramms: Hiermit erstellen Sie eine binäre Sicherung der Datenbanken im Datenverzeichnis Ihres Master-Servers. Sie können beispielsweise tar unter Unix oder PowerArchiver, WinRAR, WinZip oder eine ähnliche Software unter Windows verwenden. Um mit tar ein Archiv zu erstellen, das alle Datenbanken enthält, wechseln Sie in das Datenverzeichnis des Master-Servers und führen dann folgenden Befehl aus:

    shell> tar -cvf /tmp/mysql-snapshot.tar .
    

    Wollen Sie, dass das Archiv nur eine Datenbank namens this_db enthält, dann verwenden Sie stattdessen folgenden Befehl:

    shell> tar -cvf /tmp/mysql-snapshot.tar ./this_db
    

    Danach kopieren Sie die Archivdatei in das Verzeichnis /tmp auf dem Slave-Serverhost. Auf diesem System wechseln Sie nun in das Datenverzeichnis des Slaves und entpacken die Archivdatei mithilfe des folgenden Befehls:

    shell> tar -xvf /tmp/mysql-snapshot.tar
    

    Wenn auf dem Slave-Server andere Benutzerkonten als auf dem Master vorhanden sind, sollten Sie die Datenbank mysql unter Umständen nicht replizieren. In diesem Fall sollten Sie sie aus dem Archiv ausschließen. Ferner sollten Sie weder Logdateien noch die Dateien master.info oder relay-log.info in das Archiv einfügen.

    Während die mit FLUSH TABLES WITH READ LOCK erwirkte Lesesperre gültig ist, lesen Sie den Namen des aktuellen Binärlogs und den Versatz auf dem Master aus:

    mysql > SHOW MASTER STATUS;
    +---------------+----------+--------------+------------------+
    | File          | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +---------------+----------+--------------+------------------+
    | mysql-bin.003 | 73       | test         | manual,mysql     |
    +---------------+----------+--------------+------------------+
    

    Die Spalte File zeigt den Namen der Logdatei an, Position den Versatz innerhalb der Datei. In diesem Beispiel heißt die Binärlogdatei mysql-bin.003, der Versatz ist 73. Notieren Sie diese Werte. Sie benötigen sie später beim Konfigurieren des Slaves. Die Werte stellen die Replikationskoordinaten dar, bei denen der Slave die Verarbeitung neuer Updates vom Master startet.

    Wenn der Master zuvor ohne aktiviertes Binärloggen ausgeführt wurde, sind die von SHOW MASTER STATUS oder mysqldump --master-data angezeigten Werte für Lognamen und Position leer. In diesem Fall lauten die Werte, die Sie später als Logdateinamen und Position auf dem Slave angeben müssen, '' (Leer-String) und 4.

    Nachdem Sie die Momentaufnahme erstellt und Lognamen und Versatz aufgezeichnet haben, können Sie die Schreibaktivitäten auf dem Master neu starten:

    mysql> UNLOCK TABLES;
    

    Wenn Sie InnoDB-Tabellen einsetzen, sollten Sie im Idealfall das Tool InnoDB Hot Backup verwenden, welches ohne Sperre auf dem Master-Server eine konsistente Momentaufnahme erstellt und Lognamen und Versatz passend für die Momentaufnahme speichert, sodass die Angaben später auf dem Slave benutzt werden können. Hot Backup ist ein kommerzielles (d. h. nicht kostenloses) Zusatztool, das nicht Bestandteil der MySQL-Standarddistribution ist. Weitere Informationen finden Sie auf der Homepage von InnoDB Hot Backup unter http://www.innodb.com/manual.php.

    Wenn Sie Hot Backup nicht einsetzen, besteht die schnellste Methode zur Erstellung einer binären Momentaufnahme der InnoDB-Tabellen darin, den Master-Server herunterzufahren und die Datendateien, Logdateien und Tabellenformatdateien (.frm) von InnoDB zu kopieren. Um den aktuellen Logdateinamen und den Versatz aufzuzeichnen, sollten Sie folgende Anweisungen absetzen, bevor Sie den Server herunterfahren:

    mysql> FLUSH TABLES WITH READ LOCK;
    mysql> SHOW MASTER STATUS;
    

    Dann notieren Sie Lognamen und Versatz aus der Ausgabe von SHOW MASTER STATUS wie oben beschrieben. Danach fahren Sie den Server herunter, ohne die Tabellen zu entsperren; hierdurch ist sicherstellt, dass der Server mit einem Status beendet wird, der den Angaben zu Logdatei und Versatz entspricht:

    shell> mysqladmin -u root shutdown
    

    Eine Alternative, die sowohl bei MyISAM- als auch bei InnoDB-Tabellen funktioniert, besteht darin, einen SQL-Speicherauszug des Masters anstatt – wie oben beschrieben – einer binären Kopie zu erstellen. Hierzu führen Sie mysqldump --master-data auf dem Master aus und laden die SQL-Speicherauszugsdatei später in Ihren Slave. Allerdings ist die Erstellung einer binären Kopie schneller.

  4. Vergewissern Sie sich, dass der Abschnitt [mysqld] der Datei my.cnf auf dem Master-Host die Option log-bin enthält. Der Abschnitt sollte ferner eine Option server-id=master_id enthalten, wobei master_id ein positiver Integer zwischen 1 und 232 – 1 sein muss. Zum Beispiel:

    [mysqld]
    log-bin=mysql-bin
    server-id=1
    

    Wenn diese Optionen nicht vorhanden sind, fügen Sie sie hinzu und starten den Server neu. Der Server kann erst als Replikationsmaster agieren, wenn das binäre Loggen aktiviert ist.

    Hinweis: Um die größtmögliche Dauerhaftigkeit und Konsistenz in einer Replikationskonfiguration für InnoDB mit Transaktionen zu erzielen, sollten Sie innodb_flush_log_at_trx_commit=1 und sync_binlog=1 in der Datei my.cnf auf dem Master angeben.

  5. Beenden Sie den Server, der als Slave vorgesehen ist, und fügen Sie in seiner Datei my.cnf die folgenden Zeilen hinzu:

    [mysqld]
    server-id=slave_id
    

    Der Wert slave_id muss wie master_id auch ein positiver Integer zwischen 1 und 232 – 1 sein. Ferner muss sich die Kennung des Slaves von der des Masters unterscheiden. Zum Beispiel:

    [mysqld]
    server-id=2
    

    Wenn Sie mehrere Slaves konfigurieren, muss jeder einen eindeutigen server-id-Wert haben, der sich von dem des Masters und von denen aller anderen Slaves unterscheidet. Betrachten Sie server-id-Werte als etwas Ähnliches wie IP-Adressen: Diese Kennungen identifizieren jede Serverinstanz in der Gruppe der Replikationspartner eindeutig.

    Wenn Sie keinen server-id-Wert angeben, wird er auf 1 gesetzt, sofern Sie master-host nicht definiert haben; andernfalls wird der Wert auf 2 gesetzt. Beachten Sie, dass, wenn Sie server-id weglassen, ein Master Verbindungen aller Slaves abweist und auch ein Slave sich weigert, eine Verbindung mit einem Master herzustellen. Auf diese Weise ist das Übergehen von server-id nur für ein Backup mit einem Binärlog geeignet.

  6. Wenn Sie eine binäre Sicherung der Daten auf dem Master-Server erstellt haben, kopieren Sie sie in das Datenverzeichnis des Slaves, bevor Sie diesen starten. Stellen Sie sicher, dass die Berechtigungen für Dateien und Verzeichnisse korrekt sind. Das Systemkonto, über das Sie den Slave-Server ausführen, muss die Dateien wie beim Master auch lesen und schreiben können.

    Wenn Sie ein Backup mit mysqldump erstellen, starten Sie den Slave zuerst. Die Speicherauszugsdatei wird in einem späteren Schritt geladen.

  7. Starten Sie den Slave-Server. Erfolgte bereits früher eine Replikation, dann starten Sie den Slave mit der Option --skip-slave-start, damit er nicht sofort versucht, eine Verbindung mit dem Master herzustellen. Sie sollten den Slave-Server außerdem mit der Option --log-warnings starten, um im Falle von Problemen (z. B. Netzwerk- oder Verbindungsproblemen) mehr Meldungen im Fehlerlog zu erhalten. Die Option ist standardmäßig aktiviert, aber abgebrochene Verbindungen werden nicht im Fehlerlog vermerkt, sofern der Optionswert nicht größer als 1 ist.

  8. Wenn Sie mit mysqldump ein Backup der Daten auf dem Master-Server erstellt haben, laden Sie die Speicherauszugsdatei in den Slave-Server:

    shell> mysql -u root -p < dump_file.sql
    
  9. Führen Sie die folgende Anweisung auf dem Slave aus und ersetzen Sie dabei die Optionswerte durch die für Ihr System geeigneten Werte:

    mysql> CHANGE MASTER TO
        -> MASTER_HOST='master_host_name',
        -> MASTER_USER='replication_user_name',
        -> MASTER_PASSWORD='replication_password',
        -> MASTER_LOG_FILE='recorded_log_file_name',
        -> MASTER_LOG_POS=recorded_log_position;
    

    Die folgende Tabelle zeigt die maximal zulässige Länge bei Optionen, die String-Werte enthalten:

    MASTER_HOST60
    MASTER_USER16
    MASTER_PASSWORD32
    MASTER_LOG_FILE255
  10. Starten Sie die Slave-Threads:

    mysql> START SLAVE;
    

Nachdem Sie diesen Vorgang durchgeführt haben, sollte der Slave eine Verbindung mit dem Master herstellen und alle Updates nachholen, die seit Erstellung der Momentaufnahme erstellt wurden.

Wenn Sie es versäumt haben, die Option server-id für den Master einzustellen, dann können Slaves keine Verbindung herstellen.

Wenn Sie es versäumt haben, die Option server-id für den Slave einzustellen, dann erhalten Sie im Fehlerlog des Slaves die folgende Meldung:

Warning: You should set server-id to a non-0 value if master_host
is set; we will force server id to 2, but this MySQL server will
not act as a slave.

Ferner werden Sie Fehlermeldungen im Fehlerlog des Slaves vorfinden, wenn eine Replikation aus irgendeinem anderen Grund nicht möglich ist.

Sobald ein Slave mit der Replikation begonnen hat, finden Sie in seinem Datenverzeichnis zwei Dateien namens master.info und relay-log.info. Der Slave verwendet diese beiden Dateien, um zu vermerken, welcher Anteil des Master-Binärlogs bereits verarbeitet wurde. Sie dürfen diese Dateien keinesfalls entfernen oder bearbeiten, sofern Sie nicht genau wissen, was Sie tun und welche Auswirkungen dies haben kann. Und auch in diesem Fall sollten Sie besser die CHANGE MASTER TO-Anweisung verwenden, um die Replikationsparameter zu ändern. Der Slave aktualisiert die Statusdateien automatisch entsprechend den Werten, die in dieser Anweisung angegeben sind.

Hinweis: Der Inhalt von master.info setzt einige der Serveroptionen, die auf der Befehlszeile oder in der Datei my.cnf angegeben sind, außer Kraft. Weitere Informationen finden Sie in Abschnitt 6.9, „Replikationsoptionen in my.cnf“.

Sobald Sie über eine Momentaufnahme des Masters verfügen, können Sie diese zur Konfiguration weiterer Slaves verwenden. Folgen Sie dabei einfach der oben beschriebenen Anleitung. Sie müssen also keine neue Momentaufnahme erstellen, sondern können dieselbe auch für jeden weiteren Slave verwenden.

6.6. Replikation: Kompatibilität zwischen MySQL-Versionen

Das Binärlogformat, wie es in MySQL 5.1 implementiert ist, unterscheidet sich erheblich von dem vorheriger Versionen. Dies gilt insbesondere für den Umgang mit Zeichensätzen, LOAD DATA INFILE und Zeitzonen.

Wir empfehlen die Verwendung der jeweils aktuellen MySQL-Version, weil die Replikationsfunktionen kontinuierlich verbessert werden. Ferner empfehlen wir die Verwendung derselben Version auf Master und Slave. Empfohlen wird außerdem die Aktualisierung von Mastern und Slaves, die unter Alpha- oder Betaversionen laufen, auf neue (Produktions-)Versionen. In vielen Fällen schlägt die Replikation von einem neueren Master auf einen älteren Slave fehl. Generell können Slaves, die unter MySQL 5.1.x laufen, mit älteren Mastern (sogar solchen unter MySQL 3.23, 4.0 oder 4.1) verwendet werden, nicht jedoch umgekehrt.

Hinweis: Sie dürfen keinesfalls eine Replikation von einem Master, der ein neueres Binärlogformat aufweist, auf einen Slave durchführen, der ein älteres Format benutzt (z. B. von MySQL 5.0 auf MySQL 4.1). Dies hat gravierende Auswirkungen auf die Aktualisierung von Replikationsservern (siehe auch Abschnitt 6.7, „Upgrade eines Replikationssetups“).

Diese Angaben beziehen sich auf die Replikationskompatibilität auf Protokollebene. Es gibt weitere Einschränkungen, z. B. bei Fragen der Kompatibilität auf SQL-Ebene. So kann etwa ein Master unter 5.1 keine Replikation auf einen Slave unter 5.0 durchführen, wenn die replizierten Anweisungen SQL-Funktionen verwenden, die zwar in 5.1, nicht aber in 5.0 vorhanden sind. Diese und andere Probleme werden in Abschnitt 6.8, „Replikation: Features und bekannte Probleme“, behandelt.

6.7. Upgrade eines Replikationssetups

Wenn Sie Server aktualisieren, die Bestandteile einer Replikationskonfiguration sind, hängt die Vorgehensweise zur Aktualisierung von den aktuellen Serverversionen und der Version ab, auf die Sie aktualisieren.

6.7.1. Replikation: Upgrade auf 5.0

Dieser Abschnitt betrifft die Aktualisierung der Replikation von MySQL 3.23, 4.0 oder 4.1 auf MySQL 5.1. Ein 4.0-Server sollte unter Version 4.0.3 oder höher laufen.

Wenn Sie einen Master von einer früheren MySQL-Release-Serie auf 5.1 aktualisieren, dann müssen Sie zuallererst einmal gewährleisten, dass alle Slaves dieses Masters denselben 5.1.x-Release verwenden. Ist dies nicht der Fall, dann sollten Sie zuerst die Slaves aktualisieren. Um einen Slave zu aktualisieren, fahren Sie ihn herunter, aktualisieren ihn auf die entsprechende Version 5.1.x und starten nachfolgend zunächst den Server und dann die Replikation neu. Der 5.1-Slave kann alte Relay-Logs, die vor dem Upgrade geschrieben wurden, lesen und die enthaltenen Anweisungen ausführen. Relay-Logs, die vom Slave nach dem Upgrade erstellt wurden, haben bereits das 5.1-Format.

Nachdem die Slaves aktualisiert wurden, fahren Sie den Master herunter, aktualisieren ihn auf denselben 5.1.x-Release wie die Slaves und starten ihn dann neu. Der 5.1-Master kann alte Binärlogs, die vor dem Upgrade geschrieben wurden, lesen und an die 5.1-Slaves schicken. Die Slaves erkennen das alte Format und verarbeiten es entsprechend. Binärlogs, die vom Master nach dem Upgrade erstellt wurden, haben bereits das 5.1-Format. Auch diese werden von den 5.1-Slaves erkannt.

Es sind also bei der Aktualisierung auf MySQL 5.1 keine weiteren Maßnahmen durchzuführen – Sie müssen lediglich beachten, dass Sie ggf. zuerst die Slaves auf MySQL 5.1 aktualisieren, bevor Sie dies beim Master tun. Beachten Sie, dass ein Downgrade von 5.1 auf ältere Versionen nicht so einfach ist: Sie müssen gewährleisten, dass alle Binär- und Relay-Logs im 5.1-Format vollständig verarbeitet wurden, damit Sie sie entfernen können, bevor Sie mit dem Downgrade fortfahren.

Das Downgrade einer Replikationskonfiguration auf eine ältere Version ist nicht mehr möglich, wenn Sie von der anweisungs- auf die datensatzbasierte Replikation umgestellt haben und die erste datensatzbasierte Anweisung in das Binärlog geschrieben wurde. Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“.

6.8. Replikation: Features und bekannte Probleme

Generell erfordert die Replikationskompatibilität auf SQL-Ebene, dass alle verwendeten Funktionen sowohl vom Master als auch vom Slave unterstützt werden. Wenn Sie eine Funktion auf einem Master-Server verwenden, die nur ab einer bestimmten MySQL-Version verfügbar ist, dann können Sie keine Replikation auf einen Slave vornehmen, der älter ist als diese Version. Derartige Inkompatibilitäten treten häufig zwischen verschiedenen Serien auf. So können Sie beispielsweise keine Replikation von MySQL 5.1 auf 5.0 durchführen. Allerdings können solche Inkompatibilitäten auch innerhalb derselben Serie auftreten. So ist beispielsweise die Funktion SLEEP() seit MySQL 5.0.12 verfügbar. Wenn Sie diese Funktion auf dem Master-Server verwenden, können Sie sie nicht auf einen Slave replizieren, der älter ist als MySQL 5.0.12.

Beabsichtigen Sie, die Replikation zwischen MySQL 5.1 und einer älteren Version durchzuführen, dann sollten Sie im MySQL-Referenzhandbuch zu dieser älteren Release-Serie nach Informationen zu den Replikationseigenschaften dieser Serie suchen.

Die folgende Liste enthält genauere Angaben dazu, was unterstützt wird und was nicht. Zusätzliche InnoDB-spezifische Informationen zur Replikation finden Sie in Abschnitt 14.2.6.5, „InnoDB und MySQL-Replikation“.

Bei der klassischen anweisungsbasierten Replikation kann es Probleme mit der Replikation gespeicherter Routinen geben. Diese Probleme können Sie umgehen, indem Sie stattdessen die datensatzbasierte Replikation benutzen. Eine umfassende Liste möglicher Probleme finden Sie unter Abschnitt 19.4, „Binärloggen gespeicherter Routinen und Trigger“. Eine Beschreibung der datensatzbasierten Replikation finden Sie in Abschnitt 6.3, „Zeilenbasierte Replikation“.

  • Die Replikation von AUTO_INCREMENT-, LAST_INSERT_ID()- und TIMESTAMP-Werten erfolgt korrekt.

  • Die Funktionen USER(), UUID() und LOAD_FILE() werden ohne Änderung repliziert und funktionieren daher nur dann korrekt auf dem Slave, wenn die datensatzbasierte Replikation aktiviert ist. (Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“.)

  • Die folgende Beschränkung gilt nur für die anweisungsbasierte, nicht für die datensatzbasierte Replikation. Die Funktionen GET_LOCK(), RELEASE_LOCK(), IS_FREE_LOCK() und IS_USED_LOCK(), die Sperren auf Benutzerebene verwalten, werden repliziert, ohne dass der Slave den zugehörigen Kontext auf dem Master kennt. Aus diesem Grund sollten diese Funktionen nicht zum Einfügen in eine Tabelle auf dem Master verwendet werde, da der Kontext auf dem Slave ganz anders aussehen würde. (So sollten Sie etwa keine Anweisung wie INSERT INTO mytable VALUES(GET_LOCK(...)) absetzen.)

  • Die Variablen FOREIGN_KEY_CHECKS, SQL_MODE, UNIQUE_CHECKS und SQL_AUTO_IS_NULL werden (ab MySQL 5.0) alle repliziert. Die Systemvariable storage_engine (die auch table_type heißt) wird in MySQL 5.1 noch nicht repliziert, was für die Replikation zwischen verschiedenen Speicher-Engines von Vorteil ist.

  • Die Replikation funktioniert zwischen Mastern und Slaves unter MySQL 5.0 und 5.1 in beliebiger Kombination – auch dann, wenn Master und Slave unterschiedliche Werte für die Zeichensatz- und/oder die globalen Zeitzonenvariablen aufweisen. (Beachten Sie, dass dies nicht in Fällen zutrifft, in denen Master und/oder Slave unter MySQL 4.1 oder früher laufen.)

  • Folgendes gilt für die Replikation zwischen MySQL Servern, die unterschiedliche Zeichensätze benutzen:

    1. Wenn der Master MySQL 4.1 verwendet, müssen Sie immer dieselben globalen Werte für Zeichensatz und Sortierfolge auf dem Master und dem Slave verwenden – unabhängig davon, welche MySQL-Version auf dem Slave läuft. (Diese werden von den Optionen --character-set-server und --collation-server gesteuert.) Andernfalls kann es Fehler aufgrund von Schlüsseldubletten auf dem Slave geben, da ein Schlüssel, der im Zeichensatz des Masters eindeutig ist, dies im Zeichensatz des Slaves nicht unbedingt sein muss. Beachten Sie, dass dies keine Rolle mehr spielt, wenn Master und Slave beide unter MySQL 5.0 oder höher laufen.

    2. Wenn der Master älter ist als MySQL 4.1.3, dann sollte auf den beteiligten Clients kein anderer Zeichensatz als der global angegebene verwendet werden, weil der Slave eine solche Änderung des Zeichensatzes nicht bemerkt. Clients sollten also SET NAMES, SET CHARACTER SET usw. nicht benutzen. Wenn sowohl Master als auch Slave unter 4.1.3 oder höher laufen, können die Clients die zeichensatzbezogenen Sitzungsvariablen frei einstellen, da diese Werte in das Binärlog geschrieben und auf diese Weise dem Slave mitgeteilt werden. Clients können also SET NAMES oder SET CHARACTER SET verwenden oder Variablen wie COLLATION_CLIENT oder COLLATION_SERVER einstellen. Nicht ändern können Clients hingegen den globalen Wert dieser Variablen: Wie bereits gesagt, Master und Slave müssen für den globalen Zeichensatz immer identische Werte aufweisen.

    3. Wenn sich auf dem Master Datenbanken mit Zeichensätzen befinden, die sich vom globalen character_set_server-Wert unterscheiden, dann sollten Sie Ihre CREATE TABLE-Anweisungen so formulieren, dass Tabellen in diesen Datenbanken nicht implizit auf den Standardzeichensatz der Datenbank angewiesen sind (siehe auch Bug 2326). Ein guter Workaround hierfür besteht darin, in der CREATE TABLE-Anweisung Zeichensatz und Sortierfolge explizit anzugeben.

  • Wenn der Master MySQL 4.1 verwendet, dann sollte auf Master und Slave dieselbe Systemzeitzone eingestellt sein. Andernfalls werden einige Anweisungen – wie etwa solche, die die Funktionen NOW() oder FROM_UNIXTIME() verwenden – nicht korrekt repliziert. Sie können die Zeitzone, in der der MySQL Server läuft, mit der Option --timezone=timezone_name des Skripts mysqld_safe oder durch Einstellen der Umgebungsvariablen TZ ändern. Master und Slave sollten ferner auch dieselbe Standardeinstellung für die Verbindungszeitzone aufweisen, d. h., der Wert des Parameters --default-time-zone sollte auf Master und Slave gleich sein. Beachten Sie, dass dies nicht notwendig ist, wenn der Master unter MySQL 5.0 oder höher läuft.

  • CONVERT_TZ(...,...,@session.time_zone) wird nur dann korrekt repliziert, wenn Master und Slave unter MySQL 5.0.4 oder höher laufen.

  • Sitzungsvariablen werden nicht korrekt repliziert, wenn sie in Anweisungen verwendet werden, die Tabellen aktualisieren. So fügt SET MAX_JOIN_SIZE=1000 gefolgt von INSERT INTO mytable VALUES(@MAX_JOIN_SIZE) auf dem Master nicht dieselben Daten ein wie auf dem Slave. Dies betrifft allerdings nicht die gängige Sequenz aus SET TIME_ZONE=... gefolgt von INSERT INTO mytable VALUES(CONVERT_TZ(...,...,@time_zone)).

    Die Replikation von Sitzungsvariablen ist kein Problem, wenn die datensatzbasierte Replikation benutzt wird. Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“.

  • Es ist auch möglich, transaktionssichere Tabellen auf dem Master in nichttransaktionssichere Tabellen auf dem Slave zu replizieren. Sie können beispielsweise eine InnoDB-Tabelle auf dem Master als MyISAM-Tabelle auf dem Slave replizieren. Allerdings kommt es, wenn Sie dies tun, zu Problemen, wenn der Slave mitten in einem BEGIN/COMMIT-Block angehalten wird, weil er nachfolgend am Anfang des BEGIN-Blocks neu einstartet. Dieses Problem steht auf unserer Aufgabenliste und wird in Bälde behoben sein.

  • Änderungsanweisungen, die benutzerdefinierte Variablen (also Variablen des Typs @var_name) referenzieren, werden korrekt repliziert. (Dies gilt jedoch nicht für Versionen vor 4.1.) Beachten Sie, dass beginnend mit MySQL 5.0 bei den Namen von Benutzervariablen die Groß-/Kleinschreibung unterschieden wird, wenn Sie die Replikation zwischen MySQL 5.0 und älteren Versionen einrichten.

  • Slaves können unter Verwendung von SSL eine Verbindung zum Master herstellen.

  • Die globale Systemvariable slave_transaction_retries wirkt sich wie folgt auf die Replikation aus: Wenn ein SQL-Thread auf einem Replikationsslave eine Transaktion nicht ausführen kann, weil eine InnoDB-Blockade aufgetreten ist oder die Werte innodb_lock_wait_timeout von InnoDB bzw. TransactionDeadlockDetectionTimeout oder TransactionInactiveTimeout von NDBCluster überschritten wurden, erfolgt die durch slave_transaction_retries angegebene Anzahl von Neuversuchen, bevor der Vorgang mit einer Fehlermeldung beendet wird. Der Standardwert ist 10. Die Gesamtzahl der Neuversuche finden Sie in der Ausgabe von SHOW STATUS. (Siehe auch Abschnitt 5.2.4, „Server-Statusvariablen“.)

  • Wenn eine der Tabellenoptionen DATA DIRECTORY oder INDEX DIRECTORY in einer CREATE TABLE-Anweisung auf dem Master-Server verwendet wird, wird dieselbe Option auch auf dem Slave umgesetzt. Dies kann zu Problemen führen, wenn im Dateisystem des Slave-Hosts kein entsprechendes Verzeichnis vorhanden ist, oder wenn es zwar vorhanden ist, aber der Slave-Server nicht darauf zugreifen kann. MySQL unterstützt eine sql_mode-Option namens NO_DIR_IN_CREATE. Wenn dieser SQL-Modus am Slave-Server aktiviert ist, ignoriert der Slave die Tabellenoptionen DATA DIRECTORY und INDEX DIRECTORY beim Replizieren von CREATE TABLE-Anweisungen. Infolgedessen werden die MyISAM-Daten- und Indexdateien im Datenbankverzeichnis der Tabelle erstellt.

  • Die folgende Beschränkung betrifft nur die anweisungsbasierte Replikation, nicht die datensatzbasierte Replikation: Die Daten auf dem Master und dem Slave können verschieden werden, wenn eine Abfrage so formuliert wird, dass die Datenänderung nichtdeterministisch ist, d. h. dem Gutdünken des Abfrageoptimierers überlassen wird. (Dies ist auch abgesehen von der Replikation nicht zu empfehlen.) Eine umfassende Erläuterung dieses Problems finden Sie unter Abschnitt A.8.1, „Offene Probleme in MySQL“.

  • FLUSH LOGS, FLUSH MASTER, FLUSH SLAVE und FLUSH TABLES WITH READ LOCK werden nicht geloggt, weil dies bei der Replikation auf einen Slave Probleme verursachen würde. Ein Syntaxbeispiel finden Sie in Abschnitt 13.5.5.2, „FLUSH. Die Anweisungen FLUSH TABLES, ANALYZE TABLE, OPTIMIZE TABLE und REPAIR TABLE werden in das Binärlog geschrieben und infolgedessen auf die Slaves repliziert. Dies ist normalerweise unproblematisch, weil diese Anweisungen die Tabellendaten nicht verändern. Allerdings kann dies unter bestimmten Umständen trotzdem Probleme verursachen. Wenn Sie die Berechtigungstabellen in der mysql-Datenbank replizieren und diese Tabellen direkt und ohne Verwendung von GRANT aktualisieren, müssen Sie eine FLUSH PRIVILEGES-Anweisung auf den Slaves absetzen, damit die neuen Berechtigungen gültig werden. Ferner müssen Sie, wenn Sie FLUSH TABLES beim Umbenennen einer MyISAM-Tabelle absetzen, die Teil einer MERGE-Tabelle ist, auf den Slaves eine FLUSH TABLES-Anweisung manuell absetzen. Diese Anweisungen werden in das Binärlog geschrieben, sofern Sie nicht NO_WRITE_TO_BINLOG oder den Alias LOCAL angegeben haben.

  • MySQL unterstützt genau einen Master und mehrere Slaves. Zukünftig beabsichtigen wir, einen Votieralgorithmus hinzuzufügen, der den Master automatisch wechselt, falls Probleme in Verbindung mit dem aktuellen Master auftreten. Ferner werden wir Agentenprozesse zur Durchführung einer Lastverteilung implementieren, indem SELECT-Anweisungen an verschiedene Slaves gesendet werden.

  • Wenn ein Server heruntergefahren wird und neu startet, werden seine MEMORY-Tabellen geleert. Der Master repliziert diesen Effekt wie folgt auf seine Slaves: Wenn der Master eine MEMORY-Tabelle nach dem Start zum ersten Mal verwendet, loggt er ein Ereignis, welches den Slaves angibt, dass die Tabelle geleert werden muss, indem eine DELETE-Anweisung für die betreffende Tabelle in das Binärlog geschrieben wird. Weitere Informationen finden Sie in Abschnitt 14.4, „Die MEMORY-Speicher-Engine“.

  • Beachten Sie, dass das Folgende nicht gilt, wenn die datensatzbasierte Replikation verwendet wird, denn diese erfordert überhaupt keine Replikation von Temporärtabellen. (Siehe auch Abschnitt 6.3, „Zeilenbasierte Replikation“.)

    Temporärtabellen werden normalerweise repliziert. Eine Ausnahme liegt vor, wenn Sie den Slave-Server (und nicht nur die Slave-Threads) heruntergefahren und Temporärtabellen repliziert haben, die in Updates verwendet werden, welche noch nicht auf dem Slave ausgeführt wurden. Haben Sie den Slave-Server heruntergefahren, dann stehen die Temporärtabellen, die von diesen Aktualisierungen benötigt werden, beim Neustart des Servers nicht mehr zur Verfügung. Um dieses Problem zu umgehen, fahren Sie den Slave nicht herunter, solange Temporärtabellen geöffnet sind. Stattdessen wenden Sie folgende Vorgehensweise an:

    1. Setzen Sie eine STOP SLAVE-Anweisung ab.

    2. Überprüfen Sie mit SHOW STATUS den Wert der Variablen Slave_open_temp_tables.

    3. Wenn der Wert 0 ist, beenden Sie den Slave mit einem mysqladmin shutdown-Befehl.

    4. Ist der Wert nicht 0, dann starten Sie die Slave-Threads mit START SLAVE neu.

    5. Wiederholen Sie den Vorgang nachfolgend so oft, bis die Variable Slave_open_temp_tables 0 ist und Sie den Slave beenden können.

  • Die Verbindung mit Servern in einer Master/Slave-Zirkelbeziehung ist sicher, wenn Sie die Option --log-slave-updates benutzen. Das bedeutet, dass Sie eine Konfiguration wie die folgende erstellen können:

    A -> B -> C -> A
    

    Allerdings funktionieren viele Anweisungen in einer solchen Konfiguration nicht einwandfrei, sofern Ihr Code nicht so formuliert ist, dass potenzielle Probleme berücksichtigt werden, die aufgrund von auf verschiedenen Servern in unterschiedlicher Reihenfolge durchgeführten Updates entstehen können.

    Serverkennungen werden in Binärlogereignisse kodiert, d. h., Server A erkennt, wenn ein Ereignis, das er liest, ursprünglich von ihm selbst erstellt worden ist, und führt es dann nicht aus (es sei denn, Server A wurde mit der Option --replicate-same-server-id gestartet, die aber nur in wenigen Fällen wichtig ist). Es kommt also nicht zu Endlosschleifen. Eine solche Zirkelkonfiguration funktioniert nur, wenn Sie keine Updates durchführen, durch die es zu Konflikten zwischen Tabellen kommt: Wenn Sie Daten sowohl auf A als auch auf C einfügen, sollten Sie keinesfalls einen Datensatz auf A einfügen, dessen Schlüssel unter Umständen mit einem Datensatz auf C kollidiert. Ebenso wenig sollten Sie dieselben Datensätze auf zwei Servern aktualisieren, wenn die Reihenfolge, in der die Updates durchgeführt werden, von Bedeutung ist.

  • Wenn eine Anweisung auf einem Slave einen Fehler erzeugt, wird der Slave-SQL-Thread terminiert, und der Slave schreibt eine Meldung in sein Fehlerlog. In diesem Fall sollten Sie manuell eine Verbindung zum Slave herstellen und die Ursache des Problems bestimmen. (Hierfür ist SHOW SLAVE STATUS recht praktisch.) Danach beheben Sie das Problem (z. B. durch Erstellen einer nichtvorhandenen Tabelle) und führen dann START SLAVE aus.

  • Einen Master-Server herunterzufahren und später neu zu starten ist sicher. Wenn ein Slave seine Verbindung zum Master verliert, versucht er sofort eine Neuverbindung und wiederholt diesen Versuch in regelmäßigen Abständen, bis er erfolgreich ist. Standardmäßig erfolgt alle 60 Sekunden ein Versuch zur Neuverbindung. Dies lässt sich mit der Option --master-connect-retry ändern. Ein Slave kann auch mit Ausfällen der Netzwerkkonnektivität zurechtkommen. Allerdings bemerkt er einen solchen Ausfall erst, wenn er für slave_net_timeout Sekunden keine Daten vom Master empfangen hat. Sind die Ausfälle kurz, dann sollten Sie den Wert von slave_net_timeout verringern. Siehe auch Abschnitt 5.2.2, „Server-Systemvariablen“.

  • Das (saubere) Herunterfahren des Slaves ist auch sicher, weil er vermerkt, an welcher Stelle er beendet wurde. Unsauberes Herunterfahren hingegen kann insbesondere dann Probleme verursachen, wenn der Festplatten-Cache vor Terminierung des Systems nicht auf die Festplatte geschrieben worden war. Ihre Systemfehlertoleranz erhöht sich erheblich, wenn Sie eine gute unterbrechungsfreie Stromversorgung verwenden. Eine unsaubere Beendigung des Masters kann Inkonsistenzen zwischen dem Inhalt der Tabellen und dem Binärlog auf dem Master zur Folge haben. Dies lässt sich durch Verwendung von InnoDB-Tabellen und der Option --innodb-safe-binlog auf dem Master vermeiden. Siehe auch Abschnitt 5.12.3, „Die binäre Update-Logdatei“.

    Hinweis: --innodb-safe-binlog wird in MySQL 5.1 nicht benötigt, weil es durch die in MySQL 5.0 eingeführte Unterstützung von XA-Transaktionen obsolet geworden ist. Siehe auch Abschnitt 13.4.7, „XA-Transaktionen“.

  • Aufgrund des nichttransaktionssicheren Wesens von MyISAM-Tabellen kann es vorkommen, dass eine Anweisung eine Tabelle nur teilweise aktualisiert und dann einen Fehlercode zurückgibt. Dies kann beispielsweise beim Einfügen mehrerer Datensätze geschehen, wenn einer dieser Datensätze gegen einen Schlüssel-Constraint verstößt, oder wenn eine lange Update-Anweisung nach Aktualisierung einer Anzahl von Datensätzen terminiert wurde. Wenn dies auf dem Master passiert, wird der Slave-Thread beendet. Es liegt dann am Datenbankadministrator, zu entscheiden, was zu tun ist, sofern der Fehlercode nicht zulässig ist und die Ausführung der Anweisung auf dem Slave denselben Fehlercode verursacht. Wenn dieses Verhalten der Fehlercodeauswertung nicht gewünscht ist, können einige oder alle Fehler mit der Option --slave-skip-errors maskiert (d. h. ignoriert) werden.

  • Wenn Sie transaktionssichere Tabellen aus nichttransaktionssicheren Tabellen in einer BEGIN/COMMIT-Sequenz aktualisieren, sind die Änderungen im Binärlog unter Umständen nicht synchron zu den Tabellenzuständen, wenn die nichttransaktionssichere Tabelle aktualisiert wird, bevor die Transaktion übergeben wird. Die Ursache hierfür ist, dass die Transaktion erst dann in das Binärlog geschrieben wird, wenn sie übergeben wird.

  • In Situationen, in denen Transaktionen Updates für transaktionssichere und nichttransaktionssichere Tabellen vermischen, ist die Reihenfolge der Anweisungen im Binärlog korrekt, und alle erforderlichen Anweisungen werden – auch bei einem Rollback – in das Binärlog geschrieben. Aktualisiert allerdings eine zweite Verbindung die nichttransaktionssichere Tabelle, bevor die Transaktion der ersten Verbindung abgeschlossen ist, dann kann die geloggte Anweisungsreihenfolge falsch sein, weil die Änderung der zweiten Verbindung unmittelbar nach ihrer Ausführung geschrieben wird – unabhängig von dem Zustand der Transaktion, die von der ersten Verbindung durchgeführt wurde.

6.9. Replikationsoptionen in my.cnf

Dieser Abschnitt beschreibt die Optionen, die Sie auf Replikationsslaves verwenden können. Sie können diese Optionen wahlweise auf der Befehlszeile oder in einer Optionsdatei angeben.

Auf dem Master und jedem Slave müssen Sie die Option server-id angeben, um eine eindeutige Replikationskennung zu erstellen. Wählen Sie auf jedem Server eine eindeutige Zahl zwischen 1 und 232 – 1. Außerdem muss jede Kennung sich von jeder anderen Kennung unterscheiden. Zum Beispiel: server-id=3

Optionen, die Sie auf dem Master-Server zur Steuerung des binären Loggens verwenden können, sind in Abschnitt 5.12.3, „Die binäre Update-Logdatei“, beschrieben.

Einige Replikationsoptionen für Slave-Server werden in dem Sinne speziell gehandhabt, dass sie ignoriert werden, wenn beim Start des Slaves eine Datei master.info vorhanden ist und diese einen Wert für die betreffende Option enthält. Dies betrifft die folgenden Optionen:

  • --master-host

  • --master-user

  • --master-password

  • --master-port

  • --master-connect-retry

  • --master-ssl

  • --master-ssl-ca

  • --master-ssl-capath

  • --master-ssl-cert

  • --master-ssl-cipher

  • --master-ssl-key

Die Datei master.info in MySQL 5.1 enthält Werte, die den SSL-Optionen entsprechen. Daneben sieht das Format dieser Datei in der ersten Zeile auch die Nennung der Gesamtanzahl aller Zeilen in der Datei vor. Wenn Sie einen älteren Server (vor MySQL 4.1.1) auf eine neuere Version aktualisieren, setzt der neue Server die Datei master.info beim Start automatisch auf das neue Format. Wenn Sie hingegen ein Downgrade auf einen älteren Server durchführen, sollten Sie die erste Zeile manuell entfernen, bevor Sie den älteren Server zum ersten Mal starten.

Ist beim Start des Slave-Servers keine Datei master.info vorhanden, dann werden für diese Optionen die Werte verwendet, die in Optionsdateien oder auf der Befehlszeile angegeben wurden. Dies ist etwa der Fall, wenn Sie den Server zum ersten Mal als Replikationsslave starten, oder wenn Sie RESET SLAVE ausgeführt haben und den Slave nun herunterfahren und neu starten.

Ist die Datei master.info beim Start des Slaves vorhanden, dann verarbeitet der Server ihren Inhalt und ignoriert Werte, die für die in der Datei aufgeführten Optionen übergeben wurden. Wenn Sie den Slave-Server also mit anderen Werten für die Startoptionen starten als denen in der Datei master.info, dann haben die von Ihnen übergebenen Werte keine Auswirkung, weil der Server die Angaben der Datei master.info entnimmt. Um andere Werte verwenden zu können, müssen Sie entweder nach dem Entfernen der Datei master.info einen Neustart durchführen oder die Werte bei laufendem Slave-Server mit der Anweisung CHANGE MASTER TO zurücksetzen (Letztere ist die empfohlene Methode).

Angenommen, Sie geben folgende Option in Ihrer Datei my.cnf an:

[mysqld]
master-host=some_host

Wenn Sie den Server zum ersten Mal als Replikationsslave starten, liest und verwendet er diese Option aus der Datei my.cnf. Danach zeichnet der Server den Wert in der Datei master.info auf. Wenn Sie den Server beim nächsten Mal starten, liest er den Master-Hostwert nur aus der Datei master.info und ignoriert den Wert in der Optionsdatei. Wenn Sie später in der Datei my.cnf den anderen Master-Host some_other_host angeben, hat diese Änderung keine Auswirkungen. Sie müssen stattdessen CHANGE MASTER TO verwenden.

Da der Server einer vorhandenen Datei master.info Vorrang vor den gerade beschriebenen Startoptionen gewährt, sollten Sie diese Werte unter Umständen überhaupt nicht mit Startoptionen angeben, sondern sie stattdessen mit der CHANGE MASTER TO-Anweisung festlegen. Siehe auch Abschnitt 13.6.2.1, „CHANGE MASTER TO.

Dieses Beispiel zeigt eine etwas umfangreichere Nutzung der Startoptionen zur Konfiguration eines Slave-Servers:

[mysqld]
server-id=2
master-host=db-master.mycompany.com
master-port=3306
master-user=pertinax
master-password=freitag
master-connect-retry=60
report-host=db-slave.mycompany.com

Die folgende Liste beschreibt die Startoptionen zur Steuerung der Replikation. Viele dieser Optionen können bei laufendem Server mit der Anweisung CHANGE MASTER TO zurückgesetzt werden. Andere wie beispielsweise die --replicate-*-Optionen können nur beim Start des Slave-Servers zurückgesetzt werden. Wir beabsichtigen dies zu beheben.

  • --log-slave-updates

    Normalerweise vermerkt ein Slave Updates, die er von einem Master-Server erhalten hat, nicht in seinem eigenen Binärlog. Diese Option weist den Slave jedoch an, Updates, die von seinem SQL-Thread ausgeführt wurden, in sein eigenes Binärlog zu schreiben. Damit diese Option Wirkung zeigt, muss der Slave auch mit der Option --log-bin gestartet werden, um das binäre Loggen zu aktivieren. --log-slave-updates wird verwendet, wenn Sie Replikationsserver seriell verketten. Nehmen wir an, Sie wollen die Replikationsserver wie folgt anordnen:

    A -> B -> C
    

    Hier dient A als Master von Slave B, und B agiert seinerseits als Master von Slave C. Damit dies funktioniert, muss B gleichermaßen Master und Slave sein. Sie müssen A und B mit der Option --log-bin starten, um das binäre Loggen zu aktivieren. Ferner muss B auch mit der Option --log-slave-updates gestartet werden, damit Änderungen, die von A empfangen wurden, von B auch im eigenen Binärlog vermerkt werden.

  • --log-warnings

    Mit dieser Option schreibt ein Server mehr Meldungen zu seinen Aktionen in das Fehlerlog. In Hinsicht auf die Replikation erzeugt der Server Warnungen, wenn er nach einem Netzwerk- oder Verbindungsausfall eine Neuverbindung herstellen konnte, und gibt auch an, wann die einzelnen Slave-Threads gestartet wurden. Die Option ist standardmäßig aktiviert. Sie können sie mithilfe von --skip-log-warnings deaktivieren. Unterbrochene Verbindungen werden nicht in das Fehlerlog protokolliert, sofern der Wert größer als 1 ist.

  • --master-connect-retry=seconds

    Die Anzahl von Sekunden, für die der Slave-Thread im Falle eines Ausfalls der Verbindung oder des Master-Servers schläft, bevor er eine Neuverbindung mit dem Master herzustellen versucht. Der entsprechende Wert in der Datei master.info hat ggf. Vorrang. Ist der Wert nicht angegeben, dann wird 60 als Vorgabe benutzt.

  • --master-host=host_name

    Hostname oder IP-Adresse des Master-Replikationsservers. Der entsprechende Wert in der Datei master.info hat ggf. Vorrang. Ist kein Master-Host angegeben, dann wird der Slave-Thread nicht gestartet.

  • --master-info-file=file_name

    Der Name der Datei, in der der Slave Angaben zum Master vermerkt. Der Standardname lautet mysql.info im Datenverzeichnis.

  • --master-password=password

    Das Passwort des Kontos, welches der Slave zur Authentifizierung verwendet, wenn er sich beim Master anmeldet. Der entsprechende Wert in der Datei master.info hat ggf. Vorrang. Sofern nicht angegeben, wird ein leeres Passwort angenommen.

  • --master-port=port_number

    Die Nummer des TCP/IP-Ports, auf dem der Master horcht. Der entsprechende Wert in der Datei master.info hat ggf. Vorrang. Sofern nicht angegeben, wird der einkompilierte Wert (normalerweise 3306) als Vorgabe verwendet.

  • --master-retry-count=count

    Häufigkeit, mit der der Slave eine Neuverbindung mit dem Master probiert, bevor er aufgibt.

  • --master-ssl, --master-ssl-ca=file_name, --master-ssl-capath=directory_name, --master-ssl-cert=file_name, --master-ssl-cipher=cipher_list, --master-ssl-key=file_name

    Diese Optionen werden zur Einstellung einer sicheren, SSL-verschlüsselten Replikationsverbindung zum Master-Server benutzt. Die Bedeutungen sind mit denen der entsprechenden Optionen --ssl, --ssl-ca, --ssl-capath, --ssl-cert, --ssl-cipher und --ssl-key identisch, die in Abschnitt 5.9.7.5, „SSL-Befehlsoptionen“, beschrieben werden. Die entsprechenden Werte in der Datei master.info haben ggf. Vorrang.

  • --master-user=user_name

    Der Benutzername des Kontos, welches der Slave zur Authentifizierung verwendet, wenn er sich beim Master anmeldet. Dieses Konto benötigt die Berechtigung REPLICATION SLAVE. Der entsprechende Wert in der Datei master.info hat ggf. Vorrang. Wenn der Master-Benutzername nicht angegeben ist, wird der Name test als Vorgabe verwendet.

  • --max-relay-log-size=size

    Größe, bei der der Server die Relay-Logs automatisch rotiert. Weitere Informationen finden Sie unter Abschnitt 6.4.4, „Relay- und Statusdateien bei der Replikation“.

  • --read-only

    Bewirkt, dass der Slave keine Updates gestattet, sofern diese nicht von Slave-Threads oder von Benutzern mit der Berechtigung SUPER stammen. Auf diese Weise lässt sich sicherstellen, dass ein Slave-Server keine Aktualisierungen von Clients akzeptiert. Diese Option gilt nicht für TEMPORARY-Tabellen.

  • --relay-log=file_name

    Der Name des Relay-Logs. Der Standardname lautet host_name-relay-bin.nnnnnn, wobei host_name der Name des Slave-Serverhosts ist und nnnnnn angibt, dass Relay-Logs mit fortlaufender Nummerierung erstellt werden. Sie können die Option angeben, um vom Hostnamen unabhängige Namen für Relay-Logs zu erstellen. Ferner ist sie praktisch, wenn Ihre Relay-Logs dazu tendieren, sehr groß zu werden (und Sie max_relay_log_size nicht verringern wollen), und Sie sie an einer anderen Position als im Datenverzeichnis ablegen müssen, oder wenn Sie die Geschwindigkeit durch eine Lastverteilung auf mehrere Festplatten optimieren wollen.

  • --relay-log-index=file_name

    Der Name, der für die Indexdatei des Relay-Logs verwendet wird. Der Standardname lautet host_name-relay-bin.index im Datenverzeichnis, wobei host_name der Name des Slave-Servers ist.

  • --relay-log-info-file=file_name

    Der Name der Datei, in der der Slave Angaben zu den Relay-Logs vermerkt. Der Standardname lautet relay-log.info im Datenverzeichnis.

  • --relay-log-purge={0|1}

    Aktiviert oder deaktiviert das automatische Löschen von Relay-Logs, wenn sie nicht mehr benötigt werden. Der Vorgabewert ist 1 (aktiviert). Dies ist eine globale Variable, die dynamisch mit SET GLOBAL relay_log_purge = N geändert werden kann.

  • --relay-log-space-limit=size

    Diese Option setzt eine Obergrenze für die Gesamtgröße aller Relay-Logs auf dem Slave, angegeben in Byte. Der Wert 0 hat die Bedeutung „unbeschränkt“. Die Option ist praktisch auf Slave-Servern, bei denen die Festplattenkapazität begrenzt ist. Wenn der Grenzwert erreicht wird, beendet der I/O-Thread das Auslesen von Ereignissen aus dem Binärlog des Masters, bis der SQL-Thread aufgeholt und eine Anzahl nicht mehr benötigter Relay-Logs gelöscht hat. Beachten Sie, dass das Limit nicht absolut ist: Es gibt Fälle, in denen der SQL-Thread mehr Ereignisse benötigt, bevor er Relay-Logs löschen kann. In diesem Fall überschreitet der I/O-Thread den Grenzwert so weit, wie es notwendig ist, damit der SQL-Thread einige Relay-Logs löschen kann (andernfalls würde der Slave nämlich blockiert). Sie sollten --relay-log-space-limit auf einen Wert setzen, der mindestens zweimal so groß ist wie der Wert von --max-relay-log-size (oder --max-binlog-size, sofern --max-relay-log-size 0 ist). In diesem Fall besteht die Möglichkeit, dass der I/O-Thread auf freien Speicher warten muss, weil --relay-log-space-limit überschritten wurde, der SQL-Thread aber kein Relay-Log löschen und deswegen die Anforderung des I/O-Threads nicht bearbeiten kann. Also ist der I/O-Thread gezwungen, --relay-log-space-limit vorübergehend zu ignorieren.

  • --replicate-do-db=db_name

    Weist den Slave an, die Replikation auf Anweisungen zu beschränken, deren Standarddatenbank (also die von USE gewählte Datenbank) db_name ist. Um mehrere Datenbanken anzugeben, verwenden Sie diese Option mehrfach (d. h. jeweils einmal pro Datenbank). Beachten Sie, dass hierbei keine datenbankübergreifenden Anweisungen wie UPDATE some_db.some_table SET foo='bar' repliziert werden, solange eine andere Datenbank (oder gar keine Datenbank) gewählt ist.

    Hier ein Beispiel für etwas, das nicht so funktioniert, wie Sie es vielleicht erwarten: Wenn der Slave mit der Option --replicate-do-db=sales gestartet wird und Sie die folgenden Anweisungen auf dem Master absetzen, wird die UPDATE-Anweisung nicht repliziert:

    USE prices;
    UPDATE sales.january SET amount=amount+1000;
    

    Der wichtigste Grund für dieses Verhalten nach dem Motto „Nur die Standarddatenbank überprüfen“ besteht darin, dass es schwierig ist, allein der Anweisung zu entnehmen, ob sie repliziert werden soll (wenn Sie beispielsweise DELETE-Anweisungen für mehrere Tabellen oder UPDATE-Anweisungen für mehrere Tabellen verwenden, die datenbankübergreifend agieren). Außerdem geht es schneller, wenn nur die Standarddatenbank (statt aller Datenbanken) überprüft wird, sofern es keinen Grund dafür gibt.

    Wenn Sie datenbankübergreifende Aktualisierungen zum Laufen bringen wollen, verwenden Sie stattdessen --replicate-wild-do-table=db_name.%. Siehe auch Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.

  • --replicate-do-table=db_name.tbl_name

    Weist den Slave-Thread an, die Replikation auf die angegebene Tabelle zu beschränken. Um mehrere Tabellen anzugeben, verwenden Sie diese Option mehrfach (d. h. jeweils einmal pro Tabelle). Dies funktioniert – anders als --replicate-do-db – auch bei datenbankübergreifenden Änderungen. Siehe auch Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.

  • --replicate-ignore-db=db_name

    Weist den Slave an, keine Anweisungen zu replizieren, deren Standarddatenbank (also die von USE gewählte Datenbank) db_name ist. Um mehrere zu ignorierende Datenbanken anzugeben, verwenden Sie diese Option mehrfach (d. h. jeweils einmal pro Datenbank). Sie sollten die Option allerdings nicht angeben, wenn Sie datenbankübergreifende Änderungen ausführen, die aber nicht repliziert werden sollen. Siehe auch Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.

    Hier ein Beispiel für etwas, das nicht so funktioniert, wie Sie es vielleicht erwarten: Wenn der Slave mit der Option --replicate-ignore-db=sales gestartet wird und Sie die folgenden Anweisungen auf dem Master absetzen, wird die UPDATE-Anweisung nicht repliziert:

    USE prices;
    UPDATE sales.january SET amount=amount+1000;
    

    Wenn Sie datenbankübergreifende Aktualisierungen zum Laufen bringen wollen, verwenden Sie stattdessen --replicate-wild-ignore-table=db_name.%. Siehe auch Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.

  • --replicate-ignore-table=db_name.tbl_name

    Weist den Slave-Thread an, eine Anweisung, die die angegebene Tabelle ändert, auch dann nicht zu replizieren, wenn andere Tabellen von derselben Anweisung geändert werden könnten. Um mehrere zu ignorierende Tabellen anzugeben, verwenden Sie diese Option mehrfach (d. h. jeweils einmal pro Tabelle). Dies funktioniert – anders als --replicate-ignore-db – auch bei datenbankübergreifenden Änderungen. Siehe auch Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.

  • --replicate-rewrite-db=from_name->to_name

    Weist den Slave an, die Standarddatenbank (also die von USE gewählte Datenbank) in to_name zu übersetzen, wenn sie auf dem Master den Namen from_name hatte. Hiervon sind nur tabellenbezogene Anweisungen betroffen (also keine Anweisungen wie CREATE DATABASE, DROP DATABASE und ALTER DATABASE), und diese auch nur dann, wenn from_name die Standarddatenbank auf dem Master ist. Dies funktioniert bei datenbankübergreifenden Änderungen nicht. Die Übersetzung des Datenbanknamens erfolgt vor dem Prüfen der --replicate-*-Regeln.

    Wenn Sie diese Option auf der Befehlszeile verwenden und das Zeichen ‘>’ für Ihren Befehls-Interpreter ein Sonderzeichen ist, müssen Sie den Optionswert in Anführungszeichen setzen. Zum Beispiel:

    shell> mysqld --replicate-rewrite-db="olddb->newdb"
    
  • --replicate-same-server-id

    Wird auf Slave-Servern verwendet. Normalerweise sollten Sie die Standardeinstellung 0 verwenden, um durch eine Kreisreplikation verursachte Endlosschleifen zu verhindern. Wenn Sie den Wert 1 wählen, überspringt der Slave keine Ereignisse, die seine eigene Serverkennung enthalten – dies ist normalerweise nur in seltenen Fällen gewollt. Der Wert 1 kann bei Verwendung von --log-slave-updates nicht gewählt werden. Beachten Sie, dass der Slave-I/O-Thread standardmäßig noch nicht einmal dann Ereignisse aus dem Binärlog in das Relay-Log schreibt, wenn diese die Kennung des Slaves aufweisen (diese Optimierung hilft beim Einsparen von Festplattenkapazität). Wenn Sie also --replicate-same-server-id verwenden wollen, müssen Sie den Slave in jedem Fall mit dieser Option starten, bevor Sie ihn dazu bringen, eigene Ereignisse zu lesen, die der Slave-SQL-Thread ausführen soll.

  • --replicate-wild-do-table=db_name.tbl_name

    Weist den Slave-Thread an, die Replikation auf Anweisungen zu beschränken, bei denen die aktualisierten Tabellen den angegebenen Mustern für Datenbank- und Tabellennamen entsprechen. Muster dürfen die Jokerzeichen ‘%’ und ‘_’ enthalten; diese haben dieselbe Bedeutung wie beim Mustervergleichsoperator LIKE. Um mehrere Tabellen anzugeben, verwenden Sie diese Option mehrfach (d. h. jeweils einmal pro Tabelle). Dies funktioniert bei datenbankübergreifenden Änderungen. Siehe auch Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.

    Beispiel: --replicate-wild-do-table=foo%.bar% repliziert nur Updates, die eine Tabelle betreffen, bei der der Datenbankname mit foo und der Tabellenname mit bar beginnt.

    Wenn als Muster für den Tabellennamen % angegeben wird, dann liegt eine Entsprechung für jeden Tabellennamen vor, und die Option gilt auch für Anweisungen auf Datenbankebene (CREATE DATABASE, DROP DATABASE und ALTER DATABASE). Wenn Sie beispielsweise --replicate-wild-do-table=foo%.% angeben, werden die Anweisungen auf Datenbankebene repliziert, wenn der Datenbankname foo% entspricht.

    Um Jokerzeichen literal in den Mustern für Datenbank- oder Tabellennamen zu verwenden, kennzeichnen Sie sie mit einem Backslash. Um also beispielsweise alle Tabellen einer Datenbank namens my_own%db zu replizieren, nicht aber Tabellen aus my1ownAABCdb, sollten Sie die Zeichen ‘_’ und ‘%’ wie folgt kennzeichnen: --replicate-wild-do-table=my\_own\%db. Wenn Sie die Option auf der Befehlszeile angeben, müssen Sie unter Umständen je nach Befehls-Interpreter die Backslashes verdoppeln oder den Optionswert in Anführungszeichen setzen. So müssen Sie bei der bash-Shell etwa --replicate-wild-do-table=my\\_own\\%db angeben.

  • --replicate-wild-ignore-table=db_name.tbl_name

    Weist den Slave-Thread an, eine Anweisung nicht zu replizieren, bei der eine beliebige Tabelle dem angegebenen Jokerzeichenmuster entspricht. Um mehrere zu ignorierende Tabellen anzugeben, verwenden Sie diese Option mehrfach (d. h. jeweils einmal pro Tabelle). Dies funktioniert bei datenbankübergreifenden Änderungen. Siehe auch Abschnitt 6.10, „Wie Server Replikationsregeln auswerten“.

    Beispiel: --replicate-wild-ignore-table=foo%.bar% repliziert keine Updates, die eine Tabelle betreffen, bei der der Datenbankname mit foo und der Tabellenname mit bar beginnt.

    Informationen zur Funktionsweise von Mustervergleichen entnehmen Sie der Beschreibung zur Option --replicate-wild-do-table. Die Regeln zur Verwendung literaler Jokerzeichen im Optionswert sind dieselben wie bei --replicate-wild-ignore-table.

  • --report-host=slave_name

    Hostname oder IP-Adresse des Slaves, der oder die bei der Slave-Registrierung an den Master gemeldet wurde. Dieser Wert erscheint in der Ausgabe von SHOW SLAVE HOSTS auf dem Master-Server. Lassen Sie den Wert ungesetzt, wenn Sie nicht wollen, dass der Slave sich selbstständig beim Master registriert. Beachten Sie, dass es für den Master nicht ausreichend ist, die IP-Adresse des Slaves bei dessen Verbindungsherstellung einfach dem TCP/IP-Socket zu entnehmen. Aufgrund der Netzadressübersetzung (NAT) und anderer Routing-relevanter Probleme kann diese IP-Adresse unter Umständen nicht verwendet werden, um den Slave vom Master oder anderen Hosts aus zu kontaktieren.

  • --report-port=slave_port_num

    Die Nummer des TCP/IP-Ports zur Verbindung mit dem Slave, die bei der Slave-Registrierung an den Master gemeldet wurde. Nehmen Sie die Einstellung nur vor, wenn der Slave nicht auch einem Standardport lauscht oder Sie einen speziellen Tunnel vom Master oder anderen Clients zum Slave verwenden. Wenn Sie sich nicht sicher sind, verwenden Sie die Option nicht.

  • --skip-slave-start

    Weist den Slave-Server an, die Slave-Threads nicht zu starten, wenn der Server startet. Um die Threads später zu starten, können Sie die Anweisung START SLAVE verwenden.

  • --slave_compressed_protocol={0|1}

    Wenn diese Option auf 1 gesetzt ist, wird eine Komprimierung des Slave/Master-Protokolls verwendet, wenn sowohl Slave als auch Master diese unterstützen.

  • --slave-load-tmpdir=file_name

    Der Name des Verzeichnisses, in dem der Slave Temporärdateien erstellt. Diese Option entspricht standardmäßig dem Wert der Systemvariablen tmpdir. Wenn der Slave-SQL-Thread eine LOAD DATA INFILE-Anweisung repliziert, extrahiert er die zu ladende Datei aus dem Relay-Log in Temporärdateien und lädt diese dann in die Tabelle. Wenn die auf dem Master geladene Datei sehr groß ist, sind auch die Temporärdateien auf dem Slave groß. Aus diesem Grund kann es sich empfehlen, den Slave mit dieser Option anzuweisen, die Temporärdateien in ein Verzeichnis auf einem Dateisystem zu speichern, auf dem ausreichend viel Festplattenkapazität vorhanden ist. In diesem Fall sind auch die Relay-Logs riesig, weswegen Sie auch diese mit der Option --relay-log gleichermaßen auf jenem Dateisystem ablegen sollten.

    Das mit dieser Option angegebene Verzeichnis sollte auf einem festplattenbasierten (d. h. nicht speicherresidenten) Dateisystem liegen, da die Temporärdateien, die zur Replikation von LOAD DATA INFILE verwendet werden, einen Systemneustart überdauern müssen. Das Verzeichnis sollte außerdem nicht eines sein, welches beim Systemstart vom Betriebssystem geleert wird.

  • --slave-net-timeout=seconds

    Anzahl der Sekunden, für die auf weitere Daten vom Master gewartet wird, bevor der Slave die Verbindung als unterbrochen betrachtet, den Lesevorgang abbricht und eine Neuverbindung probiert. Der erste Versuch findet unmittelbar nach Überschreiten dieses Werts statt. Die Abstände zwischen den Neuversuchen werden von der Option --master-connect-retry gesteuert.

  • --slave-skip-errors=[err_code1,err_code2,...|all]

    Normalerweise wird die Replikation beendet, wenn ein Fehler auf dem Slave auftritt. Sie haben auf diese Weise die Möglichkeit, Inkonsistenzen in den Daten manuell zu beheben. Diese Option weist den Slave-SQL-Thread an, mit der Replikation fortzufahren, wenn eine Anweisung einen der im Optionswert aufgeführten Fehler zurückgibt.

    Verwenden Sie diese Option nicht, sofern Sie nicht genau wissen, warum Sie Fehler erhalten. Sind in Ihrer Replikationskonfiguration und Clientprogrammen ebenso wenig Fehler vorhanden wie Bugs in MySQL, dann sollte eigentlich nie ein Fehler auftreten, der die Replikation beendet. Die unüberlegte Verwendung dieser Option hat zur Folge, dass die Synchronisation zwischen Master und Slave unwiederbringlich verloren geht, ohne dass Sie überhaupt wissen, warum dies so ist.

    Die Fehlercodes sind als Zahlenangaben in den Fehlermeldungen im Fehlerlog des Slaves und in der Ausgabe von SHOW SLAVE STATUS enthalten. Anhang B, Fehlercodes und -meldungen, listet die Serverfehlercodes auf.

    Sie könnten theoretisch auch den nicht sehr empfehlenswerten Wert all angeben, damit der Slave alle Fehlermeldungen ignoriert und weiterarbeitet – egal, was auch passiert. Aber das sollten Sie besser lassen. Selbstredend gibt es, wenn Sie all verwenden, keine Garantie bezüglich der Datenintegrität. Sollten die Daten auf dem Slave in einem solchen Fall auch nicht annähernd denen auf dem Master entsprechen, so bitten wir von Beschwerden (und der Meldung von Bugs) abzusehen. Wir haben Sie gewarnt!

    Ein paar Beispiele:

    --slave-skip-errors=1062,1053
    --slave-skip-errors=all
    

6.10. Wie Server Replikationsregeln auswerten

Wenn ein Master-Server keine Anweisung in sein Binärlog schreibt, wird die Anweisung auch nicht repliziert. Schreibt der Server die Anweisung hingegen in das Log, dann wird die Anweisung an alle Slaves geschickt, und jeder Slave bestimmt, ob er sie ausführt oder ignoriert.

Auf der Master-Seite basieren die Entscheidungen darüber, welche Anweisungen zu loggen sind, auf den Optionen --binlog-do-db und --binlog-ignore-db, die das binäre Loggen steuern. Eine Beschreibung der Regeln, die der Server bei der Auswertung dieser Optionen verwendet, finden Sie in Abschnitt 5.12.3, „Die binäre Update-Logdatei“.

Auf der Slave-Seite werden die Entscheidungen darüber, ob und welche vom Master empfangenen Anweisungen ausgeführt oder ignoriert werden, entsprechend den --replicate-*-Optionen getroffen, mit denen der Slave gestartet wurde. Der Slave wertet diese Optionen entsprechend der folgenden Vorgehensweise aus.

  1. Sind --replicate-do-db- oder --replicate-ignore-db-Optionen vorhanden?

    • Ja: Unter Verwendung derselben Regeln testen wie bei den Optionen --binlog-do-db und --binlog-ignore-db. Welches Ergebnis hat der Test?

      • Anweisung ignorieren: Ignorieren und beenden.

      • Anweisung zulassen: Anweisung nicht sofort ausführen, sondern die Entscheidung verschieben. Mit nächstem Schritt fortfahren.

    • Nein: Mit nächstem Schritt fortfahren.

  2. Wird gerade eine gespeicherte Funktion ausgeführt?

    • Ja: Abfrage ausführen und beenden.

    • Nein: Mit nächstem Schritt fortfahren.

  3. Sind --replicate-*-table-Optionen vorhanden?

    • Nein: Abfrage ausführen und beenden.

    • Ja: In diesem Fall hängt das Verhalten davon ab, ob die anweisungsbasierte Replikation oder die datensatzbasierte Replikation verwendet wird:

      • Anweisungsbasierte Replikation: Mit nächstem Schritt fortfahren und mit der Auswertung der Tabellenregeln in der angegebenen Reihenfolge (zuerst die Nicht-„wild“-, dann die „wild“-Regeln) beginnen. Nur Tabellen, die aktualisiert werden sollen, werden mit den Regeln verglichen. Heißt die Anweisung etwa INSERT INTO sales SELECT * FROM prices, dann wird nur sales mit den Regeln verglichen. Wenn mehrere Tabellen durch eine entsprechende Anweisung aktualisiert werden, gewinnt die erste Tabelle, die „Do“ oder „Ignore“ entspricht: Der Server vergleicht die erste Tabelle also mit den Regeln. Konnte keine Entscheidung getroffen werden, dann überprüft er die zweite Tabelle usw.

      • Datensatzbasierte Replikation: Alle Änderungen an Tabellendatensätzen werden einzeln gefiltert. Bei Updates für mehrere Tabellen wird jede Tabelle entsprechend den Regeln separat gefiltert. Einige Änderungen werden ausgeführt, andere unter Umständen nicht – dies hängt jeweils von den Regeln und den vorgenommenen Änderungen ab. Die datensatzbasierte Replikation verarbeitet Fälle, die bei der anweisungsbasierten Replikation nicht korrekt repliziert würden, ihrerseits korrekt. Betrachten Sie folgendes Beispiel, welches davon ausgeht, dass Tabellen in der Datenbank foo repliziert werden sollen:

        mysql> USE bar;
        mysql> INSERT INTO foo.sometable VALUES (1);                    
        

  4. Gibt es --replicate-do-table-Regeln?

    • Ja: Entspricht die Tabelle einer dieser Regeln?

      • Ja: Abfrage ausführen und beenden.

      • Nein: Mit nächstem Schritt fortfahren.

    • Nein: Mit nächstem Schritt fortfahren.

  5. Gibt es --replicate-ignore-table-Regeln?

    • Ja: Entspricht die Tabelle einer dieser Regeln?

      • Ja: Abfrage ignorieren und beenden.

      • Nein: Mit nächstem Schritt fortfahren.

    • Nein: Mit nächstem Schritt fortfahren.

  6. Gibt es --replicate-wild-do-table-Regeln?

    • Ja: Entspricht die Tabelle einer dieser Regeln?

      • Ja: Abfrage ausführen und beenden.

      • Nein: Mit nächstem Schritt fortfahren.

    • Nein: Mit nächstem Schritt fortfahren.

  7. Gibt es --replicate-wild-ignore-table-Regeln?

    • Ja: Entspricht die Tabelle einer dieser Regeln?

      • Ja: Abfrage ignorieren und beenden.

      • Nein: Mit nächstem Schritt fortfahren.

    • Nein: Mit nächstem Schritt fortfahren.

  8. Es gab keine Entsprechung für eine --replicate-*-table-Regel. Gibt es noch eine weitere Tabelle, die auf diese Regeln geprüft werden kann?

    • Ja: Schleife wiederholen.

    • Nein: Wir haben nun alle zu aktualisierenden Tabellen getestet und konnten keine Übereinstimmung mit einer Regel finden. Sind --replicate-do-table- oder --replicate-wild-do-table-Regeln vorhanden?

      • Ja: Es gab „Do“-Regeln, aber keine Übereinstimmung. Abfrage ignorieren und beenden.

      • Nein: Abfrage ausführen und beenden.

6.11. Replikation: häufig gestellte Fragen

Frage: Wie konfiguriere ich einen Slave, wenn der Master ausgeführt wird und ich ihn nicht anhalten will?

Antwort: Es gibt mehrere Möglichkeiten. Wenn Sie zu einem bestimmten Zeitpunkt ein auf einer Momentaufnahme basiertes Backup des Masters erstellt und den Binärlognamen und den Versatz (aus der Ausgabe von SHOW MASTER STATUS) für die Momentaufnahme notiert haben, gehen Sie wie folgt vor:

  1. Stellen Sie sicher, dass der Slave eine eindeutige Serverkennung hat.

  2. Führen Sie die folgende Anweisung auf dem Slave aus. Geben Sie dabei für jede Option die passenden Werte an:

    mysql> CHANGE MASTER TO
        ->     MASTER_HOST='master_host_name',
        ->     MASTER_USER='master_user_name',
        ->     MASTER_PASSWORD='master_pass',
        ->     MASTER_LOG_FILE='recorded_log_file_name',
        ->     MASTER_LOG_POS=recorded_log_position;
    
  3. Führen Sie START SLAVE auf dem Slave aus.

Wenn Sie über keine Sicherungskopie des Master-Servers verfügen, können Sie wie nachfolgend beschrieben ganz einfach eine solche erstellen. Alle Schritte sind dabei auf dem Master-Host durchzuführen.

  1. Setzen Sie die folgende Anweisung ab, um eine globale Lesesperre zu erwirken:

    mysql> FLUSH TABLES WITH READ LOCK;
    
  2. Führen Sie bei weiterhin aktiver Sperre den folgenden Befehl (oder eine entsprechende Variante) aus:

    shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql
    
  3. Setzen Sie nun folgende Anweisung ab und notieren Sie die Ausgabe (Sie werden sie später noch benötigen):

    mysql> SHOW MASTER STATUS;
    
  4. Heben Sie die Sperre auf:

    mysql> UNLOCK TABLES;
    

Eine Alternative zu dieser Vorgehensweise zur Erstellung einer binären Kopie besteht darin, einen SQL-Speicherauszug des Masters zu erstellen. Hierzu führen Sie mysqldump --master-data auf dem Master aus und laden die SQL-Speicherauszugsdatei später in Ihren Slave. Allerdings ist die Erstellung einer binären Kopie schneller.

Unabhängig davon, welche der beiden Methoden Sie verwenden, befolgen Sie danach die Anleitung für den Fall, dass Sie eine Momentaufnahme erstellt und den Logdateinamen und den Offset vermerkt haben. Sie können dieselbe Momentaufnahme mehrfach verwenden. Wenn Sie die Momentaufnahme des Masters erst einmal haben, können Sie beliebig lang mit der Konfiguration des Slaves warten: Es müssen lediglich die Binärlogs auf dem Master intakt bleiben. Allerdings bestehen zwei praktische Beschränkungen, die Sie beachten müssen: Sie dürfen nicht länger als notwendig warten, um zu vermeiden, dass die zur Aufnahme der Binärlogs auf dem Master erforderliche Speichermenge zu groß wird und dass der Slave nicht schnell genug auf den Stand des Masters gebracht werden kann.

Sie können außerdem LOAD DATA FROM MASTER verwenden. Dies ist eine praktische Anweisung, die eine Momentaufnahme auf den Slave überträgt und gleichzeitig auch noch den Logdateinamen und den Versatz automatisch einstellt. Zukünftig wird LOAD DATA FROM MASTER die empfohlene Vorgehensweise zur Konfiguration eines Slaves werden. Beachten Sie allerdings, dass die Anweisung nur bei MyISAM-Tabellen funktioniert und für einen relativ langen Zeitraum eine Lesesperre setzt. Sie ist noch nicht so effektiv implementiert, wie wir uns das wünschen. Wenn Sie größere Tabellen haben, besteht die bevorzugte Methode also derzeit noch darin, nach der Ausführung von FLUSH TABLES WITH READ LOCK eine binäre Momentaufnahme auf dem Master-Server zu erstellen.

Frage: Muss der Slave fortlaufend mit dem Master verbunden sein?

Antwort: Nein. Der Slave kann stunden- oder sogar tagelang ausgeschaltet oder getrennt sein – erfolgt eine Neuverbindung, dann werden alle Aktualisierungen aufgeholt. Sie können beispielsweise eine Master/Slave-Beziehung über eine Wählverbindung konfigurieren, bei der die Verbindung nur sporadisch und nur für kurze Zeit hergestellt wird. Eine Auswirkung hiervon ist natürlich, dass man zu keinem Zeitpunkt die Synchronisation zwischen Slave und Master gewährleisten kann, sofern nicht bestimmte Maßnahmen ergriffen werden. Zukünftig wird eine Option eingeführt werden, mit der der Master blockiert wird, bis mindestens ein Slave synchronisiert wurde.

Frage: Wie erkenne ich, wie weit ein Slave im Vergleich zum Master im Rückstand ist? Anders formuliert: Wie ermittle ich den Zeitpunkt der letzten vom Slave replizierten Abfrage?

Antwort: Lesen Sie die Spalte Seconds_Behind_Master in der Ausgabe von SHOW SLAVE STATUS aus. Siehe auch Abschnitt 6.4, „Replikation: Implementationsdetails“.

Wenn der Slave-SQL-Thread ein Ereignis ausführt, welches er vom Master gelesen hat, dann setzt er seine eigene Zeit auf den Zeitstempel des Ereignisses um. (Dies ist auch Voraussetzung dafür, dass TIMESTAMP korrekt repliziert wird.) In der Spalte Time der Ausgabe von SHOW PROCESSLIST beschreibt die angezeigte Sekundenzahl für den Slave-SQL-Thread die Anzahl der Sekunden zwischen dem Zeitstempel des letzten replizierten Ereignisses und der Echtzeit des Slave-Systems. Auf diese Weise können Sie den Zeitpunkt des letzten replizierten Ereignisses ermitteln. Beachten Sie, dass, wenn Ihr Slave für eine Stunde vom Master getrennt wurde und dann eine neue Verbindung herstellt, in der Spalte Time sofort Werte wie 3600 für den Slave-SQL-Thread in der Ausgabe von SHOW PROCESSLIST erscheinen. Dies liegt daran, dass der Slave Anweisungen ausführt, die eine Stunde alt sind.

Frage: Wie kann ich den Master zwingen, Updates zu sperren, bis der Slave den Rückstand aufgeholt hat?

Antwort: Gehen Sie wie folgt vor:

  1. Führen Sie auf dem Master die folgenden Anweisungen aus:

    mysql> FLUSH TABLES WITH READ LOCK;
    mysql> SHOW MASTER STATUS;
    

    Notieren Sie die Replikationskoordinaten (Logdateiname und Versatz) in der Ausgabe der SHOW-Anweisung.

  2. Setzen Sie auf dem Slave folgende Anweisung ab. Die Argumente für die Funktion MASTER_POS_WAIT() sind die Replikationskoordinaten, die Sie im vorherigen Schritt ermittelt haben:

    mysql> SELECT MASTER_POS_WAIT('log_name', log_offset);
    

    Die SELECT-Anweisung sperrt den Master, bis der Slave die entsprechende Position in der angegebenen Logdatei erreicht hat. An dieser Stelle läuft der Slave synchron zum Master, und die Anweisung gibt ihre Werte zurück.

  3. Setzen Sie nun auf dem Master die folgende Anweisung ab, damit er wieder Updates verarbeiten kann:

    mysql> UNLOCK TABLES;
    

Frage: Welche Aspekte muss ich bei der Konfiguration der 2-Wege-Replikation beachten?

Antwort: Die MySQL-Replikation unterstützt derzeit kein Sperrprotokoll zwischen Master und Server, mit dem die Atomizität eines verteilten (serverübergreifenden) Updates gewährleistet werden kann. Es ist also möglich, dass Client A ein Update auf dem Co-Master 1 vornimmt, während gleichzeitig (also bevor dieses Update an den Co-Master 2 weitergegeben wird) Client B ein Update auf dem Co-Master 2 durchführt, welches für das Update von Client A eine andere Wirkung hervorruft als auf Co-Master 1. Auf diese Weise erzeugt das Update von Client A nach der Ankunft auf dem Co-Master 2 Tabellen, die sich von denen auf dem Co-Master 1 unterscheiden – und zwar auch, nachdem alle Updates von Co-Master 2 ebenfalls weitergegeben wurden. Dies bedeutet, dass Sie niemals zwei Server in einer 2-Wege-Replikationsbeziehung miteinander verketten sollten, sofern Sie nicht sicher sind, dass Ihre Updates in beliebiger Reihenfolge erfolgen können, oder im Clientcode den Fall unterschiedlicher Updatereihenfolgen irgendwie berücksichtigen.

Sie sollten auch daran denken, dass, soweit es Updates betrifft, die 2-Wege-Replikation die Leistungsfähigkeit – sofern überhaupt – nicht allzu sehr optimiert. Jeder Server muss dieselbe Anzahl von Updates ausführen – ebenso wie es auch bei nur einem Server der Fall wäre. Der einzige Unterschied besteht darin, dass es zu weniger konkurrierenden Sperranforderungen kommt, weil die Updates, die von einem anderen Server kommen, in nur einem Slave-Thread serialisiert werden. Aber auch dieser Vorteil kann durch Netzwerklatenzen schon wieder aufgewogen werden.

Frage: Wie kann ich mit der Replikation die Leistung meines Systems verbessern?

Antwort: Sie sollten einen Server als Master konfigurieren und alle Schreiboperationen an ihn richten. Nachfolgend sollten Sie so viele Slaves einrichten, wie es Budget und Platzverhältnisse zulassen, und Leseoperationen dann auf Master und Slaves verteilen. Sie können die Slaves auch mit den Optionen --skip-innodb, --skip-bdb, --low-priority-updates und --delay-key-write=ALL starten, um Slave-seitig Geschwindigkeitsvorteile erzielen zu können. In diesem Fall verwendet der Slave nichttransaktionssichere MyISAM-Tabellen statt InnoDB- und BDB-Tabellen, um den transaktionsbedingten Mehraufwand zu umgehen und die Geschwindigkeit so zu steigern.

Frage: Was kann ich tun, um den Clientcode in meinen eigenen Anwendungen so zu formulieren, dass eine leistungssteigernde Replikation verwendet wird?

Antwort: Wenn der Teil Ihres Codes, der für den Datenbankzugriff zuständig ist, einwandfrei abstrahiert bzw. modularisiert ist, sollte die Konvertierung in eine Form, die in einer Replikationskonfiguration läuft, schnell und einfach erfolgen. Ändern Sie die Implementierung Ihres Datenbankzugriffs so, dass alle Schreiboperationen an den Master gesendet werden, und senden Sie die Leseoperationen an den Master oder einen Slave. Wenn Ihr Code nicht derart abstrahierbar ist, bietet Ihnen die Konfiguration eines Replikationssystems vielleicht die Möglichkeit und die Motivation, ihn entsprechend zu bereinigen. Erstellen Sie zunächst eine Wrapper-Bibliothek oder ein Wrapper-Modul, das die folgenden Funktionen implementiert:

  • safe_writer_connect()

  • safe_reader_connect()

  • safe_reader_statement()

  • safe_writer_statement()

Der Namensteil safe_ in den Funktionsnamen verweist darauf, dass die jeweilige Funktion alle Fehlerbedingungen selbst abfängt. Sie können für die Funktionen auch andere Namen verwenden. Wichtig ist lediglich, dass Sie über eine einheitliche Schnittstelle verfügen, um Lese- und Schreibverbindungen herzustellen und Lese- oder Schreiboperationen auszuführen.

Nachfolgend konvertieren Sie Ihren Clientcode so, dass er die Wrapper-Bibliothek verwendet. Unter Umständen ist dies anfangs ein schmerzlicher und beängstigender Vorgang, der sich aber langfristig auszahlt. Alle Anwendungen, die den gerade beschriebenen Ansatz verfolgen, können von einer Master/Slave-Konfiguration profitieren, auch wenn diese mehrere Slaves umfasst. Der Code ist weitaus einfacher zu pflegen, und das Hinzufügen von Problembehandlungsoptionen ist trivial. Sie müssen nur ein oder zwei Funktionen modifizieren – beispielsweise, wie lang eine Anweisung zur Ausführung benötigte oder welche der abgesetzten Anweisungen den Fehler zurückgegeben hat.

Wenn Sie viel Code geschrieben haben, sollten Sie diese Konvertierungsarbeit mit dem Hilfsprogramm replace automatisieren, welches Bestandteil der MySQL-Standarddistributionen ist, oder Ihr eigenes Konvertierungsskript abfassen. Im Idealfall verwendet Ihr Code konsistent die gängigen Stilkonventionen bei der Programmierung. Andernfalls wird es ohnehin einfacher sein, ihn neu zu erstellen oder ihn zumindest durchzuarbeiten und dabei manuell so zu vereinheitlichen, dass der Stil konsistent ist.

Frage: Wie stark und unter welchen Umständen kann die MySQL-Replikation die Leistung meines Systems verbessern?

Antwort: Die MySQL-Replikation ist am vorteilhaftesten für Systeme, die häufig Leseoperationen und seltener Schreiboperationen verarbeiten müssen. Theoretisch können Sie Ihr System bei Implementierung einer Konfiguration mit einem Master und mehreren Slaves skalieren, indem Sie weitere Slaves hinzufügen, bis entweder Ihre Netzwerkbandbreite erschöpft ist oder Ihr Aktualisierungsaufkommen so stark zugenommen hat, dass es der Master nicht mehr verarbeiten kann.

Um zu ermitteln, wie viele Slaves Sie verwenden können, bevor die Vorteile sich zu relativieren beginnen, und wie weit Sie die Leistungsfähigkeit Ihres Standorts verbessern können, müssen Sie Ihre Abfragemuster und das Verhältnis zwischen dem Durchsatz für Leseoperationen (Leseoperationen/Sekunde oder reads) und Schreiboperationen (writes) kennen auf einem typischen Master und einem typischen Slave durch Benchmark-Tests in Erfahrung bringen. Das folgende Beispiel zeigt eine relativ stark vereinfachte Berechnung der Auswirkungen der Replikation auf einem hypothetischen System.

Angenommen, die Systemlast umfasst 10 Prozent Schreiboperationen und 90 Prozent Leseoperationen. Durch ein Benchmarking haben wir ermittelt, dass reads 1200 – 2 × writes ist. Anders gesagt, kann das System 1200 Leseoperationen pro Sekunde ohne Schreiboperationen verarbeiten, ein Schreibvorgang erfolgt durchschnittlich halb so schnell wie ein Lesevorgang, und die Beziehung ist linear. Nehmen wir nun ferner an, dass der Master und jeder Slave jeweils die gleiche Kapazität aufweisen und dass wir einen Master und N Slaves haben. Daraus ergibt sich für jeden Server (Master oder Slave):

reads = 1200 – 2 × writes

reads = 9 × writes / (N + 1) (Leseoperationen werden aufgeteilt, während Schreiboperationen an alle Server gehen)

9 × writes / (N + 1) + 2 × writes = 1200

writes = 1200 / (2 + 9/(N+1))

Die letzte Gleichung gibt die maximale Anzahl von Schreibvorgängen für N Slaves basierend auf einer maximalen Leserate von 1200 pro Minute und einem Verhältnis von neun Leseoperationen pro Schreiboperation an.

Diese Analyse lässt die folgenden Rückschlüsse zu:

  • Wenn N = 0 ist (d. h. keine Replikation), dann kann unser System ca. 1200 ÷ 11 = 109 Schreiboperationen pro Sekunde verarbeiten.

  • Bei N = 1 sind 184 Schreiboperationen pro Sekunde möglich.

  • Bei N = 8 sind 400 Schreiboperationen pro Sekunde möglich.

  • Bei N = 17 sind 480 Schreiboperationen pro Sekunde möglich.

  • Schließlich kommen wir, je mehr sich N der Unendlichkeit (und unserem Budget der negativen Unendlichkeit) annähert, auf einen Wert von 600 Schreiboperationen pro Sekunde, während wir unseren Systemdurchsatz etwa auf das 5,5fache gesteigert haben. Bei nur acht Servern beträgt die Steigerung hingegen knapp das Vierfache.

Beachten Sie, dass diese Berechnungen eine uneingeschränkte Netzwerkbandbreite voraussetzen und mehrere andere Faktoren vernachlässigen, die für Ihr System von Bedeutung sein könnten. In vielen Fällen können Sie keine Berechnung ähnlich der obigen durchführen, mit der sich exakt voraussagen ließe, wie sich das Hinzufügen von N Replikationsslaves auf Ihr System auswirken würde. Allerdings kann Ihnen die Beantwortung der folgenden Fragen dabei helfen, zu bestimmen, ob und inwieweit eine Replikation die Leistungsfähigkeit Ihres Systems verbessern könnte:

  • Welches Verhältnis besteht zwischen Lese- und Schreiboperationen auf Ihrem System?

  • Wie viel mehr Schreiboperationen kann ein Server verarbeiten, wenn Sie die Anzahl der Leseoperationen verringern?

  • Wie viele Slaves unterstützt die Bandbreite in Ihrem Netzwerk?

Frage: Wie kann ich mithilfe der Replikation eine Redundanz oder Hochverfügbarkeit realisieren?

Antwort: Mit den derzeit verfügbaren Funktionen sollten Sie einen Master und einen Slave (oder mehrere Slaves) einrichten und ein Skript verfassen, welches den Master auf Verfügbarkeit prüft. Dann weisen Sie Ihre Anwendungen und die Slaves an, bei einem Ausfall des Masters einen anderen Master zu wählen. Hier ein paar Vorschläge:

  • Verwenden Sie die CHANGE MASTER TO-Anweisung, um einen Slave anzuweisen, den Master zu wechseln.

  • Eine gute Möglichkeit, Ihre Anwendungen bezüglich des Standorts des Masters auf dem aktuellen Stand zu halten, ist die Verwendung eines dynamischen DNS-Eintrags für den Master. Bei bind können Sie nsupdate verwenden, um Ihr DNS dynamisch zu aktualisieren.

  • Starten Sie Ihre Slaves mit der Option --log-bin und ohne die Option --log-slave-updates. Auf diese Weise ist ein Slave in der Lage, zum Master zu werden, sobald Sie die Anweisungen STOP SLAVE, RESET MASTER und CHANGE MASTER TO auf anderen Slaves absetzen. Angenommen, wir hätten folgende Konfiguration:

           WC
            \
             v
     WC----> M
           / | \
          /  |  \
         v   v   v
        S1   S2  S3
    

    In diesem Diagramm bezeichnet M den Master, S die Slaves und WC die Clients, die Schreib- und Lesevorgänge an die Datenbank absetzen. (Clients, die nur aus der Datenbank lesen, sind nicht vorhanden, da bei ihnen keine Änderungen erforderlich sind.) S1, S2 und S3 sind Slaves, die mit der Option --log-bin und ohne --log-slave-updates laufen. Da die von einem Slave empfangenen Updates nicht im Binärlog vermerkt werden, sofern nicht die Option --log-slave-updates angegeben ist, sind die Binärlogs auf den Slaves anfangs leer. Fällt nun M aus irgendeinem Grund aus, dann können Sie einen der Slaves auswählen, der dann der neue Master wird. Wenn Sie also etwa S1 auswählen, sollten alle WC auf S1 umgelenkt werden, der die Updates in sein Binärlog schreibt. S2 und S3 replizieren nachfolgend von S1.

    Sinn der Ausführung des Slaves ohne --log-slave-updates ist es, zu verhindern, dass Slaves Updates zweimal erhalten, was vorkommen kann, wenn einer der Slaves zum neuen Master wird. Nehmen wir einmal an, bei S1 wäre die Option --log-slave-updates aktiviert. Er schreibt nun Updates, die er von M empfängt, in sein eigenes Binärlog. Wenn S2 von M auf S1 also umschaltet, empfängt er Updates von S1, die er bereits von M erhalten hat.

    Stellen Sie sicher, dass alle Slaves alle Anweisungen im jeweiligen Relay-Log verarbeitet haben. Setzen Sie auf jedem Slave STOP SLAVE IO_THREAD ab und suchen Sie dann in der Ausgabe von SHOW PROCESSLIST die Angabe Has read all relay log. Wenn dieser Zustand von allen Slaves erreicht wurde, können sie auf die neue Konfiguration umgestellt werden. Auf dem Slave S1, der neuer Master werden soll, setzen Sie STOP SLAVE und RESET MASTER ab.

    Auf den anderen Slaves S2 und S3 setzen Sie STOP SLAVE und CHANGE MASTER TO MASTER_HOST='S1' ab (wobei 'S1' den echten Hostnamen von S1 darstellt). Zu CHANGE MASTER fügen Sie nun alle Informationen darüber hinzu, wie von S2 oder S3 aus eine Verbindung mit S1 hergestellt wird (also user, password, port). Sie müssen in CHANGE MASTER den Namen des Binärlogs von S1 oder der Binärlogposition, ab der gelesen werden soll, nicht angeben. Wir wissen, dass es das erste Binärlog und die Position 4 ist (dies sind die Standardwerte von CHANGE MASTER). Abschließend setzen Sie START SLAVE auf S2 und S3 ab.

    Nun weisen Sie alle WC an, ihre Anweisung an S1 zu leiten. Von diesem Punkt an werden alle Updateanweisungen, die von WC an S1 gesendet werden, in das Binärlog von S1 geschrieben, welches dann alle Updateanweisungen enthält, die seit dem Ausfall von M an S1 gesendet wurden.

    Das Ergebnis ist folgende Konfiguration:

           WC
          /
          |
     WC   |  M(unavailable)
      \   |
       \  |
        v v
         S1<--S2  S3
          ^       |
          +-------+
    

    Wenn M wieder betriebsbereit ist, müssen Sie darauf dieselbe CHANGE MASTER-Anweisung absetzen, die Sie auf S2 und S3 verwendet haben, damit M ein Slave von S1 wird und alle WC-Schreiboperationen empfängt, die er seit dem Ausfall verpasst hat. Um M wieder zum Master zu machen (etwa weil es sich dabei um das leistungsfähigste System handelt), verwenden Sie die beschriebene Methode erneut und tun dabei so, als ob S1 nicht mehr verfügbar wäre und M nun zum neuen Master wird. Während dieses Vorgangs dürfen Sie nicht vergessen, RESET MASTER auf M auszuführen, bevor Sie S1, S2 und S3 zu Slaves von M machen. Andernfalls empfangen diese Server alte WC-Schreiboperationen, die abgesetzt wurden, bevor M ausfiel.

Frage: Woher weiß ich, ob ein Master-Server das anweisungsbasierte oder das datensatzbasierte Binärlogformat verwendet?

Antwort: Überprüfen Sie den Wert der Systemvariablen binlog_format:

mysql> SHOW VARIABLES LIKE 'binlog_format';

Dieser heißt entweder STATEMENT (anweisungsbasierte Replikation) oder ROW (datensatzbasierte Replikation).

Frage: Wie weise ich einen Slave an, die datensatzbasierte Replikation zu verwenden?

Antwort: Slaves wissen automatisch, welches Format sie verwenden müssen.

6.12. Vergleich zwischen anweisungsbasierter und zeilenbasierter Replikation

Jedes Binärlogformat hat seine Vor- und Nachteile. Dieser Abschnitt fasst diese zusammen, um Ihnen eine Einschätzung zu erlauben, welches Format in Ihrer speziellen Situation das geeignetere ist.

Vorteile der anweisungsbasierten Replikation:

  • Bewährte Technologie, seit MySQL 3.23 vorhanden.

  • Kleinere Logdateien. Wenn Änderungs- oder Löschvorgänge viele Datensätze betreffen, sind die Logdateien wesentlich kleiner. Kleinere Logdateien erfordern weniger Speicherplatz und sind schneller gesichert.

  • Logdateien enthalten alle Anweisungen, mit denen Änderungen vorgenommen wurden, d. h., sie können zur Überwachung der Datenbank verwendet werden.

  • Logdateien können nicht nur zu Replikationszwecken, sondern auch zur Point-in-Time-Wiederherstellung verwendet werden. Siehe auch Abschnitt 5.10.3, „Zeitpunktbezogene Wiederherstellung“.

  • Ein Slave kann eine neuere MySQL-Version mit einer anderen Datensatzstruktur verwenden.

Nachteile der anweisungsbasierten Replikation:

  • Nicht alle UPDATE-Anweisungen können repliziert werden: Jedes nichtdeterministische Verhalten (z. B. bei der Verwendung von Zufallsfunktionen in einer SQL-Anweisung) ist bei der anweisungsbasierten Replikation schwer zu replizieren. Bei Anweisungen, die eine nichtdeterministische benutzerdefinierte Funktion (User-Defined Function, UDF) verwenden, ist die Replikation des Ergebnisses bei der anweisungsbasierten Replikation überhaupt nicht möglich (dagegen repliziert die datensatzbasierte Replikation einfach den von der UDF zurückgegebenen Wert).

  • Anweisungen können nicht korrekt repliziert werden, wenn sie eine UDF verwenden, die nichtdeterministisch ist (d. h. deren Wert von anderen Aspekten als den übergebenen Parametern abhängt).

  • Anweisungen können nicht korrekt repliziert werden, wenn sie eine der folgenden Funktionen enthalten:

    • LOAD_FILE()

    • UUID()

    • USER()

    • FOUND_ROWS()

    Alle übrigen Funktionen (einschließlich RAND(), NOW(), LOAD DATA INFILE usw.) werden korrekt repliziert.

  • INSERT ... SELECT erfordert eine höhere Zahl von Sperren auf Datensatzebene als bei der datensatzbasierten Replikation.

  • UPDATE-Anweisungen, die einen Tabellenscan erfordern (weil in der WHERE-Klausel kein Index verwendet wird), müssen eine höhere Anzahl von Datensätzen sperren als bei der datensatzbasierten Replikation.

  • (Nur bei InnoDB) Eine INSERT-Anweisung, die AUTO_INCREMENT verwendet, blockiert andere, nicht kollidierende INSERT-Anweisungen.

  • Langsamere Umsetzung von Daten auf dem Slave bei komplexen Abfragen.

  • Gespeicherte Funktionen (nicht aber gespeicherte Prozeduren) werden mit demselben NOW()-Wert wie die aufrufende Anweisung ausgeführt. (Dies kann abhängig von den Umständen ein Vor- oder Nachteil sein.)

  • Deterministische UDFs müssen auf die Slaves angewendet werden.

  • Wenn am Slave etwas nicht stimmt, nehmen die Unterschiede zwischen Master und Slave im Laufe der Zeit zu.

  • Tabellen müssen auf dem Master und dem Slave (fast) identisch sein.

Vorteile der datensatzbasierten Replikation:

  • Alles kann repliziert werden. Dies ist die sicherste Form der Replikation. Beachten Sie, dass zurzeit DDL-Anweisungen (Data Definition Language) wie etwa CREATE TABLE anweisungsbasiert repliziert werden, während bei DML-Anweisungen (Data Manipulation Language) sowie bei GRANT- und REVOKE-Anweisungen die Replikation datensatzbasiert erfolgt. Für Anweisungen wie CREATE ... SELECT wird eine CREATE-Anweisung aus der Tabellendefinition erstellt, die dann anweisungsbasiert repliziert wird, während das Einfügen von Datensätzen datensatzbasiert repliziert wird.

  • Die Technologie ist dieselbe wie bei den meisten anderen Datenbanksystemen – Kenntnisse anderer Systeme lassen sich einfach auf MySQL übertragen.

  • In vielen Fällen geht es bei Tabellen mit Primärschlüsseln schneller, wenn man die Daten auf den Slave anwendet.

  • Bei den folgenden Anweisungstypen werden weniger Sperren auf dem Master benötigt (was die Nebenläufigkeit erhöht):

    • INSERT ... SELECT

    • INSERT -Anweisungen mit AUTO_INCREMENT

    • UPDATE- oder DELETE-Anweisungen mit WHERE-Klauseln, die keine Schlüssel verwenden und die meisten der untersuchten Datensätze unverändert lassen

  • Weniger Sperren auf dem Slave bei INSERT-, UPDATE- oder DELETE-Anweisungen.

  • Es ist möglich, mehrere Threads hinzuzufügen, um Daten zukünftig auf den Slave anzuwenden (dies funktioniert bei SMP-Systemen besser).

Nachteile der datensatzbasierten Replikation:

  • Größere Logdateien (in manchen Fällen sogar wesentlich größer).

  • Das Binärlog enthält Daten für umfangreiche Anweisungen, die per Rollback rückgängig gemacht wurden.

  • Wenn Sie mit der datensatzbasierten Replikation eine Anweisung (z. B. eine UPDATE- oder DELETE-Anweisung) replizieren, muss jeder geänderte Datensatz in das Binärlog geschrieben werden. Im Gegensatz dazu wird bei Verwendung der anweisungsbasierten Replikation nur die Anweisung in das Binärlog geschrieben. Wenn die Anweisung viele Datensätze ändert, schreibt die datensatzbasierte Replikation deutlich mehr Daten in das Binärlog. In diesem Fall wird das Binärlog für eine längere Zeit gesperrt, um die Daten schreiben zu können, was Probleme mit der Nebenläufigkeit verursachen kann.

  • Deterministische UDFs, die große BLOB-Werte erzeugen, werden merklich langsamer repliziert.

  • Sie können die Logs darauf überprüfen, welche Anweisungen ausgeführt wurden.

  • Sie können auf dem Slave nicht nachprüfen, welche Anweisungen vom Master empfangen und dann ausgeführt wurden.

6.13. Replikation: Problemlösungen

Wenn Sie die Anleitung befolgt haben und Ihre Replikationskonfiguration trotzdem nicht funktioniert, sollten Sie zuallererst das Fehlerlog auf Meldungen überprüfen. Allzu viele Benutzer haben bei Auftreten eines Problems kostbare Zeit damit vergeudet, dies nicht gleich gemacht zu haben.

Wenn Sie aus dem Fehlerlog nicht ableiten können, welches Problem vorliegt, probieren Sie die folgenden Methoden aus:

  • Überprüfen Sie, ob am Master das binäre Loggen aktiviert ist, indem Sie eine SHOW MASTER STATUS-Anweisung absetzen. Bei aktiviertem Loggen ist Position ungleich null. Sollte das binäre Loggen nicht aktiviert sein, dann stellen Sie sicher, dass der Master mit den Optionen --log-bin und --server-id läuft.

  • Überprüfen Sie, ob der Slave ausgeführt wird. Mit SHOW SLAVE STATUS können Sie feststellen, ob die Werte von Slave_IO_Running und Slave_SQL_Running jeweils Yes lauten. Andernfalls überprüfen Sie die Optionen, die beim Start des Slave-Servers angegeben waren. So verhindert etwa --skip-slave-start, dass die Slave-Threads gestartet werden, bis Sie eine START SLAVE-Anweisung absetzen.

  • Wird der Slave ausgeführt, dann prüfen Sie, ob er eine Verbindung zum Master herstellen konnte. Setzen Sie SHOW PROCESSLIST ab, suchen Sie die I/O- und SQL-Threads und überprüfen Sie die zugehörigen State-Spalten. Siehe auch Abschnitt 6.4, „Replikation: Implementationsdetails“. Wenn für den I/O-Thread als Status Connecting to master angegeben ist, überprüfen Sie die Berechtigungen für den Replikationsbenutzer auf dem Master, den Hostnamen des Masters und Ihre DNS-Konfiguration und stellen Sie sicher, dass der Master ausgeführt wird und auch vom Slave erreicht werden kann.

  • Wurde der Slave bereits vorher ausgeführt, dann aber beendet, dann liegt das in der Regel daran, dass irgendeine Anweisung, die auf dem Master erfolgreich verarbeitet wurde, auf dem Slave fehlgeschlagen ist. Dies sollte niemals passieren, wenn Sie eine korrekte Momentaufnahme auf dem Master erstellt und die Daten auf dem Slave niemals außerhalb des Slave-Threads modifiziert haben. Wird der Slave unerwartet beendet, dann liegt entweder ein Bug vor, oder Sie sind auf eine der bekannten Einschränkungen der Replikation gestoßen, die in Abschnitt 6.8, „Replikation: Features und bekannte Probleme“, beschrieben sind. Wenn es sich um einen Bug handelt, lesen Sie Abschnitt 6.14, „Berichten von Replikationsfehlern und -problemen“, um zu erfahren, wie Sie diesen melden.

  • Wenn eine Anweisung, die auf dem Master klaglos verarbeitet wurde, nicht auf dem Slave ausgeführt werden kann, probieren Sie folgende Vorgehensweise aus, sofern die Durchführung einer vollständigen Datenbankneusynchronisierung durch Löschen der Datenbanken auf dem Slave und Kopieren einer neuen Momentaufnahme vom Master nicht realisierbar ist:

    1. Ermitteln Sie, ob die betreffende Tabelle auf dem Slave sich von der auf dem Master unterscheidet. Versuchen Sie zu ergründen, was geschehen ist. Dann machen Sie die Tabelle auf dem Slave identisch zu der auf dem Master und führen START SLAVE aus.

    2. Funktioniert der vorherige Schritt nicht oder ist er nicht durchführbar, dann prüfen Sie, ob es sicher ist, die Änderung (sofern erforderlich) manuell durchzuführen und die nächste Anweisung vom Master zu ignorieren.

    3. Wenn Sie feststellen, dass Sie die nächste Anweisung vom Master übergehen können, setzen Sie die folgenden Anweisungen ab:

      mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = N;
      mysql> START SLAVE;
      

      Der Wert von N sollte 1 sein, wenn die nächste Anweisung vom Master weder AUTO_INCREMENT noch LAST_INSERT_ID() verwendet. Andernfalls wählen Sie den Wert 2. Grund hierfür ist die Tatsache, dass Anweisungen, die AUTO_INCREMENT oder LAST_INSERT_ID() verwenden, zwei Ereignisse in das Binärlog des Masters schreiben.

    4. Wenn Sie ganz sicher sind, dass der Slave vollkommen synchron zum Master gestartet wurde und niemand die betreffenden Tabellen außerhalb des Slave-Threads modifiziert hat, dann ist die Diskrepanz mit hoher Wahrscheinlichkeit Ergebnis eines Bugs. Wenn Sie die aktuelle MySQL-Version verwenden, melden Sie dieses Problem bitte. Wenn Sie hingegen eine ältere Version einsetzen, aktualisieren Sie – sofern möglich – auf den aktuellen Produktions-Release, um festzustellen, ob das Problem fortbesteht.

6.14. Berichten von Replikationsfehlern und -problemen

Wenn Sie festgestellt haben, dass kein benutzerseitiger Fehler vorliegt und die Replikation trotzdem nicht stabil ist oder womöglich gar nicht funktioniert, ist es an der Zeit, uns einen Bugreport zu schicken. Wir benötigen von Ihnen so viele Informationen wie möglich, um den Bug aufzuspüren. Bitte nehmen Sie sich für die Vorbereitung des Bugreports Zeit und seien Sie sorgfältig bei Ihren Angaben.

Wenn Sie einen reproduzierbaren Testfall haben, der den Bug demonstriert, geben Sie diesen bitte in unsere Fehlerdatenbank ein. Eine Anleitung zur Vorgehensweise finden Sie in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“. Wenn Sie ein „Phantomproblem“ haben (d. h. eines, welches sich nicht gezielt reproduzieren lässt), dann gehen Sie wie folgt vor:

  1. Stellen Sie sicher, dass kein Fehler vorhanden ist. Wenn Sie am Slave beispielsweise Änderungen außerhalb des Slave-Threads vornehmen, dann sind die Daten nicht mehr synchron, und es kann bei Updates zu Verstößen aufgrund von Dubletten eindeutiger Schlüssel kommen. In diesem Fall bleibt der Slave-Thread stehen und wartet, bis Sie die Tabellen manuell bereinigt und die Synchronisation auf diese Weise wiederhergestellt haben. Dies ist kein replikationsbezogenes Problem. Die Replikation schlägt vielmehr aufgrund eines äußeren Störeinflusses fehl.

  2. Führen Sie den Slave mit den Optionen --log-slave-updates und --log-bin aus. Diese Optionen bewirken, dass der Slave die Updates, die er vom Master erhält, in seine eigenen Binärlogs schreibt.

  3. Speichern Sie alle Beweismittel, bevor Sie den Replikationsstatus zurücksetzen. Wenn wir keine oder nur bruchstückhafte Informationen erhalten, wird es schwierig bis unmöglich, die Problemursache zu ermitteln. Folgende Beweisstücke sollten Sie übermitteln:

    • alle Binärlogs des Masters

    • alle Binärlogs des Slaves

    • Ausgabe von SHOW MASTER STATUS auf dem Master zum Zeitpunkt der Feststellung des Problems

    • Ausgabe von SHOW SLAVE STATUS auf dem Slave zum Zeitpunkt der Feststellung des Problems

    • Fehlerlogs von Master und Slave

  4. Überprüfen Sie mit mysqlbinlog die Binärlogs. Folgender Befehl sollte zur Ermittlung der problematischen Abfrage hilfreich sein. Hierbei sind log_pos und log_file die Werte Master_Log_File bzw. Read_Master_Log_Pos in der Ausgabe von SHOW SLAVE STATUS.

    shell> mysqlbinlog -j log_pos \
              log_file | head
    

Nachdem Sie alle Beweisstücke für das Problem gesammelt haben, versuchen Sie es zunächst als separaten Testfall zu extrahieren. Geben Sie das Problem danach mit möglichst vielen Informationen in unsere Bugdatenbank ein. Die Vorgehensweise ist in Abschnitt 1.8, „Wie man Bugs oder Probleme meldet“, beschrieben.

6.15. Auto-Increment in der Multi-Master-Replikation

Wenn mehrere Server als Replikationsmaster konfiguriert sind, müssen spezielle Schritte unternommen werden, um Schlüsselkollisionen bei der Verwendung von AUTO_INCREMENT-Spalten zu verhindern; andernfalls könnten mehrere Master beim Einfügen von Datensätzen versuchen, denselben AUTO_INCREMENT-Wert zu verwenden.

Die Systemvariablen auto_increment_increment und auto_increment_offset ermöglichen die Multi-Master-Replikation in Verbindung mit AUTO_INCREMENT-Spalten. Jede dieser Variablen hat einen Standard- und Mindestwert von 1. Der Höchstwert beträgt jeweils 65.535.

Diese beiden Variablen beeinflussen das Verhalten von AUTO_INCREMENT-Spalten wie folgt:

  • auto_increment_increment steuert das Intervall zwischen aufeinander folgenden AUTO_INCREMENT-Werten.

  • auto_increment_offset bestimmt den Startwert der Spalte AUTO_INCREMENT.

Durch Auswahl nichtkollidierender Werte auf verschiedenen Mastern wird dafür gesorgt, dass Server in einer Multimaster-Umgebung beim Einfügen neuer Datensätze in dieselbe Tabelle keine kollidierenden AUTO_INCREMENT-Werte verwenden. Stellen Sie die Variablen wie folgt ein, um N Master-Server zu konfigurieren:

  • Setzen Sie auto_increment_increment auf jedem Master auf N.

  • Stellen Sie auf jedem der N Master einen unterschiedlichen Wert für auto_increment_offset ein (0, 1, 2, … , N – 1).

Weitere Informationen zu auto_increment_increment und auto_increment_offset finden Sie in Abschnitt 5.2.2, „Server-Systemvariablen“.


Dies ist eine Übersetzung des MySQL-Referenzhandbuchs, das sich auf dev.mysql.com befindet. Das ursprüngliche Referenzhandbuch ist auf Englisch, und diese Übersetzung ist nicht notwendigerweise so aktuell wie die englische Ausgabe. Das vorliegende deutschsprachige Handbuch behandelt MySQL bis zur Version 5.1.