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:
Stellen Sie sicher, dass der Slave eine eindeutige Serverkennung hat.
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
;
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.
Setzen Sie die folgende Anweisung ab, um eine globale Lesesperre zu erwirken:
mysql> FLUSH TABLES WITH READ LOCK;
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
Setzen Sie nun folgende Anweisung ab und notieren Sie die Ausgabe (Sie werden sie später noch benötigen):
mysql> SHOW MASTER STATUS;
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:
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.
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.
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 / (
(Leseoperationen werden aufgeteilt, während
Schreiboperationen an alle Server gehen)
N
+ 1)
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.
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.