Baron Schwartz / Peter Zaitsev / Vadim Tkachenko

Werbung
D3kjd3Di38lk323nnm
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replikation
Inhalt
Vorwort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XI
1 Die MySQL-Architektur
.............................................. 1
Die logische Architektur von MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Nebenläufigkeitskontrolle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Transaktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Multi-Version Concurrency Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Die Storage-Engines von MySQL. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2 Engpässe finden: Benchmarking und Profiling. . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Wozu Benchmarks? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Benchmarking-Strategien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Benchmarking-Taktiken. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Benchmarking-Werkzeuge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Benchmarking-Beispiele . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Profiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Profiling des Betriebssystems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
36
41
46
48
59
82
3 Schema-Optimierung und Indizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Optimale Datentypen auswählen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Grundlagen der Indizierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Indizierungsstrategien für High Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
Indizierung – eine Fallstudie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Index- und Tabellenpflege . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
Normalisierung und Denormalisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
ALTER TABLE beschleunigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
Hinweise zu Storage-Engines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
|
V
4 Optimierung der Abfrageleistung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
Grundlagen langsamer Abfragen: Datenzugriff optimieren . . . . . . . . . . . . . . . . .
Methoden zum Umstrukturieren von Abfragen. . . . . . . . . . . . . . . . . . . . . . . . . .
Grundlagen der Abfrageverarbeitung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Grenzen des MySQL-Abfrageoptimierers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Bestimmte Arten von Abfragen optimieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Hinweise für den Abfrageoptimierer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Benutzerdefinierte Variablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5 Erweiterte MySQL-Funktionen
......................................
Der MySQL-Abfrage-Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Code in MySQL speichern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Cursor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Vorbereitete Anweisungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Benutzerdefinierte Funktionen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Zeichensätze und Sortierreihenfolgen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Volltextsuche . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Fremdschlüsselbeschränkungen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Merge-Tabellen und Partitionierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Verteilte (XA-) Transaktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
163
169
172
192
202
210
213
220
220
234
242
243
248
250
255
263
272
273
283
6 Die Servereinstellungen optimieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
Grundlagen der Konfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Allgemeines Tuning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Das Ein-/Ausgabeverhalten von MySQL anpassen . . . . . . . . . . . . . . . . . . . . . . .
Die MySQL-Nebenläufigkeit anpassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Lastbasierte Anpassungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Verbindungsbezogene Werte anpassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7 Betriebssystem- und Hardwareoptimierung
...........................
Was beschränkt die Leistung von MySQL? . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Wie Sie CPUs für MySQL auswählen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Speicher- und Festplattenressourcen abwägen. . . . . . . . . . . . . . . . . . . . . . . . . . .
Hardware für einen Slave wählen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
RAID-Leistungsoptimierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Storage Area Networks und Network-Attached Storage . . . . . . . . . . . . . . . . . . .
Mehrere Festplatten-Volumes benutzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Netzwerkkonfiguration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
VI
287
293
304
320
323
330
331
332
332
336
345
345
354
355
358
| Inhalt
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Ein Betriebssystem wählen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ein Dateisystem wählen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Threading. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Swapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Der Betriebssystemstatus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8 Replikation
.....................................................
Replikation im Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Replikation einrichten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Replikation näher betrachtet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Replikationstopologien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Replikation und Kapazitätsplanung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Replikationsadministration und -wartung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Replikationsprobleme und Lösungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Wie schnell ist die Replikation? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Die Zukunft der MySQL-Replikation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
360
361
363
364
366
373
373
377
386
393
408
410
421
441
443
9 Skalierung und Hochverfügbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
Terminologie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
MySQL skalieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Lastausgleich . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Hochverfügbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
446
448
475
487
10 Optimierung auf Anwendungsebene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
Überblick über die Anwendungsleistung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Webserverprobleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Caching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
MySQL erweitern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Alternativen zu MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
498
502
505
512
514
11 Backup und Wiederherstellung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
Überblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Überlegungen und Kompromisse. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Binärlogs organisieren und sichern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Daten in einem Backup sichern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Wiederherstellung aus einem Backup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Backup- und Wiederherstellungsgeschwindigkeit . . . . . . . . . . . . . . . . . . . . . . . .
Backup-Werkzeuge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Backups mit Skripten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
516
521
531
534
546
558
558
566
Inhalt | VII
12 Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 570
Terminologie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Account-Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Betriebssystemsicherheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Netzwerksicherheit. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Datenverschlüsselung. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
MySQL in einer chroot-Umgebung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13 Der MySQL-Serverstatus
...........................................
Systemvariablen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
SHOW STATUS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
SHOW INNODB STATUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
SHOW PROCESSLIST. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
SHOW MUTEX STATUS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Status der Replikation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
INFORMATION_SCHEMA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
570
571
592
593
601
606
608
608
609
616
631
631
633
634
14 Werkzeuge für High Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 636
Schnittstellenwerkzeuge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Überwachungswerkzeuge. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Analysewerkzeuge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
MySQL-Dienstprogramme. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Weitere Informationsquellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
636
638
649
652
655
A Große Dateien übertragen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 656
B EXPLAIN benutzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661
C Sphinx mit MySQL benutzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677
D Sperren debuggen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706
Index
...............................................................
VIII |
Inhalt
717
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
KAPITEL 8
Replikation
Wir untersuchen in diesem Kapitel alle Aspekte der Replikation. Wir beginnen mit einem
Überblick über die Funktionsweise, schauen uns dann die grundlegenden Servereinstellungen, die Gestaltung aufwendigerer Replikationskonfigurationen sowie die Verwaltung
und Optimierung der replizierten Server an. Obwohl wir uns in diesem Buch im Allgemeinen vor allem auf die Performance konzentrieren, kümmern wir uns in Bezug auf die
Replikation auch um die Korrektheit und die Zuverlässigkeit. Außerdem schauen wir uns
einige künftige Änderungen und Verbesserungen bei der MySQL-Replikation an, wie
etwa interessante Patches, die von Google geschaffen wurden.
Replikation im Überblick
Das Grundproblem, das mithilfe der Replikation gelöst wird, ist Folgendes: Wie hält
man die Daten eines Servers synchron zu den Daten eines anderen? Viele Slaves können
sich mit einem einzigen Master verbinden, und ein Slave kann wiederum als Master auftreten. Sie können Master und Slaves in vielen unterschiedlichen Topologien anordnen.
Sie können den gesamten Server oder nur bestimmte Datenbanken replizieren oder sogar
wählen, welche Tabellen Sie replizieren wollen.
MySQL unterstützt zwei Arten der Replikation: anweisungsbasierte Replikation und zeilenbasierte Replikation. Die anweisungsbasierte (oder »logische«) Replikation gibt es seit
MySQL 3.23. Sie wird von den meisten Leuten heutzutage in der Praxis eingesetzt. Zeilenbasierte Replikation ist dagegen neu in MySQL 5.1. Bei beiden Arten werden Änderungen
| 373
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Die in MySQL integrierte Fähigkeit zur Replikation ist die Grundlage für den Aufbau
großer, leistungsstarker Anwendungen auf MySQL-Basis. Die Replikation erlaubt es
Ihnen, einen oder mehrere Server als Slaves oder Repliken eines anderen Servers zu konfigurieren. Das ist nicht nur für High-Performance-Anwendungen sinnvoll, sondern auch
für viele andere Aufgaben, wie etwa das gemeinsame Benutzen von Daten mit einem
externen Büro, das Vorhalten eines »Hot Spare« oder das Betreiben eines Servers mit
einer Kopie der Daten zu Test- oder Schulungszwecken.
im Binärlog des Masters1 aufgezeichnet, und das Log wird dann auf dem Slave wieder abgespielt. Beide sind asynchron – d.h., es gibt keine Garantie, dass die Kopie der Daten auf dem
Slave in jedem Moment auf dem neuesten Stand ist.2 Es gibt keine Gewähr, wie groß die
Latenz auf dem Slave sein könnte. Große Abfragen könnten dafür sorgen, dass der Slave
Sekunden, Minuten oder sogar Stunden hinter den Master zurückfällt.
Die Replikation erhöht im Allgemeinen den Aufwand auf dem Master nicht sehr. Auf
dem Master muss das binäre Logging aktiviert sein, das recht aufwendig sein kann, allerdings brauchen Sie das sowieso für ordentliche Backups. Abgesehen vom Binär-Logging
bringt beim normalen Betrieb auch jeder angeschlossene Slave eine gewisse zusätzliche
Last auf dem Master mit sich (hauptsächlich Netzwerk-Ein-/Ausgaben).
Replikation eignet sich relativ gut zum Skalieren von Leseoperationen, die Sie an einen
Slave umleiten können, ist allerdings nur dann eine gute Methode zum Skalieren von
Schreibvorgängen, wenn Sie sie richtig gestaltet haben. Beim Anschließen vieler Slaves an
einen Master werden die Schreiboperationen lediglich viele Male, nämlich einmal auf
jedem Slave, ausgeführt. Das gesamte System ist auf die Anzahl der Schreiboperationen
beschränkt, die der schwächste Teil ausführen kann.
Auch wenn man mehr als nur ein paar Slaves hat, ist eine Replikation eine Verschwendung, weil dabei im Prinzip eine Menge Daten unnötigerweise dupliziert werden. So
besitzt z.B. ein einziger Master mit 10 Slaves 11 Kopien derselben Daten und dupliziert
den größten Teil dieser Daten in 11 unterschiedliche Caches. Das ist analog zu einem 11fachen RAID 1 auf der Serverebene. Es ist keine ökonomische Anwendung der Hardware, kommt aber überraschend oft vor. Wir werden in diesem Kapitel Methoden vorstellen, um dieses Problem zu umgehen.
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Die Replikation ist in MySQL meist abwärtskompatibel. Das heißt, dass ein neuerer Server normalerweise ohne Probleme der Slave eines älteren Servers sein kann. Ältere Versionen des Servers dagegen sind oft nicht in der Lage, als Slaves der neueren Versionen zu
dienen: Sie verstehen möglicherweise neue Funktionen oder die SQL-Syntax nicht, die
neuere Server benutzen, außerdem können sich die bei der Replikation verwendeten
Dateiformate unterscheiden. So können Sie z.B. nicht von einem MySQL-5.0-Master zu
einem MySQL-4.0-Slave replizieren. Testen Sie auf jeden Fall Ihre Replikationseinstellung, bevor Sie von einer Hauptversion auf eine andere wechseln, also etwa von 4.1 auf
5.0 oder von 5.0 auf 5.1.
1 Wenn das Binärlog neu für Sie ist, finden Sie in Kapitel 6, in diesem Kapitel und in Kapitel 11 weitere Informationen.
2 Mehr dazu finden Sie in »Synchrone MySQL-Replikation« auf Seite 492.
374 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Probleme, die durch die Replikation gelöst werden
Hier sind einige der gebräuchlichsten Anwendungsfälle für die Replikation:
Lastausgleich
Die MySQL-Replikation kann Ihnen dabei helfen, Leseabfragen über mehrere Server zu verteilen, was auch gut für leseintensive Anwendungen funktioniert. Mit einigen einfachen Codeänderungen erreichen Sie sogar einen einfachen Lastausgleich.
In kleinem Maßstab benutzen Sie vereinfachte Ansätze, wie fest kodierte Hostnamen oder Lastverteilung per DNS (bei dem ein Hostname auf mehrere IP-Adressen
zeigt). Sie können auch raffiniertere Ansätze verfolgen. Normale Lösungen zum
Lastausgleich, wie etwa Produkte zum Lastausgleich in Netzwerken, können die
Last zwischen MySQL-Servern verteilen. Auch das LVS-Projekt (Linux Virtual Server) funktioniert ganz gut. Wir befassen uns in Kapitel 9 mit Lastausgleich.
Backups
Replikation bietet eine wertvolle Technik zum Unterstützen von Backups. Allerdings stellt ein Slave weder ein Backup noch einen Ersatz für Backups dar.
Hochverfügbarkeit und Failover
Mithilfe der Replikation können Sie vermeiden, dass MySQL der einzige Schwachpunkt in Ihrer Anwendung ist. Mit einem guten Failover-System (System zur Ausfallsicherung) mit replizierten Slaves können Sie die Ausfallzeiten drastisch
verringern. Failover behandeln wir ebenfalls in Kapitel 9.
Testen von MySQL-Upgrades
Es ist üblich, einen Slave-Server mit einer aufgerüsteten MySQL-Version auszustatten und mit seiner Hilfe zu überprüfen, ob die Abfragen erwartungsgemäß funktionieren, bevor man alle anderen Server umrüstet.
Wie die Replikation funktioniert
Bevor wir uns detailliert damit befassen, wie man die Replikation einrichtet, wollen wir
uns anschauen, wie MySQL tatsächlich Daten repliziert. Global gesehen, handelt es sich
bei der Replikation um einen einfachen dreiteiligen Vorgang:
3 Obwohl, wie wir später sehen werden, die zeilenbasierte Replikation, die in MySQL 5.1 eingeführt wurde, viel
mehr Bandbreite benutzen könnte als die traditionellere, anweisungsbasierte Replikation.
Replikation im Überblick | 375
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Datenverteilung
Die Replikation von MySQL ist normalerweise nicht sehr bandbreitenintensiv,3 und
Sie können sie nach Belieben stoppen und starten. Sie eignet sich daher, um eine
Kopie Ihrer Daten an einem räumlich entfernten Ort anzulegen, wie etwa in einem
anderen Rechenzentrum. Der entfernte Slave kann sogar über eine Verbindung agieren, die nur sporadisch existiert (ob absichtlich oder nicht). Falls Ihre Slaves allerdings nur eine geringe Verzögerung bei der Replikation haben sollen, brauchen Sie
eine stabile Verbindung mit geringer Latenz.
1. Der Master zeichnet die Änderungen an seinen Daten in seinem Binärlog auf. (Diese
Aufzeichnungen werden als Binärlog-Events bezeichnet.)
2. Der Slave kopiert die Binärlog-Events des Masters in sein Relay-Log.
3. Der Slave spielt die Ereignisse im Relay-Log noch einmal ab und wendet damit die
Das ist nur der Überblick – die einzelnen Schritte sind relativ komplex. Abbildung 8-1
verdeutlicht die Replikation im Detail.
Master
Slave
Ein/AusgabeThread
Datenänderungen
SQL-Thread
Lesen
Lesen
Schreiben
Binärlog
Wiederabspielen
RelayLog
Abbildung 8-1: Wie die MySQL-Replikation funktioniert
Der erste Teil dieses Vorgangs ist das Schreiben in das Binärlog auf dem Master (wir zeigen Ihnen später, wie Sie das einrichten). Direkt, bevor eine Transaktion, die Daten auf
dem Master aktualisiert, fertig wird, schreibt der Master die Änderungen in sein Binärlog.
MySQL schreibt die Transaktionen seriell in das Binärlog, auch wenn die Anweisungen
in den Transaktionen während der Ausführung verschachtelt wurden. Nachdem die
Events in das Binärlog geschrieben wurden, weist der Master die Storage-Engine(s) an,
die Transaktionen zu bestätigen.
Im nächsten Schritt muss der Slave das Binärlog des Masters auf seine eigene Festplatte
kopieren, und zwar in das sogenannte Relay-Log. Zuerst startet er einen Arbeits-Thread,
den Ein-/Ausgabe-Slave-Thread. Der Ein-/Ausgabe-Thread öffnet eine normale Clientverbindung zum Master und startet dann einen speziellen Binlog-Dump-Prozess (es gibt
dazu keinen SQL-Befehl). Der Binlog-Dump-Prozess liest die Events aus dem Binärlog
des Masters. Er fragt nicht nach Events. Wenn er mit dem Master fertig ist, wird er
zurückgestellt und wartet auf das Signal des Masters, das besagt, dass es wieder neue
Events gibt. Der Ein-/Ausgabe-Thread schreibt die Events in das Relay-Log des Slaves.
376 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Änderungen auf seine eigenen Daten an.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Vor MySQL 4.0 funktionierte die Replikation in vielen Aspekten ganz
anders. Zum Beispiel verwendete die erste Replikationsfunktionalität von
MySQL kein Relay-Log, so dass bei der Replikation nur zwei Threads zum
Einsatz kamen und nicht drei. Die meisten Leute verwenden inzwischen
aber neuere MySQL-Versionen, wir werden uns daher in diesem Kapitel
nicht über die sehr alten Versionen von MySQL auslassen.
Abbildung 8-1 zeigte nur zwei Replikations-Threads auf dem Slave. Es gibt aber außerdem einen Thread auf dem Master: Wie jede Verbindung zu einem MySQL-Server startet
die Verbindung, die der Slave zum Master öffnet, einen Thread auf dem Master.
Diese Replikationsarchitektur koppelt die Vorgänge des Holens und des Abspielens von
Events auf dem Slave voneinander ab, wodurch sie asynchron ausgeführt werden können. Das heißt, der Ein-/Ausgabe-Thread kann unabhängig vom SQL-Thread arbeiten.
Sie erlegt dem Replikationsprozess außerdem Beschränkungen auf, von denen die wichtigste lautet, dass die Replikation auf dem Slave serialisiert wird. Das bedeutet, dass Aktualisierungen, die auf dem Master möglicherweise parallel (in unterschiedlichen Threads)
ausgeführt wurden, auf dem Slave nicht parallelisiert werden können. Wie wir später
sehen werden, ist das für viele Lasten ein möglicher Performance-Engpass.
Die Replikation einrichten
Das Einrichten der Replikation ist in MySQL ein relativ einfacher Vorgang, es gibt für die
grundlegenden Schritte allerdings viele Variationen, die vom jeweiligen Szenario abhängen. Das einfachste Szenario sind frisch installierte Master und Slaves. Auf einer höheren
Ebene sieht das Vorgehen so aus:
1. einrichten der Replikations-Accounts auf jedem Server
2. konfigurieren von Master und Slave
3. den Slave anweisen, eine Verbindung zum Master herzustellen und ihn zu replizieren
Hier wird davon ausgegangen, dass viele Standardeinstellungen ausreichen, was in der
Tat zutrifft, wenn Sie den Master und den Slave gerade installiert haben und sie die gleichen Daten aufweisen (die vorgegebene mysql-Datenbank). Wir zeigen Ihnen, wie Sie die
einzelnen Schritte ausführen. Dabei nehmen wir an, dass Ihre Server server1 (IP-Adresse
192.168.0.1) und server2 (IP-Adresse 192.168.0.2) heißen. Anschließend erläutern wir,
wie man einen Slave von einem Server aus initialisiert, der bereits läuft, und untersuchen
die empfohlene Replikationskonfiguration.
Die Replikation einrichten | 377
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Der SQL-Slave-Thread erledigt den letzten Teil des Vorgangs. Dieser Thread liest die
Events aus dem Relay-Log und spielt sie wieder ab, wobei er die Daten des Slaves aktualisiert, damit sie schließlich denen des Masters entsprechen. Solange dieser Thread mit dem
Ein-/Ausgabe-Thread Schritt hält, bleibt das Relay-Log normalerweise im Cache des
Betriebssystems, Relay-Logs verursachen also einen sehr geringen Overhead. Die Events,
die der SQL-Thread ausführt, können optional in das Slave-eigene Binärlog übernommen
werden. Wir kommen später auf Szenarien zurück, bei denen sich das als sinnvoll erweist.
Replikations-Accounts anlegen
mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.*
-> TO repl@'192.168.0.%' IDENTIFIED BY 'p4ssword';
Diesen Account legen wir sowohl auf dem Master als auch auf dem Slave an. Beachten
Sie, dass wir den Benutzer auf das lokale Netzwerk beschränkt haben, weil der Replikations-Account unsicher ist. (In Kapitel 12 erfahren Sie mehr über die Sicherheit.)
Der Replikationsbenutzer benötigt eigentlich nur die Berechtigung REPLICATION CLIENT auf dem Master; die Berechtigung REPLICATION SLAVE auf beiden Servern ist nicht erforderlich. Weshalb also gewähren wir diese
Berechtigungen auf beiden Servern? Das hat zwei Gründe:
• Der Account, den Sie benutzen, um die Replikation zu überwachen
und zu verwalten, braucht die Berechtigung REPLICATION SLAVE. Es
ist einfacher, den gleichen Account für beide Zwecke einzusetzen,
anstatt einen eigenen Benutzer für diese Aufgabe anzulegen.
• Wenn Sie den Account auf dem Master einrichten und dann den
Slave vom Master klonen, wird der Slave korrekterweise so eingerichtet, dass er als Master agiert, falls Sie irgendwann einmal die Rollen
von Master und Slave vertauschen wollen.
Master und Slave konfigurieren
Der nächste Schritt besteht darin, einige Einstellungen auf dem Master zu aktivieren, der
bei uns den Namen server1 tragen soll. Sie müssen das Binär-Logging einschalten und
eine Server-ID angeben. Setzen Sie die folgenden Zeilen in die my.cnf-Datei des Masters
(oder überprüfen Sie, ob diese Zeilen vorhanden sind):
log_bin
server_id
= mysql-bin
= 10
Die exakten Werte müssen Sie selbst einsetzen. Wir nehmen hier den einfachsten Weg,
Sie können natürlich etwas Raffinierteres verwenden.
Sie müssen explizit eine eindeutige Server-ID festlegen. Wir haben beschlossen, 10 anstelle
von 1 zu nehmen, weil 1 die Vorgabe ist, die ein Server typischerweise wählt, wenn kein
Wert angegeben wurde. (Das ist versionsabhängig; manche MySQL-Versionen funktionieren dann einfach nicht.) Die 1 kann deshalb leicht zu Verwirrung und Konflikten mit Servern führen, die keine expliziten Server-IDs besitzen. Oft wird das letzte Oktett der IPAdresse des Servers benutzt, vorausgesetzt natürlich, dass die Adresse sich nicht ändert
und eindeutig ist (d.h., dass die Server nur zu einem Subnetz gehören).
378 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
MySQL verfügt über einige besondere Berechtigungen, die den Replikationsprozessen
die Ausführung erlauben. Der Slave-Ein-/Ausgabe-Thread, der auf dem ReplikationsSlave-Server läuft, stellt eine TCP/IP-Verbindung zum Master her. Sie müssen also einen
Benutzer-Account auf dem Master anlegen und diesem die richtigen Berechtigungen verleihen, damit der Ein-/Ausgabe-Thread sich als dieser Benutzer anmelden und das Binärlog des Masters lesen kann. Wir erzeugen hier einen Benutzer-Account namens repl:
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File
| Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |
98 |
|
|
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
Der Slave verlangt in seiner my.cnf-Datei eine Konfiguration ähnlich der des Masters,
außerdem müssen Sie MySQL auf dem Slave neu starten:
log_bin
server_id
relay_log
log_slave_updates
read_only
=
=
=
=
=
mysql-bin
2
mysql-relay-bin
1
1
Technisch gesehen, sind einige dieser Optionen nicht erforderlich, und für einige geben
wir einfach nur explizit die Vorgabewerte an. Tatsächlich wird auf einem Slave nur der
Parameter server_id verlangt, wir haben aber auch log_bin aktiviert und der BinärlogDatei einen expliziten Namen gegeben. Standardmäßig wird sie nach dem Hostnamen
des Servers benannt, das kann aber zu Problemen führen, wenn sich der Hostname
ändert. Außerdem wollen wir, dass die Logs jedes Servers gleich heißen, um eine einfache
Slave-zu-Master-Umwandlung zu erlauben. Das heißt, nicht nur der Replikationsbenutzer auf Master und Slave ist gleich, sondern auch die Einstellungen für beide.
Wir haben außerdem zwei weitere optionale Konfigurationsparameter hinzugefügt:
relay_log (um die Lage und den Namen des Relay-Logs anzugeben) und log_slave_
updates (damit der Slave die replizierten Events in sein eigenes Binärlog schreiben kann).
Die zweite Option verursacht auf den Slaves zusätzliche Arbeit, doch wie Sie später sehen
werden, haben wir gute Gründe dafür, diese optionalen Einstellungen auf jedem Slave
hinzuzufügen.
Manche Leute aktivieren nur das Binärlog und nicht log_slave_updates, so dass sie es
merken, ob irgendetwas, wie etwa eine fehlkonfigurierte Anwendung, Daten auf dem
Slave modifiziert. Falls möglich sollten Sie die Konfigurationseinstellung read_only
benutzen, die verhindert, dass andere als die besonders berechtigten Threads Daten
ändern. (Gewähren Sie Ihren Benutzern nicht mehr Berechtigungen als nötig!) Allerdings
ist read_only oft nicht praktisch, vor allem nicht für Anwendungen, die in der Lage sein
müssen, Tabellen auf Slaves zu erzeugen.
Die Replikation einrichten | 379
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Wenn das Binär-Logging noch nicht in der Konfigurationsdatei des Masters angegeben
war, müssen Sie MySQL neu starten. Um sicherzustellen, dass die Binärlog-Datei auf
dem Master angelegt wurde, führen Sie SHOW MASTER STATUS aus und überprüfen, ob Sie
eine Ausgabe erhalten, die der folgenden Ausgabe ähnelt. (MySQL hängt einige Ziffern
an den Dateinamen an, Sie sehen daher bei der Datei nicht exakt den Namen, den Sie
angegeben haben.)
Setzen Sie die Replikationskonfigurationsoptionen, wie etwa master_host
und master_port, nicht in die my.cnf-Datei des Slaves. Diese alte Methode
der Konfiguration eines Slaves wird nicht mehr empfohlen. Sie kann Probleme verursachen und bringt keine Vorteile mit sich.
Der nächste Schritt besteht darin, dass man dem Slave mitteilt, wie er sich mit dem Server
verbinden und seine Binärlogs abspielen soll. Benutzen Sie dafür nicht die Datei my.cnf,
sondern nehmen Sie die Anweisung CHANGE MASTER TO. Diese Anweisung ersetzt die entsprechenden my.cnf-Einstellungen komplett. Sie erlaubt es Ihnen auch, den Slave in
Zukunft auf einen anderen Master zu richten, ohne den Server zu stoppen. Hier ist die
Anweisung, die Sie zum Start der Replikation auf dem Slave ausführen müssen:
mysql>
->
->
->
->
CHANGE MASTER TO MASTER_HOST='server1',
MASTER_USER='repl',
MASTER_PASSWORD='p4ssword',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=0;
Der Parameter MASTER_LOG_POS ist auf 0 gesetzt, weil dies der Anfang des Logs ist. Nachdem Sie dies ausgeführt haben, sollten Sie anhand der Ausgabe von SHOW SLAVE STATUS
feststellen können, dass die Einstellungen des Slaves korrekt sind:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 4
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
...omitted...
Seconds_Behind_Master: NULL
Die Spalten Slave_IO_State, Slave_IO_Running und Slave_SQL_Running zeigen, dass die
Slave-Prozesse nicht laufen. Scharfsinnige Leser werden auch bemerken, dass die LogPosition 4 anstelle von 0 ist. Das liegt daran, dass 0 eigentlich keine Log-Position ist; sie
bedeutet nur »am Anfang der Log-Datei«. MySQL weiß, dass das erste Event tatsächlich
an Position 4 kommt.4
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Den Slave starten
4 Wie Sie an der früheren Ausgabe von SHOW MASTER STATUS erkennen können, befindet es sich tatsächlich an Position 98. Master und Slave machen das miteinander aus, sobald der Slave sich mit dem Master verbunden hat,
was noch nicht geschehen ist.
380 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Um die Replikation zu starten, führen Sie folgenden Befehl aus:
mysql> START SLAVE;
Dieser Befehl erzeugt keine Fehlermeldungen oder Ausgaben. Untersuchen Sie jetzt noch
einmal SHOW SLAVE STATUS:
Sie sehen, dass sowohl die Slave-Ein-/Ausgabe- als auch die SQL-Threads laufen und
dass Seconds_Behind_Master nicht mehr NULL ist (wir untersuchen später, was
Seconds_Behind_Master bedeutet). Der Ein-/Ausgabe-Thread wartet auf ein Event vom
Master, was bedeutet, dass er alle Binärlogs des Masters geholt hat. Die Log-Positionen
haben sich erhöht, es wurden also einige Events geholt und ausgeführt (Ihre Ergebnisse
werden anders aussehen). Wenn Sie auf dem Master eine Änderung vornehmen, sollten
Sie sehen, dass sich die verschiedenen Datei- und Positionseinstellungen auf dem Slave
erhöhen. Sie sollten auch Änderungen an den Datenbanken auf dem Slave feststellen
können!
Sie erkennen auch die Replikations-Threads in den jeweiligen Prozesslisten auf dem Master und dem Slave. Auf dem Master sollten Sie eine Verbindung sehen, die vom Ein-/Ausgabe-Thread des Slaves erzeugt wurde:
mysql> SHOW PROCESSLIST\G
*************************** 1. row ***************************
Id: 55
User: repl
Host: slave1.webcluster_1:54813
db: NULL
Command: Binlog Dump
Time: 610237
State: Has sent all binlog to slave; waiting for binlog to be updated
Info: NULL
Auf dem Slave müssen Sie zwei Threads sehen. Einer ist der Ein-/Ausgabe-Thread, der
andere ist der SQL-Thread:
Die Replikation einrichten | 381
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 164
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 164
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...omitted...
Seconds_Behind_Master: 0
1. row ***************************
to send event
2. row ***************************
log; waiting for the slave I/O thread to update it
Die gezeigte Beispielausgabe stammt von Servern, die schon lange laufen, weshalb die
Time-Spalten der Ein-/Ausgabe-Threads auf dem Master und dem Slave große Werte zeigen. Der SQL-Thread auf dem Slave war 33 Sekunden lang untätig, was bedeutet, dass 33
Sekunden lang keine Events eingespielt wurden.
Diese Prozesse laufen immer unter dem Benutzer-Account »system user«, die anderen
Spalten zeigen bei Ihnen dagegen andere Werte. Wenn z.B. der SQL-Thread ein Event
auf dem Slave abspielt, zeigt die Info-Spalte, dass die Abfrage ausgeführt wird.
Falls Sie ein bisschen mit der MySQL-Replikation herumspielen wollen,
dann kann Giuseppe Maxias MySQL-Sandbox-Skript (http://sourceforge.
net/projects/mysql-sandbox/) eine »Spielinstallation« aus einer frisch heruntergeladenen MySQL-tar-Datei starten. Es sind nur einige Tastendrücke
und etwa 15 Sekunden nötig, um einen Master und zwei Slaves zum Laufen zu bringen:
$ ./set_replication.pl ~/mysql-5.0.45-linux-x86_64-glibc23.tar.gz
Einen Slave von einem anderen Server aus initialisieren
Die gerade gezeigten Hinweise zur Einrichtung gingen davon aus, dass Sie Master und
Slave nach einer Neuinstallation mit den vorgegebenen Anfangsdaten gestartet haben, so
dass Sie implizit die gleichen Daten auf beiden Servern hatten und die Binärlog-Koordinaten des Masters kannten. Das ist nicht unbedingt der typische Fall. Normalerweise
werden Sie bereits einen Master am Laufen haben und wollen einen neu installierten
Slave mit diesem synchronieren, obwohl dieser nicht die Daten des Masters besitzt.
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
mysql> SHOW PROCESSLIST\G
***************************
Id: 1
User: system user
Host:
db: NULL
Command: Connect
Time: 611116
State: Waiting for master
Info: NULL
***************************
Id: 2
User: system user
Host:
db: NULL
Command: Connect
Time: 33
State: Has read all relay
Info: NULL
Es gibt verschiedene Möglichkeiten, einen Slave von einem anderen Server aus zu initialisieren oder zu »klonen«. Dazu gehört das Kopieren der Daten vom Master, das Klonen
eines Slaves von einem anderen Slave aus und das Starten eines Slaves aus einem aktuellen
Backup. Sie brauchen drei Dinge, um einen Slave mit einem Master zu synchronisieren:
382 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
• Einen Schnappschuss der Daten des Masters zu einem bestimmten Zeitpunkt.
• Die Binärlog-Dateien des Masters von diesem Zeitpunkt bis zu Gegenwart.
Dies sind Methoden, um einen Slave von einem anderen Server zu klonen:
Mit einer kalten Kopie
Eine der einfachsten Methoden, um einen Slave zu starten, besteht darin, den potenziellen Master herunterzufahren und seine Dateien auf den Slave zu kopieren (in
Anhang A erfahren Sie, wie Sie Dateien effizient kopieren). Sie können dann den
Master wieder starten, der dann ein neues Binärlog beginnt, und CHANGE MASTER TO
einsetzen, um den Slave am Anfang dieses Binärlogs zu starten. Der Nachteil dieser
Technik ist offensichtlich: Sie müssen den Master herunterfahren, während Sie die
Kopie anlegen.
Mit einer warmen Kopie
Wenn Sie nur MyISAM-Tabellen benutzen, können Sie die Dateien mit mysqlhotcopy kopieren, während der Server läuft. Näheres erfahren Sie in Kapitel 11.
Mittels mysqldump
Falls Sie nur InnoDB-Tabellen verwenden, können Sie den folgenden Befehl verwenden, um alles vom Master zu speichern, es in den Slave zu laden und die Koordinaten des Slaves auf die entsprechende Position im Binärlog des Masters zu ändern:
$ mysqldump --single-transaction --all-databases --master-data=1
--host=server1 | mysql --host=server2
Die Option --single-transaction veranlasst den Dump, die Daten so zu lesen, wie sie
am Anfang der Transaktion vorlagen. Diese Option kann auch bei anderen transaktionsfähigen Storage-Engines funktionieren, wir haben sie aber nicht getestet. Falls
Sie keine transaktionsfähigen Tabellen verwenden, können Sie die Option --lock-alltables einsetzen, um einen konsistenten Dump aller Tabellen zu bekommen.
Mit einem LVM-Schnappschuss oder einem Backup
Wenn Sie die entsprechenden Binärlog-Koordinaten kennen, können Sie einen
LVM-Schnappschuss vom Master oder einem Backup benutzen, um den Slave zu
initialisieren (falls Sie ein Backup verwenden, dann verlangt diese Methode, dass Sie
alle Binärlogs des Masters seit dem Zeitpunkt des Backups aufbewahrt haben). Stellen Sie einfach das Backup oder den Schnappschuss auf dem Slave wieder her, und
benutzen Sie dann die passenden Binärlog-Koordinaten in CHANGE MASTER TO. Mehr
dazu erfahren Sie in Kapitel 11.
InnoDB Hot Backup, das ebenfalls in Kapitel 11 behandelt wird, ist eine gute
Methode, um einen Slave zu initialisieren, falls Sie nur InnoDB-Tabellen benutzen.
Die Replikation einrichten | 383
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
• Die aktuelle Log-Datei des Masters und den Byte-Offset innerhalb dieses Logs zu
dem exakten Zeitpunkt, zu dem Sie den Schnappschuss erzeugt haben. Wir bezeichnen diese beiden Werte als Log-Datei-Koordinaten, weil sie zusammen eine Binärlog-Position kennzeichnen. Sie können die Log-Datei-Koordinaten des Masters mit
dem Befehl SHOW MASTER STATUS ermitteln.
Von einem anderen Slave
Mit einer der erwähnten Schnappschuss- oder Klontechniken können Sie einen
Slave aus einem anderen klonen. Falls Sie allerdings mysqldump verwenden, funktioniert die Option --master-data nicht.
Der größte Nachteil beim Klonen eines Slaves von einem anderen Slave besteht
darin, dass Sie schlechte Daten klonen, falls Ihr Slave aus irgendeinem Grund nicht
synchron mit dem Master ist.
Benutzen Sie nicht LOAD DATA FROM MASTER oder LOAD TABLE FROM MASTER!
Diese Befehle sind veraltet, langsam und sehr gefährlich. Außerdem funktionieren sie nur mit MyISAM.
Machen Sie sich mit der Technik vertraut, für die Sie sich letztendlich entscheiden, und
dokumentieren Sie sie, oder schreiben Sie sich ein Skript. Sie werden diesen Vorgang mit
hoher Wahrscheinlichkeit mehr als einmal durchführen und müssen dazu in der Lage
sein, ihn zu wiederholen, falls etwas schiefgeht.
Die empfohlene Replikationskonfiguration
Es gibt viele Replikationsparameter, und die meisten von ihnen haben wenigstens eine
gewisse Wirkung auf die Datensicherheit und die Performance. Wir erläutern später,
welche Regeln Sie wann brechen sollten. In diesem Abschnitt zeigen wir eine empfohlene, »sichere« Replikationskonfiguration, die die Gelegenheiten zum Auftreten von Problemen minimiert.
Die wichtigste Einstellung für das Führen eines Binärlogs auf dem Master ist sync_binlog:
sync_binlog=1
Sie veranlasst MySQL, den Inhalt des Binärlogs bei jedem Bestätigen einer Transaktion
auf die Festplatte zu synchronisieren, damit Sie im Falle eines Absturzes keine LogEvents verlieren. Wenn Sie diese Option deaktivieren, hat der Server zwar etwas weniger
Arbeit, aber die Binärlog-Einträge könnten nach einem Serverabsturz beschädigt werden
oder verlorengehen. Auf einem Slave, der nicht als Master auftreten muss, verursacht
diese Option unnötigen Overhead. Sie gilt nur für das Binärlog, nicht für das Relay-Log.
Wir empfehlen außerdem die Verwendung von InnoDB, falls Sie beschädigte Tabellen
nach einem Absturz nicht tolerieren können. MyISAM ist in Ordnung, falls die Beschädigung der Tabelle keine große Sache ist, MyISAM-Tabellen dagegen gelangen wahrscheinlich in einen inkonsistenten Zustand, wenn ein Slave-Server abstürzt. Es kommt mit
großer Sicherheit dazu, dass eine Anweisung unvollständig auf eine oder mehrere Tabel-
384 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Anstatt SHOW MASTER STATUS zu benutzen, um die Binärlog-Koordinaten des Masters
zu erhalten, müssen Sie SHOW SLAVE STATUS einsetzen, damit Sie die Position finden,
an der der Slave auf dem Master ausgeführt wurde, als Sie den Schnappschuss
erzeugt haben.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
len angewandt wurde und die Daten auch dann inkonsistent bleiben, nachdem Sie die
Tabellen repariert haben.
Falls Sie InnoDB benutzen, empfehlen wir Ihnen unbedingt, die folgenden Optionen auf
dem Master einzustellen:
Das sind die Standardeinstellungen in MySQL 5.0. Auf dem Slave sollten Sie die folgenden Konfigurationsoptionen aktivieren:
skip_slave_start
read_only
Die Option skip_slave_start verhindert, dass der Slave nach einem Absturz automatisch
wieder startet, wodurch Sie die Möglichkeit haben, einen Server zu reparieren, falls er
Probleme hat. Wenn der Slave nach einem Absturz automatisch startet und in einem
inkonsistenten Zustand ist, kann er weitere Schäden anrichten, so dass Sie unter Umständen seine Daten wegwerfen und von vorn beginnen müssen. Selbst wenn Sie alle empfohlenen Optionen aktiviert haben, kann ein Slave nach einem Absturz noch kaputtgehen,
weil die Relay-Logs und die Datei master.info nicht absturzsicher sind. Sie werden nicht
einmal auf die Festplatte übertragen, und es gibt keine Konfigurationsoption, mit der
man dieses Verhalten kontrollieren könnte. (Die Google-Patches, auf die wir später noch
kommen, befassen sich mit diesem Problem.)
Die Option read_only hält die meisten Benutzer davon ab, nichttemporäre Tabellen zu
ändern. Ausgenommen sind der Slave-SQL-Thread und Threads mit der Berechtigung
SUPER. Dies ist einer der Gründe dafür, weshalb Sie Ihren normalen Accounts nicht die
Berechtigung SUPER geben sollten (mehr zu Berechtigungen erfahren Sie in Kapitel 12).
Wenn ein Slave weit hinter seinem Master zurückliegt, dann kann der Slave-Ein-/Ausgabe-Thread viele Relay-Logs schreiben. Der Slave-SQL-Thread entfernt sie, sobald er
damit fertig ist, sie abzuspielen (das können Sie mit der Option relay_log_purge ändern).
Falls er aber weit hinterher ist, füllt der Ein-/Ausgabe-Thread möglicherweise die Festplatte. Die Lösung für dieses Problem ist die Konfigurationsvariable relay_log_space_
limit. Übersteigt die Gesamtgröße aller Relay-Logs die Größe dieser Variablen, stoppt
der Ein-/Ausgabe-Thread und wartet darauf, dass der SQL-Thread etwas mehr Festplattenplatz freigibt.
Das klingt zwar alles gut und schön, kann aber insgeheim problematisch sein. Wenn der
Slave noch nicht alle Relay-Logs vom Master geholt hat, sind diese Logs vielleicht für
immer verloren, falls der Master abstürzt. Es ist sicher keine schlechte Idee, wenn Sie den
Slave so viel Platz wie nötig für die Relay-Logs benutzen lassen (es sei denn, Sie haben mit
dem Festplattenplatz etwas Besseres vor). Deswegen haben wir die Einstellung
relay_log_space_limit nicht in unsere empfohlene Konfiguration aufgenommen.
Die Replikation einrichten | 385
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
innodb_flush_logs_at_trx_commit=1 # Uebertraegt alle Log-Schreibvorgaenge
innodb_support_xa=1
# Nur MySQL 5.0 und neuere Versionen
innodb_safe_binlog
# Nur MySQL 4.1, ist in etwa aequivalent
# zu innodb_support_xa
Replikation näher betrachtet
Anweisungsbasierte Replikation
MySQL 5.0 und frühere Versionen unterstützen nur anweisungsbasierte Replikation
(auch als logische Replikation bezeichnet). Das ist in der Datenbankwelt ungewöhnlich.
Bei der anweisungsbasierten Replikation wird die Abfrage aufgezeichnet, die die Daten
auf dem Master geändert hat. Wenn der Slave das Event aus dem Relay-Log liest und es
ausführt, führt er die tatsächliche SQL-Abfrage noch einmal aus, die der Master ausgeführt hat. Dieses Vorgehen bringt sowohl Vor- als auch Nachteile mit sich.
Der offensichtlichste Vorteil besteht darin, dass es relativ einfach zu implementieren ist.
Durch das einfache Aufzeichnen und erneute Abspielen aller Anweisungen, die Daten
ändern, bleibt der Slave theoretisch synchron mit dem Master. Ein weiterer Vorteil der
anweisungsbasierten Replikation besteht darin, dass die Binärlog-Events in der Regel
ausgesprochen kompakt sind. Anweisungsbasierte Replikation benötigt also relativ
wenig Bandbreite – eine Abfrage, die Gigabytes an Daten aktualisiert, belegt möglicherweise nur einige Dutzend Bytes im Binärlog. Darüber hinaus funktioniert das erwähnte
Werkzeug mysqlbinlog mit anweisungsbasiertem Logging am besten.
In der Praxis ist die anweisungsbasierte Replikation jedoch nicht ganz so einfach, wie es
scheinen mag, weil viele Änderungen auf dem Master noch von anderen Faktoren als nur
dem Abfragetext abhängen können. Beispielsweise werden die Anweisungen auf dem
Master und dem Slave zu mehr oder weniger unterschiedlichen Zeiten ausgeführt. Daraus folgt, dass das Binärlog-Format von MySQL mehr als nur den Abfragetext enthält; es
überträgt auch mehrere Bits mit Metadaten, wie etwa den aktuellen Zeitstempel. Außerdem gibt es Anweisungen, die MySQL nicht korrekt replizieren kann, wie etwa Abfragen
mit der Funktion CURRENT_USER( ). Auch gespeicherte Routinen und Trigger werfen bei
der anweisungsbasierten Replikation Probleme auf.
Ein weiteres Problem bei der anweisungsbasierten Replikation besteht darin, dass die
Modifikationen serialisierbar sein müssen. Das erfordert erhebliche Mengen an Spezialcode, Konfigurationseinstellungen und zusätzliche Serverfunktionen, einschließlich der
Next-Key-Locks von InnoDB und automatisch inkrementierender Sperren. Nicht alle
Storage-Engines funktionieren mit anweisungsbasierter Replikation, obwohl es diejenigen tun, die in der offiziellen MySQL-Serverdistribution bis einschließlich MySQL 5.1
enthalten sind.
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Nachdem wir einige der Grundlagen der Replikation erläutert haben, wollen wir sie uns
genauer anschauen. Wir untersuchen, wie Replikation wirklich funktioniert, welche Stärken und Schwächen sie mitbringt und welche erweiterten Konfigurationsoptionen es für
die Replikation gibt.
Im MySQL-Handbuch finden Sie im Kapitel über die Replikation eine vollständige Liste
mit den Nachteilen der anweisungsbasierten Replikation.
386 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Zeilenbasierte Replikation
Zeilenbasiertes Logging ist nicht abwärtskompatibel. Das Dienstprogramm mysqlbinlog, das mit MySQL 5.1 vertrieben wird, kann Binärlogs
lesen, die Events im zeilenbasierten Format aufzeichnen (sie sind nicht
vom Menschen lesbar, der MySQL-Server kann sie allerdings interpretieren). mysqlbinlog-Versionen aus früheren MySQL-Distributionen dagegen
erkennen solche Log-Events nicht und beenden sich mit einer Fehlermeldung, wenn sie sie bemerken.
MySQL kann manche Änderungen mithilfe der zeilenbasierten Replikation effizienter
replizieren, weil der Slave die Abfragen nicht noch einmal wiedergeben muss, mit denen
die Zeilen auf dem Master geändert wurden. Das erneute Abspielen einiger Abfragen
kann sehr teuer sein. Hier sehen Sie z.B. eine Abfrage, die Daten aus einer sehr großen
Tabelle in einer kleineren Tabelle zusammenfasst:
mysql>
->
->
->
INSERT INTO summary_table(col1, col2, sum_col3)
SELECT col1, col2, sum(col3)
FROM enormous_table
GROUP BY col1, col2;
Stellen Sie sich vor, dass es nur drei eindeutige Kombinationen aus col1 und col2 in der
enormous_table-Tabelle gibt. Diese Abfrage scannt viele Zeilen in der Quelltabelle, ergibt
aber nur drei Zeilen in der Zieltabelle. Durch das Replizieren dieses Events muss der
Slave die ganze Arbeit wiederholen, um nur wenige Zeilen zu generieren. Eine zeilenbasierte Replikation ist dagegen auf dem Slave unwahrscheinlich billig und damit viel effizienter.
Andererseits lässt sich das folgende Event mit einer anweisungsbasierten Replikation billiger replizieren:
mysql> UPDATE enormous_table SET col1 = 0;
Die Verwendung der zeilenbasierten Replikation wäre in diesem Fall viel teurer, weil sie
jede Zeile ändert: Jede Zeile müsste in das Binärlog geschrieben werden, wodurch dieses
außerordentlich anwachsen würde. Sowohl durch das Logging als auch durch die Replikation würde die Last auf dem Master stark ansteigen, und das langsamere Logging
würde in der Folge die Nebenläufigkeit herabsetzen.
Replikation näher betrachtet | 387
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
MySQL 5.1 bietet Unterstützung für zeilenbasierte Replikation, bei der die tatsächlichen
Datenänderungen im Binärlog aufgezeichnet werden. Ihre Implementierung ähnelt der
anderer Datenbankprodukte. Dieses Vorgehen bringt einige Vor- und Nachteile mit sich.
Der größte Vorteil besteht darin, dass MySQL jede Anweisung korrekt replizieren kann;
einige Anweisungen werden sogar noch effizienter repliziert. Die wichtigsten Nachteile
sind, dass das Binärlog viel größer werden kann und dass nicht so klar ist, welche Anweisungen die Daten aktualisiert haben, so dass sich das Binärlog nicht für eine Prüfung mit
mysqlbinlog eignet.
Mit einem Binärlog, das Events im zeilenbasierten Format enthält, ist eine punktgenaue
Wiederherstellung schwieriger zu realisieren, aber nicht unmöglich. Ein Log-Server kann
dabei helfen – mehr dazu später.
Theoretisch löst die zeilenbasierte Replikation verschiedene Probleme, auf die wir später
noch kommen. In der Praxis setzen jedoch die meisten Leute, von denen wir wissen, dass
sie MySQL 5.1 im täglichen Betrieb benutzen, weiterhin auf die anweisungsbasierte
Replikation. Es ist deshalb noch zu früh, etwas Abschließendes über die zeilenbasierte
Replikation zu sagen.
Replikationsdateien
Schauen wir uns einige der Dateien an, die bei der Replikation verwendet werden. Sie
kennen bereits das Binärlog und das Relay-Log. Es gibt aber noch mehr Dateien. Wo
MySQL sie ablegt, hängt hauptsächlich von Ihren Konfigurationseinstellungen ab. Üblicherweise legen unterschiedliche MySQL-Versionen sie in unterschiedliche Verzeichnisse. Sie finden sie entweder im Datenverzeichnis oder in dem Verzeichnis, das die .pidDatei des Servers enthält (auf Unix-artigen Systemen wahrscheinlich /var/run/mysqld/).
Hier sind sie:
mysql-bin.index
Ein Server, bei dem das Binär-Logging aktiviert ist, besitzt auch eine Datei, die
genauso heißt wie die Binärlogs, allerdings mit dem Suffix .index. Diese Datei verfolgt die Binärlog-Dateien, die auf der Festplatte existieren. Es handelt sich nicht um
einen Index im Sinne eines Tabellenindex. Stattdessen enthält jede Zeile in der Datei
den Dateinamen einer Binärlog-Datei.
Vielleicht glauben Sie jetzt, dass diese Datei redundant ist und gelöscht werden
kann (schließlich könnte MySQL einfach auf der Festplatte nachschauen, um seine
Dateien zu finden), das sollten Sie aber unterlassen. MySQL verlässt sich auf diese
Indexdatei und kann eine Binärlog-Datei nicht erkennen, wenn sie hier nicht
erwähnt wird.
mysql-relay-bin.index
Diese Datei dient dem gleichen Zweck wie die Binärlog-Indexdatei, allerdings für
die Relay-Logs.
master.info
Diese Datei enthält die Informationen, die ein Slave-Server benötigt, um eine Verbindung zu seinem Master herzustellen. Das Format ist einfacher Text (ein Wert pro
Zeile) und kann zwischen den MySQL-Versionen variieren. Löschen Sie diese Datei
388 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Da kein Format für alle Situationen perfekt geeignet ist, wechselt MySQL 5.1 dynamisch
zwischen anwendungsbasierter und zeilenbasierter Replikation. Standardmäßig verwendet es die anwendungsbasierte Replikation. Wenn es allerdings ein Event bemerkt, das
mit einer Anweisung nicht korrekt repliziert werden kann, geht es zur zeilenbasierten
Replikation über. Sie können das Format bei Bedarf auch steuern, indem Sie die Sitzungsvariable binlog_format einstellen.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Diese Dateien bilden eine ziemlich plumpe Methode, den Replikations- und LoggingZustand von MySQL aufzuzeichnen. Leider werden sie nicht synchron geschrieben. Falls
also bei Ihrem Server der Strom ausfällt und die Dateien noch nicht auf die Festplatte
übertragen waren, könnten sie nach einem Neustart fehlerhaft sein.
Standardmäßig tragen die Binärlogs den Hostnamen des Servers mit einem zusätzlichen
numerischen Suffix, allerdings ist es besser, ihnen in my.cnf explizit einen Namen zu
geben:
log_bin
# Nicht so, sonst werden die Dateien mit dem Hostnamen benannt
log_bin = mysql-bin # Das ist sicher
Das ist wichtig, weil sonst die Replikation fehlschlagen könnte, wenn sich der Hostname
des Servers ändert. Wir empfehlen darüber hinaus, nicht den Hostnamen für die Benennung zu verwenden – klopfen Sie also die Vorgaben nicht auch noch fest. Legen Sie stattdessen einen Namen für Ihre Binärlogs fest, und benutzen Sie ihn allgemein. Dadurch
wird es viel einfacher, die Datei eines Servers auf eine andere Maschine zu verschieben
und das Failover zu automatisieren.
Sie sollten auch die Relay-Logs (die standardmäßig ebenfalls nach dem Hostnamen des
Servers benannt werden) und die entsprechenden .index-Dateien explizit mit Namen versehen. Hier sind unsere empfohlenen my.cnf-Einstellungen für all diese Optionen:
log_bin
log_bin_index
relay_log
relay_log_index
=
=
=
=
mysql-bin
mysql-bin.index
mysql-relay-bin
mysql-relay-bin.index
Die .index-Dateien erben ihre Namen eigentlich von den Log-Dateien, allerdings schadet
es nichts, wenn man sie explizit benennt.
Die .index-Dateien arbeiten auch mit einer anderen Einstellung zusammen, nämlich
expire_logs_days, die angibt, wie MySQL abgelaufene Binärlogs aufräumen soll. Wenn
die mysql-bin.index-Dateien Dateien erwähnen, die es auf der Festplatte gar nicht gibt,
funktioniert die automatische Reinigung nicht, ja, nicht einmal die Anweisung PURGE
MASTER LOGS funktioniert. Die Lösung für dieses Problem besteht im Allgemeinen darin,
die Binärlogs vom MySQL-Server verwalten zu lassen, damit dieser nicht durcheinanderkommt.
Sie müssen explizit eine Log-Reinigungsstrategie implementieren, entweder mit
expire_logs_days oder auf andere Weise, da MySQL ansonsten die Festplatte mit BinärReplikation näher betrachtet | 389
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
nicht, da Ihr Slave sonst nicht weiß, wie er sich nach einem Neustart mit dem Master verbinden soll. Diese Datei enthält das Passwort des Replikationsbenutzers im
Klartext, so dass Sie ihre Berechtigungen einschränken müssen.
relay-log.info
Diese Datei enthält die aktuellen Binärlog- und Relay-Log-Koordinaten des Slaves
(d.h. die Position des Slaves auf dem Master). Löschen Sie sie nicht, da der Slave
sonst nach einem Neustart vergisst, woher er repliziert hat, und möglicherweise versucht, Anweisungen noch einmal abzuspielen, die er bereits ausgeführt hat.
logs füllt. Denken Sie in diesem Zusammenhang gleich über Ihre Backup-Regelungen
nach. Mehr über das Binärlog erfahren Sie in »Das Binärlogformat« auf Seite 532.
Replikations-Events an andere Slaves senden
Master
Slave
Slave
Ein/AusgabeThread
Lesen
Datenänderungen
Mit log_slave_
SQL-Thread updates
Lesen
Lesen
Schreiben
Binärlog
Ein/AusgabeThread
Wiederabspielen
RelayLog
BinaryLog
SQL-Thread
Lesen
Wiederabspielen
RelayLog
Abbildung 8-2: Ein Replikations-Event an weitere Slaves übergeben
In diesem Szenario sorgt eine Änderung auf dem Master dafür, dass ein Event in sein
Binärlog geschrieben wird. Der erste Slave holt sich das Event und führt es aus. An dieser
Stelle wäre das Leben des Events normalerweise vorbei. Da aber log_slave_updates aktiviert ist, schreibt der Slave das Event stattdessen in sein eigenes Binärlog. Jetzt kann der
zweite Slave das Event in sein Relay-Log übertragen und ausführen. Diese Konfiguration
sorgt also dafür, dass Änderungen auf dem ursprünglichen Master an Slaves weiterverteilt werden können, die nicht direkt an den Master angeschlossen sind. Wir setzen
log_slave_updates immer, weil Sie dadurch einen Slave anschließen können, ohne den
Server neu starten zu müssen.
Wenn der erste Slave ein Binärlog-Event vom Master in sein eigenes Binärlog schreibt,
befindet sich das Event mit hoher Wahrscheinlichkeit an einer anderen Position als auf
dem Master – d.h., es könnte in einer anderen Log-Datei stehen oder an einer anderen
numerischen Position innerhalb der Log-Datei. Sie dürfen also nicht davon ausgehen,
dass alle Server, die sich an der gleichen logischen Stelle in der Replikation befinden, die
gleichen Log-Koordinaten aufweisen. Wie wir später sehen werden, wird dadurch die
Erledigung mancher Aufgaben verkompliziert, etwa das Wechseln der Slaves zu einem
anderen Master oder das Ankündigen eines Slaves als Master.
390 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Mit der Option log_slave_updates können Sie einen Slave als Master für andere Slaves
verwenden. Sie weist MySQL an, die Events, die der Slave-SQL-Thread ausführt, in sein
eigenes Binärlog zu schreiben, das andere Slaves sich dann holen und ausführen können.
Abbildung 8-2 verdeutlicht das.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Falls Sie Probleme damit haben, die Replikation in Gang zu bekommen,
dann sollten Sie als eines der ersten Dinge die Server-ID überprüfen. Es
reicht nicht, nur die @@server_id-Variable zu untersuchen. Diese besitzt
einen Vorgabewert, allerdings funktioniert die Replikation nur, wenn dieser Vorgabewert ausdrücklich gesetzt ist, entweder in my.cnf oder über
einen SET-Befehl. Wenn Sie einen SET-Befehl verwenden, dann denken Sie
daran, auch die Konfigurationsdatei zu aktualisieren, da Ihre Einstellungen sonst einen Serverneustart nicht überleben.
Replikationsfilter
Die Möglichkeiten zur Replikationsfilterung erlauben es Ihnen, nur einen Teil der Serverdaten zu replizieren. Es gibt zwei Arten von Replikationsfiltern: solche, die Events aus
dem Binärlog auf dem Master filtern, und solche, die Events filtern, die aus dem RelayLog auf dem Slave kommen. Abbildung 8-3 illustriert die beiden Arten.
Master
Slave
Ein/AusgabeThread
SQL-Thread
Lesen
binlog_do_db
binlog_ignore_db
Wiederabspielen
Schreiben Lesen
Bin rlog
RelayLog
replicate_do_db
replicate_do_table
replicate_ignore_db
replicate_ignore_table
replicate_rewrite_db
replicate_wild_do_table
replicate_wild_ignore_table
Abbildung 8-3: Möglichkeiten zur Replikationsfilterung
Replikation näher betrachtet | 391
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Falls Sie nicht sorgfältig darauf geachtet haben, jedem Server eine eindeutige Server-ID zu
geben, könnte die Konfiguration eines Slaves auf diese Weise zu schleichenden Fehlern
führen oder sogar dafür sorgen, dass sich die Replikation beschwert und stoppt. Eine der
am häufigsten auftretenden Fragen in Bezug auf die Konfiguration der Replikation lautet,
weshalb man die Server-ID angeben muss. Müsste MySQL nicht in der Lage sein, Anweisungen zu replizieren, ohne zu wissen, woher sie stammen? Wieso kümmert sich MySQL
darum, ob die Server-ID global eindeutig ist? Die Antwort auf diese Frage ist darin zu
suchen, wie MySQL eine Endlosschleife bei der Replikation verhindert. Wenn der SlaveSQL-Thread das Relay-Log liest, dann verwirft er alle Events, deren Server-ID seiner eigenen entspricht. Dadurch werden Endlosschleifen bei der Replikation unterbrochen. Das
Verhindern von Endlosschleifen ist für einige der nützlichsten Replikationstopologien
wichtig, etwa für die Master-Master-Replikation.
Die Optionen zur Filterung des Binärlogs heißen binlog_do_db und binlog_ignore_db.
Normalerweise sollten Sie sie nicht aktivieren, wie wir gleich erklären.
Sie müssen vor allen Dingen verstehen, dass die Optionen *_do_db und *_ignore_db
sowohl auf dem Master als auch auf dem Slave nicht so funktionieren, wie Sie es vielleicht erwarten. Vermutlich glauben Sie, dass die Optionen auf der Datenbank des angegebenen Objekts filtern, dabei filtern sie tatsächlich auf der aktuellen Standarddatenbank.
Das heißt, wenn Sie die Anweisungen
mysql> USE test;
mysql> DELETE FROM sakila.film;
auf dem Master ausführen, filtern die Parameter *_do_db und *_ignore_db die DELETEAnweisung auf test, nicht auf sakila. Normalerweise ist das nicht das, was Sie wollen,
und kann dazu führen, dass die falschen Anweisungen repliziert oder ignoriert werden.
Es gibt Anwendungen für die Parameter *_do_db und *_ignore_db, allerdings sind diese
begrenzt und selten, und Sie sollten sie sehr vorsichtig einsetzen. Wenn Sie diese Parameter verwenden, kann es leicht vorkommen, dass die Replikation in eine Schieflage gerät.
Die Optionen binlog_do_db und binlog_ignore_db haben nicht nur das
Potenzial, die Replikation zu stören, sondern machen es auch noch
unmöglich, eine punktgenaue Wiederherstellung aus einem Backup durchzuführen. Sie sollten sie in den meisten Situationen nicht verwenden. Wir
zeigen Ihnen weiter hinten in diesem Kapitel einige sichere Methoden, die
Replikation mit Blackhole-Tabellen zu filtern.
Mit Replikationsfiltern möchte man normalerweise verhindern, dass GRANT- und REVOKEAnweisungen auf Slaves repliziert werden.5 Oft kommt es vor, dass ein Administrator
einem Benutzer mit GRANT bestimmte Schreibberechtigungen auf dem Master gewährt hat
und dann feststellt, dass diese auf den Slave weiterverbreitet wurden, wo der Benutzer
eigentlich keine Daten ändern dürfte. Die folgenden Replikationsoptionen auf dem Slave
verhindern das:
replicate_ignore_table=mysql.columns_priv
replicate_ignore_table=mysql.db
replicate_ignore_table=mysql.host
replicate_ignore_table=mysql.procs_priv
replicate_ignore_table=mysql.tables_priv
replicate_ignore_table=mysql.user
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Auf dem Slave filtern die replicate_*-Optionen Events, während der Slave-SQL-Thread
sie aus dem Relay-Log liest. Sie können eine oder mehrere Datenbanken replizieren oder
ignorieren, eine Datenbank in eine andere Datenbank umschreiben und Tabellen auf
Basis einer LIKE-Mustervergleichssyntax replizieren oder ignorieren.
5 Eine bessere Möglichkeit, die Berechtigungen auf Slaves zu beschränken, besteht darin, read_only zu benutzen
und auf dem Master und den Slaves die gleichen Berechtigungen einzusetzen.
392 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Vielleicht haben Sie den Tipp erhalten, einfach alle Tabellen in der mysql-Datenbank mit
einer solchen Regel auszufiltern:
replicate_wild_ignore_table=mysql.%
Die Filteroptionen sind im MySQL-Handbuch gut dokumentiert, weshalb wir die Einzelheiten hier nicht wiederholen wollen.
Replikationstopologien
Sie können die MySQL-Replikation für fast jede Konfiguration aus Mastern und Slaves
einrichten. Als Einschränkung gilt nur, dass eine Instanz eines MySQL-Slaves nur einen
Master haben darf. Es sind viele komplexe Topologien möglich, doch selbst die einfachen können sehr flexibel sein. Eine einzige Topologie kann viele unterschiedliche
Anwendungszwecke haben. Behalten Sie dies im Hinterkopf, wenn Sie unsere Beschreibungen lesen, weil wir nur die einfachen Anwendungen beschreiben. Die Vielfalt der
Möglichkeiten könnte leicht ein ganzes Buch füllen.
Wir haben bereits gesehen, wie man einen Master mit einem einzigen Slave einrichtet. In
diesem Abschnitt schauen wir uns weitere gebräuchliche Topologien an und diskutieren
deren Stärken und Beschränkungen. Merken Sie sich diese Grundregeln:
• Eine MySQL-Slave-Instanz kann nur einen Master haben.
• Jeder Slave muss eine eindeutige Server-ID besitzen.
• Ein Master kann viele Slaves haben (bzw. ein Slave kann entsprechend viele
Geschwister aufweisen).
• Ein Slave kann Änderungen von seinem Master weiterverbreiten und der Master
anderer Slaves sein, falls Sie log_slave_updates aktivieren.
Ein Master und mehrere Slaves
Neben der bereits erwähnten, zwei Server umfassenden Master-Slave-Anordnung ist dies
die einfachste Replikationstopologie. Sie ist im Prinzip genauso einfach wie die Grundanordnung, weil die Slaves überhaupt nichts miteinander zu tun haben; sie sind jeweils nur
mit dem Master verbunden. Abbildung 8-4 zeigt dieses Arrangement.
Replikationstopologien | 393
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Sicher, damit wird verhindert, dass GRANT-Anweisungen repliziert werden, allerdings werden jetzt auch keine Events und Routinen repliziert. Solche unvorhergesehenen Folgen
sind der Grund dafür, weshalb wir gesagt haben, dass Sie mit Filtern vorsichtig sein müssen. Es ist sicher besser, wenn Sie verhindern, dass bestimmte Anweisungen repliziert
werden. Üblicherweise erreichen Sie das mit SET SQL_LOG_BIN=0, obwohl auch dieses Vorgehen Gefahren birgt. Im Allgemeinen sollten Sie Replikationsfilter sehr vorsichtig einsetzen und auch nur, wenn Sie sie wirklich brauchen, weil es leicht ist, mit ihnen die
anweisungsbasierte Replikation zu stören. (Zeilenbasierte Replikation könnte einige dieser Probleme lösen, allerdings ist das noch nicht vollständig bewiesen.)
Master
Slave
Slave
Abbildung 8-4: Ein Master mit mehreren Slaves
Diese Konfiguration ist am sinnvollsten, wenn Sie wenige Schreib- und viele Leseoperationen haben. Sie können die Lesevorgänge über eine beliebige Anzahl Slave-Server verteilen, und zwar bis zu dem Punkt, an dem die Slaves zu viel Last auf den Master legen
oder die Netzwerkbandbreite vom Master zu den Slaves zu einem Problem wird. Sie können viele Slaves auf einmal einrichten oder sie bei Bedarf hinzufügen. Dabei gehen Sie
genauso vor, wie wir es bereits gezeigt haben.
Obwohl diese Topologie sehr einfach ist, genügt sie vielen Anforderungen. Hier sind nur
einige Anregungen:
• Verwenden Sie unterschiedliche Slaves für unterschiedliche Rollen (z.B. für unterschiedliche Indizes oder Storage-Engines).
• Richten Sie einen der Slaves als Reserve-Master ein, zu dem es keinen weiteren Verkehr als die Replikation gibt.
• Setzen Sie einen der Slaves als Notfallreserve in ein entferntes Rechenzentrum.
• Richten Sie einen oder mehrere Slaves mit Zeitverzögerung ein, so dass er als Notfallreserve dienen kann.
• Nutzen Sie einen der Slaves für Backups, zu Trainingszwecken oder als Entwicklungs- oder Staging-Server.
Einer der Gründe für die Beliebtheit dieser Topologie besteht darin, dass sie viele der
Komplexitäten vermeidet, die andere Konfigurationen mit sich bringen. Hier ein Beispiel:
Es ist leicht, einen Slave in Bezug auf die Binärlog-Positionen auf dem Master mit einem
anderen Slave zu vergleichen, weil sie gleich sind. Mit anderen Worten: Wenn Sie alle
Slaves an der gleichen logischen Position in der Replikation stoppen, dann lesen sie alle
von der gleichen physischen Stelle im Log des Masters. Das ist eine hübsche Eigenschaft,
die viele administrative Aufgaben vereinfacht, wie etwa die Beförderung eines Slaves zum
Master.
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Slave
Diese Eigenschaft gilt allerdings nur zwischen »verschwisterten« Slaves. Zwischen Servern, die sich nicht in einer direkten Master-Slave- oder Geschwisterbeziehung befinden,
lassen sich Log-Positionen nicht so einfach vergleichen. Viele der Topologien, die wir
394 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
später vorstellen, wie etwa die Baumreplikation oder Distribution-Master, erlauben es
nicht so einfach festzustellen, von welcher Stelle in der logischen Abfolge der Events ein
Slave tatsächlich repliziert.
Die Master-Master-Replikation (auch als Dual-Master- oder bidirektionale Replikation
bezeichnet) umfasst zwei Server, die jeweils als Master und als Slave des anderen Servers
konfiguriert sind – mit anderen Worten: ein Paar aus Co-Mastern. Abbildung 8-5 verdeutlicht dies.
Master
Master
Abbildung 8-5: Master-Master-Replikation
MySQL unterstützt keine Multimaster-Replikation
Wir verwenden den Begriff Multimaster-Replikation ganz speziell, um einen Slave mit
mehr als einem Master zu beschreiben. Unabhängig davon, was man Ihnen erzählt hat,
unterstützt MySQL (im Gegensatz zu einigen anderen Datenbankservern) momentan die
Konfiguration, die in Abbildung 8-6 gezeigt wird, nicht. Wir zeigen Ihnen jedoch weiter
hinten in diesem Kapitel einige Möglichkeiten, die Multimaster-Replikation zu emulieren.
Leider benutzen viele Leute diesen Begriff gelegentlich, um eine Anordnung zu beschreiben, bei der es mehr als einen Master in der gesamten Replikationstopologie gibt, wie etwa
die »Baum«-Topologie, auf die wir noch kommen. Andere Leute beschreiben damit die
sogenannte Master-Master-Replikation, bei der die Server gegenseitig als Master und Slave
auftreten.
Diese Probleme mit der Terminologie verursachen viel Verwirrung und sogar Streit. Deshalb ist es unserer Meinung nach am besten, sorgfältig mit den Namen umzugehen. Stellen
Sie sich vor, wie schwierig es wird, sich zu verständigen, wenn MySQL auf einmal Unterstützung für einen Slave mit zwei Mastern bietet! Welchen Begriff würden Sie dafür benutzen, wenn Sie »Multimaster-Replikation« nicht reserviert haben?
Es gibt Anwendungen für eine Master-Master-Replikation im Aktiv-Aktiv-Modus, allerdings sind diese üblicherweise sehr speziell. Ein möglicher Anwendungszweck ist für geografisch getrennte Büros, bei denen jedes Büro seine eigene lokal schreibbare Kopie der
Daten benötigt.
Replikationstopologien | 395
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Master-Master im Aktiv-Aktiv-Modus
Master
Master
Abbildung 8-6: MySQL unterstützt keine Multimaster-Replikation.
Das größte Problem mit einer solchen Konfiguration besteht darin, wie mit widersprüchlichen Änderungen umgegangen wird. Die Liste der möglichen Probleme, die dadurch
verursacht werden, dass man zwei schreibbare Co-Master hat, ist sehr lang. Probleme
treten normalerweise auf, wenn eine Abfrage gleichzeitig auf beiden Mastern die gleiche
Zeile ändert oder zum gleichen Zeitpunkt auf beiden Servern etwas in eine Tabelle mit
einer AUTO_INCREMENT-Spalte einfügt.
Seit MySQL 5.0 gibt es einige Replikationsfunktionen, die diese Art der Replikation ein
wenig sicherer machen: die Einstellungen auto_increment_increment und auto_increment_
offset. Diese Einstellungen erlauben es Servern, automatisch nicht-widersprüchliche
Werte für INSERT-Abfragen zu generieren. Es ist aber immer noch gefährlich, auf beiden
Servern Schreiboperationen zu erlauben. Updates, die auf den beiden Maschinen in
unterschiedlicher Reihenfolge geschehen, können weiterhin dafür sorgen, dass die Daten
stillschweigend in Konflikt geraten. Stellen Sie sich z.B. vor, dass Sie eine Tabelle mit
einer Spalte und einer Zeile haben, die den Wert 1 enthält. Nehmen Sie nun an, dass
diese beiden Anweisungen gleichzeitig ausgeführt werden:
• Auf dem ersten Co-Master:
mysql> UPDATE tbl SET col=col + 1;
• Auf dem zweiten:
mysql> UPDATE tbl SET col=col * 2;
Das Ergebnis? Ein Server hat den Wert 4, der andere den Wert 3. Und dennoch gibt es
keine Replikationsfehler.
Dass Daten durcheinanderkommen, ist nur der Anfang. Was passiert, wenn die normale
Replikation mit einem Fehler stoppt, die Anwendung aber weiter auf beide Server
schreibt? Sie können nicht einfach einen der Server von dem anderen klonen, weil beide
von ihnen Änderungen enthalten, die Sie auf den anderen kopieren müssen. Es ist vermutlich ziemlich schwer, dieses Problem zu lösen.
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Slave
Wenn Sie eine Master-Master-Aktiv-Aktiv-Konfiguration sorgfältig einrichten, möglicherweise mit gut partitionierten Daten und Berechtigungen, können Sie einige dieser
396 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Probleme vermeiden.6 Es ist jedoch schwierig, das wirklich gut hinzubekommen, und
normalerweise gibt es eine bessere Methode, das gewünschte Ziel zu erreichen.
Master-Master im Aktiv-Passiv-Modus
Es gibt eine Variante der Master-Master-Replikation, mit der man die gerade besprochenen Nachteile vermeidet und die in der Tat eine sehr leistungsfähige Methode darstellt,
um fehlertolerante und hochverfügbare Systeme zu entwickeln. Der wesentliche Unterschied besteht darin, dass einer der Server ein schreibgeschützter »passiver« Server ist,
wie Abbildung 8-7 zeigt.
Aktiv
Passiv
Abbildung 8-7: Master-Master-Replikation im Aktiv-Passiv-Modus
Mit dieser Konfiguration können Sie die aktiven und passiven Serverrollen leicht wechseln, da die Konfigurationen der Server symmetrisch sind. Dadurch werden Failover und
Failback erleichtert. Außerdem können Sie Wartungsarbeiten, Tabellenoptimierungen,
Betriebssystem-(oder Anwendungs- oder Hardware-)Upgrades und andere Aufgaben
ohne Ausfallzeiten durchführen.
So wird z.B. durch das Ausführen einer ALTER TABLE-Anweisung die gesamte Tabelle
gesperrt, d.h., Lese- und Schreiboperationen werden blockiert. Dieser Zustand kann
lange anhalten und den Service unterbrechen. Die Master-Master-Konfiguration erlaubt
es Ihnen jedoch, die Slave-Threads auf dem aktiven Server zu stoppen, so dass keine
Aktualisierungen vom passiven Server mehr verarbeitet werden. Ferner können Sie bei
einer Master-Master-Konfiguration die Tabelle auf dem passiven Server verändern, die
Rollen vertauschen und den Slave-Prozess auf dem vormals aktiven Server neu starten.7
Dieser Server liest dann sein Relay-Log und führt die gleiche ALTER TABLE-Anweisung aus.
Auch dies kann lange dauern, was aber egal ist, da der Server aktuell keine Abfragen
bedient.
6 Einige, aber nicht alle – wir können den Advocatus Diaboli spielen und Ihnen in praktisch jeder vorstellbaren
Anordnung Schwachstellen zeigen.
7 Sie können das Binär-Logging zeitweise mit SET SQL_LOG_BIN=0 deaktivieren, anstatt die Replikation zu stoppen. Manche Befehle, wie etwa OPTIMIZE TABLE, unterstützen auch die Optionen LOCAL oder NO_WRITE_TO_BINLOG,
die das Logging verhindern.
Replikationstopologien | 397
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Im Allgemeinen bringt es mehr Ärger, als dass es nützt, wenn man Schreiboperationen
auf beiden Servern zulässt. Eine Aktiv-Passiv-Konfiguration dagegen ist ganz sinnvoll,
wie Sie im nächsten Abschnitt sehen werden.
Schauen wir uns an, wie man ein Master-Master-Paar konfiguriert. Führen Sie diese
Schritte auf beiden Servern aus, damit die Konfigurationen symmetrisch bleiben:
1. Aktivieren Sie das Binär-Logging, wählen Sie eindeutige Server-IDs, und legen Sie
Accounts für die Replikation an.
2. Aktivieren Sie das Logging von Slave-Updates. Das ist entscheidend für Failover und
Failback, wie Sie später sehen werden.
3. Konfigurieren Sie optional den passiven Server als schreibgeschützt, um Änderun-
gen zu verhindern, die mit Änderungen auf dem aktiven Server in Konflikt geraten
könnten.
4. Stellen Sie sicher, dass die Server exakt die gleichen Daten enthalten.
5. Starten Sie die MySQL-Instanz auf allen Servern.
6. Konfigurieren Sie die einzelnen Server als Slave des jeweils anderen Servers, wobei
Sie mit dem neu angelegten Binärlog beginnen.
Wir wollen nun verfolgen, was geschieht, wenn es eine Änderung auf dem aktiven Server
gibt. Die Änderung wird in sein Binärlog geschrieben und gelangt durch die Replikation
in das Relay-Log des passiven Servers. Der passive Server führt die Abfrage aus und
schreibt das Event in sein eigenes Binärlog, da Sie log_slave_updates eingeschaltet haben.
Der aktive Server holt dann die gleiche Änderung über die Replikation in sein eigenes
Relay-Log, ignoriert sie jedoch, weil die Server-ID des Events seiner eigenen entspricht.
In »Die Master wechseln« auf Seite 415 erfahren Sie, wie Sie die Rollen vertauschen.
Das Einrichten einer Aktiv-Passiv-Master-Master-Topologie ist ein bisschen wie das
Anlegen eines Hot-Spare, nur dass Sie hier das »Spare« verwenden können, um die Performance anzukurbeln. Sie können es für Leseabfragen, Backups, »Offline«-Wartungsarbeiten, Upgrades usw. einsetzen – Dinge, die mit einem echten Hot-Spare nicht möglich
sind. Allerdings erzielen Sie hiermit keine bessere Schreib-Performance als mit einem einzelnen Server (mehr dazu später).
Wenn wir weitere Szenarien und Anwendungen für die Replikation vorstellen, kommen
wir auf diese Konfiguration zurück. Es ist eine sehr wichtige und verbreitete Replikationstopologie.
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Mit der Aktiv-Passiv-Master-Master-Topologie umgehen Sie viele weitere Probleme und
Beschränkungen in MySQL. Sie können sich beim Einrichten und Verwalten eines solchen Systems vom MySQL-Master-Master Replication Manager (http://code.google.com/
p/mysql-master-master/) unterstützen lassen. Dieses Programm automatisiert viele knifflige Aufgaben, wie etwa das Wiederherstellen und Neusynchronisieren der Replikation,
das Einrichten neuer Slaves usw.
Master-Master mit Slaves
Bei einer verwandten Konfiguration werden jedem Co-Master ein oder mehrere Slaves
hinzugefügt (siehe Abbildung 8-8).
398 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Master
Master
Slave
Abbildung 8-8: Master-Master-Replikation mit Slaves
Vorteilhaft an dieser Konfiguration ist die zusätzliche Redundanz. In einer geografisch
verteilten Replikationstopologie vermeidet sie die eine Schwachstelle jedes Standorts.
Wir üblich können Sie außerdem leseintensive Abfragen auf die Slaves abschieben.
Wenn Sie lokal für ein schnelles Failover eine Master-Master-Topologie einsetzen, kann
Ihnen diese Konfiguration dennoch helfen. Es ist möglich, aber auch etwas komplexer,
einen der Slaves zu befördern, um einen ausgefallenen Master zu ersetzen. Das gilt auch
für das Verschieben eines der Slaves derart, dass er auf einen anderen Master verweist.
Die zusätzliche Komplexität ist ein wichtiger Gesichtspunkt.
Ring
Die Dual-Master-Konfiguration ist in Wirklichkeit ein Sonderfall8 der Ring-Replikationskonfiguration, die in Abbildung 8-9 zu sehen ist. Ein Ring umfasst drei oder mehr Master. Jeder Server ist ein Slave des vorhergehenden Servers im Ring und ein Master des
nachfolgenden Servers. Diese Topologie wird auch als kreisförmige Replikation bezeichnet.
Master
Master
Master
Abbildung 8-9: Eine Replikationsringtopologie
8 Ein etwas vernünftigerer Sonderfall, wie wir hinzufügen wollen.
Replikationstopologien | 399
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Slave
Sie können einige der Risiken einer ringförmigen Replikationsanordnung mildern, indem
Sie Slaves hinzufügen, die an jedem Standort für Redundanz sorgen (siehe Abbildung 8-10).
Das schützt allerdings nur vor dem Risiko eines Serverausfalls. Ein Stromausfall oder ein
anderes Problem, das die Verbindung zwischen den Standorten beeinflusst, unterbricht
weiterhin den gesamten Ring.
Slave
Slave
Master
Master
Master
Slave
Abbildung 8-10: Ein Replikationsring mit Slaves an jedem Standort
Master, Distribution-Master und Slaves
Wir haben erwähnt, dass Slaves eine ziemliche Last auf einen Master laden können,
wenn es genügend von ihnen gibt. Jeder Slave erzeugt auf dem Master einen neuen
Thread, der den speziellen binlog dump-Befehl ausführt. Dieser Befehl liest die Daten aus
dem Binärlog und schickt sie an den Slave. Die Arbeit wird für jeden Slave-Thread wiederholt; die Threads teilen sich die Ressourcen nicht, die für einen Binlog-Dump benötigt
werden.
400 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Ringe verfügen nicht über die wichtigsten Vorteile einer Master-Master-Anordnung, wie
etwa symmetrische Konfiguration und einfaches Failover. Darüber hinaus sind sie vollständig davon abhängig, dass jeder Knoten im Ring verfügbar ist, wodurch sich die
Wahrscheinlichkeit stark erhöht, dass das gesamte System ausfällt. Und falls Sie einen
der Knoten aus dem Ring entfernen, können alle Replikations-Events, die von diesem
Knoten stammten, in eine Endlosschleife gelangen. Sie kreisen für immer durch die
Topologie, weil der einzige Server, der sie anhand ihrer Server-ID filtern könnte, der Server ist, der sie erzeugt hat. Ringe sind im Allgemeinen eigenwillig und sollten am besten
vermieden werden.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Wenn es viele Slaves und ein besonders großes Binärlog-Event, wie ein riesiges LOAD DATA
INFILE, gibt, kann die Last auf dem Master deutlich ansteigen. Dem Master geht unter
Aus diesem Grund bietet es sich an, die Last vom Server zu nehmen und einen Distribution-Master einzusetzen, wenn Sie viele Slaves benötigen. Ein Distribution-Master ist ein
Slave, dessen einziger Zweck darin besteht, die Binärlogs vom Master zu lesen und anzubieten. Mit dem Distribution-Master können sich viele Slaves verbinden, wodurch der
ursprüngliche Master von der Last abgeschirmt wird. Um zu vermeiden, dass die Abfragen tatsächlich auf dem Distribution-Master ausgeführt werden, sollten Sie seine Tabellen in die Blackhole-Storage-Engine überführen, wie es in Abbildung 8-11 gezeigt ist.
Master
Distribution-Master mit
Blackhole-Storage-Engine
Viele Slaves
Abbildung 8-11: Ein Master, ein Distribution-Master und viele Slaves
Es ist schwer, genau anzugeben, wie viele Slaves ein Master bedienen kann, bevor er
einen Distribution-Master braucht. Als Faustregel gilt: Wenn ein Master mit fast voller
Kapazität läuft, dann sollten Sie ihm nicht mehr als 10 Slaves zuordnen. Gibt es nur eine
geringe Schreibaktivität oder replizieren Sie nur einen Bruchteil der Tabellen, dann kann
der Master wahrscheinlich viel mehr Slaves bedienen. Außerdem müssen Sie sich nicht
auf einen Distribution-Master beschränken. Sie können mehrere verwenden, wenn Sie
auf eine wirklich große Zahl von Slaves replizieren müssen. Sogar eine Pyramide aus Distribution-Mastern wäre möglich.
Der Distribution-Master lässt sich auch für andere Aufgaben benutzen, wie etwa das Filtern und das Umschreiben von Regeln für die Binärlog-Events. Das ist effizienter, als
wenn Sie das Logging, Umschreiben und Filtern auf jedem Slave wiederholen.
Replikationstopologien | 401
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Umständen sogar der Speicher aus, und er stürzt ab, weil alle Slaves gleichzeitig das gleiche riesige Event anfordern. Falls andererseits die Slaves unterschiedliche Binlog-Events
anfordern, die sich nicht mehr im Dateisystem-Cache befinden, werden vermutlich viele
Festplattensuchen verursacht, die sich ebenfalls zuungunsten der Leistung des Servers
auswirken.
Falls Sie auf dem Distribution-Master mit Blackhole-Tabellen arbeiten, kann dieser mehr
Slaves bedienen als üblich. Der Distribution-Master führt die Abfragen aus, die ausgesprochen preiswert sind, weil die Blackhole-Tabellen keine Daten enthalten.
storage_engine = blackhole
Dies beeinflusst nur CREATE TABLE-Anweisungen, die nicht explizit eine Storage-Engine
angeben. Falls Sie eine Anwendung haben, die Sie nicht kontrollieren können, dann ist
diese Topologie eventuell empfindlich. Sie können InnoDB mit der Option skip_innodb
deaktivieren und die Tabellen auf MyISAM zurückgreifen lassen, Sie können jedoch die
Engines MyISAM oder Memory nicht ausschalten.
Der andere wesentliche Nachteil ist die Schwierigkeit, den Master durch einen der (tatsächlichen) Slaves zu ersetzen. Es ist schwierig, einen der Slaves an seine Stelle zu befördern, weil der dazwischenliegende Master dafür sorgt, dass er fast immer andere
Binärlog-Koordinaten besitzt als der ursprüngliche Master.
Baum oder Pyramide?
Falls Sie einen Master auf eine sehr große Anzahl von Slaves replizieren – egal, ob Sie die
Daten geografisch verteilen oder lediglich versuchen, die Lesekapazität zu erhöhen –, kann
es praktischer sein, ein pyramidenförmiges Design zu verwenden (siehe Abbildung 8-12).
Master
Slave
Slave
Slave
Slave
Slave
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Häufig taucht die Frage auf, wie man sicherstellt, dass alle Tabellen auf dem Distribution-Master die Blackhole-Storage-Engine benutzen. Was passiert, wenn jemand auf dem
Master eine neue Tabelle anlegt und eine andere Storage-Engine festlegt? Das Problem
tritt übrigens auch auf, wenn Sie auf einem Slave eine andere Storage-Engine einsetzen
wollen. Normalerweise setzt man die storage_engine-Option des Servers:
Slave
Abbildung 8-12: Eine pyramidenförmige Replikationstopologie
402 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Der Vorteil dieses Aufbaus besteht darin, dass er die Last auf dem Master mildert – genau
wie der Distribution-Master im vorherigen Abschnitt. Nachteilig ist, dass jeder Ausfall in
einer Zwischenebene mehrere Server beeinträchtigt. Wären die Slaves jeweils direkt an
den Master angeschlossen, würde dies nicht geschehen. Je mehr Zwischenebenen Sie
außerdem haben, umso schwieriger und komplizierter wird der Umgang mit Ausfällen.
Die MySQL-Replikation ist so flexibel, dass man oft sogar eigene Lösungen für die
Anforderungen einer Anwendung entwickeln kann. Typischerweise nutzt man eine Kombination aus Filterung, Verteilung und Replikation auf unterschiedliche Storage-Engines.
Sie können natürlich auch »hacken«, also etwa auf und von Servern replizieren, die die
Blackhole-Storage-Engine einsetzen (wie in »Master, Distribution-Master und Slaves« auf
Seite 400 besprochen). Ihr Entwurf kann so ausgeklügelt sein, wie Sie wollen. Die größten Einschränkungen betreffen das, was Sie vernünftigerweise überwachen und administrieren können, sowie die Grenzen Ihrer Ressourcen (Netzwerkbandbreite, CPULeistung usw.).
Selektive Replikation
Um die Lokalitätseigenschaft auszunutzen und Ihren Arbeitssatz für Leseoperationen im
Speicher zu behalten, können Sie auf jeden der vielen Slaves eine kleine Menge Daten
replizieren. Wenn jeder Slave einen Bruchteil der Daten des Masters enthält und Sie Leseoperationen an die Slaves umleiten, nutzen Sie den Speicher auf den einzelnen Slaves viel
besser aus. Jeder Slave übernimmt auch nur einen Bruchteil der Schreiblast des Masters,
so dass der Master viel leistungsfähiger wird, ohne dass die Slaves zurückfallen.
Dieses Szenario ähnelt in gewisser Hinsicht der horizontalen Datenpartitionierung, auf
die wir im nächsten Kapitel ausführlicher eingehen werden, besitzt aber den Vorteil, dass
immer noch ein Server alle Daten vorhält – der Master. Das bedeutet, dass Sie für eine
Schreibabfrage niemals auf mehr als einen Server schauen müssen. Gibt es Leseabfragen,
die Daten benötigen, die nicht alle auf einem einzigen Slave-Server vorliegen, dann haben
Sie die Möglichkeit, diese Leseoperationen auf dem Master ausführen zu lassen. Selbst
wenn Sie nicht alle Leseoperationen auf den Slaves durchführen können, sollten Sie in
der Lage sein, viele von ihnen vom Master abzuziehen.
Am einfachsten geht das, indem Sie die Daten auf verschiedene Datenbanken auf dem
Master aufteilen und dann jede Datenbank auf einen anderen Slave-Server replizieren.
Falls Sie z.B. Daten für jede Abteilung in Ihrem Unternehmen auf einen anderen Slave
replizieren wollen, legen Sie Datenbanken namens sales, marketing, procurement usw. an.
Jeder Slave muss dann eine replicate_wild_do_table-Konfigurationsoption enthalten, die
seine Daten auf die angegebene Datenbank beschränkt. Hier ist die Konfigurationsoption
für die sales-Datenbank:
replicate_wild_do_table = sales.%
Replikationstopologien | 403
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Eigene Replikationslösungen
Funktionen trennen
Viele Anwendungen enthalten einen Mix aus OLTP- (Online Transaction Processing)
und OLAP-(Online Analytical Processing-)Abfragen. OLTP-Abfragen sind meist kurz
und transaktionsfähig. OLAP-Abfragen dagegen sind normalerweise groß und langsam
und verlangen keine absolut aktuellen Daten. Die zwei Arten von Abfragen beanspruchen den Server völlig unterschiedlich. Daher werden sie am besten auf Servern ausgeführt, die verschieden konfiguriert sind und vielleicht sogar unterschiedliche StorageEngines und Hardware verwenden.
Eine gebräuchliche Lösung für dieses Problem besteht darin, die Daten des OLTP-Servers
auf Slaves zu replizieren, die speziell für die OLAP-Last entworfen wurden. Diese Slaves
können eine andere Hardware, andere Konfigurationen, Indizes und/oder Storage-Engines besitzen. Wenn Sie einen Slave für OLAP-Abfragen vorsehen, dann könnten Sie auf
diesem Slave auch eine gewisse Verzögerung bei der Replikation oder eine anderweitig
verminderte Service-Qualität tolerieren. Das bedeutet möglicherweise, dass Sie ihn für
Aufgaben einsetzen, die auf einem nicht speziell zugewiesenen Slave zu einer unakzeptablen Performance führen würden, etwa für das Ausführen sehr lange laufender Abfragen.
Es ist keine spezielle Replikationsanordnung erforderlich. Allerdings erreichen Sie vielleicht deutliche Einsparungen, wenn Sie nicht alle Daten des Masters auf dem Slave
haben. Denken Sie daran: Selbst wenn Sie nur einen kleinen Teil der Daten mit Replikationsfiltern im Relay-Log herausfiltern können, verringern Sie die Ein-/Ausgabe- und
Cache-Aktivität.
Daten archivieren
Sie können Daten auf einem Slave-Server archivieren – d.h., sie auf dem Slave behalten,
aber vom Master entfernen –, indem Sie Löschabfragen auf dem Master ausführen und
dafür sorgen, dass diese Abfragen nicht auf dem Slave ausgeführt werden. Dazu sind zwei
Methoden üblich: Entweder Sie deaktivieren selektiv das Binär-Logging auf dem Master,
oder Sie setzen auf dem Slave replicate_ignore_db-Regeln ein.
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Das Filtern mit einem Distribution-Master ist ebenfalls sinnvoll. Falls Sie z.B. nur einen
Teil eines stark ausgelasteten Servers über ein langsames oder sehr teures Netzwerk replizieren wollen, dann nutzen Sie einfach einen lokalen Distribution-Master mit BlackholeTabellen und Filterregeln. Der Distribution-Master kann Replikationsfilter enthalten, die
unerwünschte Einträge aus seinen Logs entfernen. Auf diese Weise vermeiden Sie gefährliche Loggingeinstellungen auf dem Master, und außerdem müssen Sie nicht alle Logs
über das Netzwerk auf die entfernten Slaves übertragen.
Die erste Methode verlangt das Ausführen von SET SQL_LOG_BIN=0 in dem Prozess, der die
Daten auf dem Master aufräumt. Anschließend werden die Daten aufgeräumt. Auf dem
Slave ist in diesem Fall keine besondere Replikationskonfiguration erforderlich. Und da
die Anweisungen auch nicht in das Binärlog des Masters gelangen, ist diese Methode
404 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
sogar noch ein bisschen effizienter. Der größte Nachteil besteht darin, dass Sie das Binärlog auf dem Master nicht mehr dazu verwenden können, die punktgenaue Wiederherstellung zu überwachen, da es nicht mehr jede Modifikation enthält, die Sie an den Daten
des Masters vorgenommen haben. Außerdem ist für diese Methode die SUPER-Berechtigung nötig.
Das Maakit-Programm mk-archiver unterstützt beide Methoden.
Eine dritte Möglichkeit besteht darin, mit binlog_ignore_db ReplikationsEvents herauszufiltern. Wie wir aber bereits angemerkt haben, halten wir
das in den meisten Situationen für gefährlich.
Slaves für Volltextsuchen einsetzen
Viele Anwendungen verlangen eine Kombination aus Transaktionen und Volltextsuchen.
Allerdings sind nur in MyISAM-Tabellen Fähigkeiten zur Volltextsuche eingebaut, und
MyISAM unterstützt keine Transaktionen. Eine Lösung wäre, einen Slave für Volltextsuchen zu konfigurieren, indem die Storage-Engine für bestimmte Tabellen auf dem Slave
auf MyISAM geändert wird. Sie können Volltextindizes hinzufügen und Volltextsuchabfragen auf dem Slave ausführen. Dadurch werden potenzielle Replikationsprobleme mit
transaktionsfähigen und nichttransaktionsfähigen Storage-Engines in derselben Abfrage
auf dem Master vermieden, und der Master muss nicht noch zusätzlich die Volltextindizes pflegen.
Schreibgeschützte Slaves
In vielen Unternehmen zieht man es vor, die Slaves nur zum Lesen zuzulassen, damit
ungewollte Änderungen nicht die Replikation unterbrechen. Dazu verwendet man die
Konfigurationsvariable read_only. Sie deaktiviert die meisten Schreiboperationen: Ausnahmen bilden die Slave-Prozesse, Benutzer mit der Berechtigung SUPER und temporäre
Tabellen. Diese Lösung ist perfekt, solange Sie nicht normalen Benutzern die Berechtigung SUPER gewähren, was Sie sowieso nie tun sollten.
Replikationstopologien | 405
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Bei der zweiten Technik wird eine bestimmte Datenbank mit USE auf dem Master eingesetzt, bevor die Anweisungen ausgeführt werden, die die Daten aufräumen. Sie können
z.B. eine Datenbank namens purge anlegen und dann in der my.cnf-Datei des Slaves
replicate_ignore_db=purge festlegen. Anschließend starten Sie den Slave neu. Der Slave
ignoriert Anweisungen, die diese Datenbank mit USE benutzen. Dieser Ansatz hat nicht
die Schwächen der ersten Technik, bringt allerdings den (kleinen) Nachteil mit sich, dass
der Slave veranlasst wird, Binärlog-Events zu holen, die er gar nicht braucht. Potenziell
könnte außerdem jemand versehentlich Abfragen in der purge-Datenbank ausführen, die
nicht zum Aufräumen der Daten gedacht sind, was den Slave dazu bringt, gewünschte
Events nicht wieder abzuspielen.
Multimaster-Replikation emulieren
Sie müssen die Binärlog-Koordinaten für die einzelnen Master im Auge behalten. Außerdem sollten Sie sicherstellen, dass der Ein-/Ausgabe-Thread des Slaves nicht mehr Daten
holt, als er in jedem Durchlauf ausführen soll; ansonsten erhöhen Sie unter Umständen
den Netzwerkverkehr deutlich, indem Sie in jedem Zyklus viele Daten holen und verwerfen.
Es gibt für diesen Zweck ein fertiges Skript: http://code.google.com/p/mysql-mmre/.
Sie können die Multimaster-Replikation mithilfe einer Master-Master- (oder Ring-) Replikation und der Blackhole-Storage-Engine mit einem Slave emulieren, wie Abbildung 8-13
zeigt.
Co-Master1
Co-Master2
DB1
DB1
DB2
DB2
DB1
Blackhole-Storage-Engines
DB2
Slave1
Abbildung 8-13: Emulation der Multimaster-Replikation mit zwei Mastern und der Blackhole-StorageEngine
In dieser Konfiguration besitzen die beiden Master jeweils ihre eigenen Daten. Sie enthalten außerdem die Tabellen vom anderen Master, benutzen aber die Blackhole-StorageEngine, um zu vermeiden, dass sie tatsächlich Daten in diesen Tabellen speichern. Ein
Slave ist an einen der Co-Master angeschlossen – es spielt keine Rolle, an welchen. Dieser
Slave verwendet nicht die Blackhole-Storage-Engine, so dass er im Prinzip der Slave beider Master ist.
406 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
MySQL bietet momentan keine Unterstützung für die Multimaster-Replikation (d.h.
einen Slave mit mehr als einem Master). Sie können diese Topologie jedoch emulieren,
indem Sie einen Slave so konfigurieren, dass er abwechselnd auf unterschiedliche Master
verweist. Zum Beispiel verweisen Sie den Slave auf Master A und lassen ihn eine Weile
laufen, richten ihn dann für eine Weile auf Master B und wechseln dann wieder zurück
auf Master A. Wie gut das funktioniert, hängt von Ihren Daten ab sowie davon, wie viel
Arbeit die beiden Master für den einen Slave verursachen. Ist die Last auf Ihren Mastern
relativ leicht und kommen sich ihre Updates nicht ins Gehege, dann könnte das ganz gut
funktionieren.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Eigentlich ist dafür keine Master-Master-Topologie erforderlich. Sie können einfach von
server1 auf server2 auf den Slave replizieren. Wenn server2 die Blackhole-StorageEngine für Tabellen benutzt, die von server1 repliziert wurden, enthält er keine Daten
von server1, wie in Abbildung 8-14 zu sehen ist.
DB1
DB1
Master 2
DB2
DB1
Slave
DB2
Abbildung 8-14: Eine weitere Methode, um die Multimaster-Replikation zu emulieren
Beide Konfigurationen können unter den üblichen Problemen leiden, wie etwa widersprüchlichen Aktualisierungen und CREATE TABLE-Anweisungen, die explizit eine StorageEngine angeben.
Einen Log-Server erzeugen
Eines der Dinge, die Sie mit der MySQL-Replikation erreichen können, ist die Erzeugung
eines »Log-Servers« ohne Daten, dessen einzige Aufgabe darin besteht, das Abspielen
und/oder Filtern von Binärlog-Events zu erleichtern. Wie Sie später erkennen werden,
nützt das, wenn man die Replikation nach einem Absturz neu starten muss, und hilft bei
der punktgenauen Wiederherstellung, die wir in Kapitel 11 vorstellen.
Stellen Sie sich vor, Sie haben eine Gruppe von Binärlogs oder Relay-Logs – vielleicht aus
einem Backup, vielleicht von einem abgestürzten Server – und wollen die darin enthaltenen Events wieder abspielen. Sie könnten die Events mit mysqlbinlog extrahieren, bequemer und effizienter ist es jedoch, eine MySQL-Instanz ohne Daten einzurichten und ihr
vorzugaukeln, dass die Binärlogs ihre eigenen wären. Sie können das MySQL SandboxSkript von http://sourceforge.net/projects/mysql-sandbox/ benutzen, um den Log-Server
einzurichten, falls Sie ihn nur zeitweise benötigen. Der Log-Server benötigt keine Daten,
weil er keine Logs ausführen wird – er dient nur den Logs der anderen Server. (Er braucht
allerdings einen Replikationsbenutzer.)
Schauen wir uns an, wie diese Technik funktioniert (Anwendungen dafür zeigen wir später). Nehmen Sie an, die Logs heißen somelog-bin.000001, somelog-bin.000002 usw.
Replikationstopologien | 407
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Master 1
Legen Sie diese Dateien in das Binärlogverzeichnis Ihres Log-Servers. Wir nehmen einmal
an, das ist /var/log/mysql. Bevor Sie den Log-Server starten, bearbeiten Sie seine my.cnfDatei:
log_bin
= /var/log/mysql/somelog-bin
log_bin_index = /var/log/mysql/somelog-bin.index
# /bin/ls -1 /var/log/mysql/somelog-bin.[0-9]* > /var/log/mysql/somelog-bin.index
Sorgen Sie dafür, dass der Benutzer-Account, unter dem MySQL läuft, die Log-Indexdatei lesen und schreiben kann. Jetzt können Sie Ihren Log-Server starten und mit SHOW
MASTER LOGS überprüfen, ob er die Log-Dateien sieht.
Wieso ist es für die Wiederherstellung besser, einen Log-Server anstelle von mysqlbinlog
einzusetzen? Dafür gibt es mehrere Gründe:
• Es ist schneller, weil jetzt die Anweisungen nicht mehr aus dem Log extrahiert und
an mysql geleitet werden müssen.
• Sie können den Fortgang leicht überblicken.
• Sie können Fehlern leicht begegnen. Es ist z.B. möglich, Anweisungen zu überspringen, die nicht repliziert werden können.
• Sie können leicht Replikations-Events filtern.
• Manchmal ist mysqlbinlog aufgrund der Änderungen des Logging-Formats nicht in
der Lage, das Binärlog zu lesen.
Replikation und Kapazitätsplanung
Meist sind Schreiboperationen die Engstelle bei der Replikation. Es ist schwierig, Schreiboperationen mit der Replikation zu skalieren. Sie müssen richtig rechnen, wenn Sie planen, welche Kapazität die Slaves Ihrem System insgesamt hinzufügen. Es kommt in
diesem Zusammenhang leicht zu Fehlern.
Stellen Sie sich z.B. vor, Ihre Arbeitsbelastung besteht zu 20 % aus Schreib- und zu 80 %
aus Lesevorgängen. Um die Berechnungen zu erleichtern, wollen wir vereinfachen und
Folgendes annehmen:
• Lese- und Schreibabfragen erfordern die gleiche Menge Arbeit.
• Alle Server sind genau gleich und haben die Kapazität, exakt 1.000 Abfragen pro
Sekunde zu erledigen.
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Der Server entdeckt die Log-Dateien nicht automatisch, Sie müssen also die Log-Indexdatei des Servers aktualisieren. Nutzen Sie dazu auf Unix-artigen Systemen folgenden
Befehl:9
9 Wir benutzen explizit /bin/ls, um zu verhindern, dass gebräuchliche Aliase aufgerufen werden, die TerminalEscape-Codes für eine farbige Darstellung hinzufügen.
408 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
• Slaves und Master besitzen die gleichen Leistungsmerkmale.
• Sie können alle Leseabfragen auf die Slaves verschieben.
Es sieht so aus, als könnten Sie 2 Slaves hinzufügen und die 1.600 Leseoperationen zwischen ihnen aufteilen. Vergessen Sie jedoch nicht, dass Ihre Schreiblast sich auf 400
Abfragen pro Sekunde erhöht hat und nicht zwischen Mastern und Slaves aufgeteilt werden kann. Jeder Slave muss 400 Schreiboperationen pro Sekunde durchführen. Das
bedeutet, dass jeder Slave zu 40 % mit Schreiboperationen belastet wird und nur 600
Leseoperationen pro Sekunde bedienen kann. Daher brauchen Sie nicht zwei, sondern
drei Slaves, um den doppelten Verkehr zu erledigen.
Was ist, wenn Ihr Verkehr sich wieder verdoppelt? Es gibt dann 800 Schreiboperationen
pro Sekunde, der Master kommt also noch hinterher. Die Slaves sind dann aber auch zu
80 % mit Schreiboperationen belastet, so dass Sie 16 Slaves brauchen, um die 3.200 Leseabfragen pro Sekunde zu verarbeiten. Und wenn sich der Verkehr jetzt noch ein wenig
erhöht, ist es für den Master zu viel.
Das ist weit von einer linearen Skalierbarkeit entfernt: Sie benötigen 17-mal so viele Server, um die vierfache Anzahl an Abfragen zu verarbeiten. Dies verdeutlicht, dass Sie
schnell einen Punkt abnehmender Erträge erreichen, wenn Sie Slaves zu einem einzigen
Master hinzufügen. Und das gilt sogar bei unseren unrealistischen Annahmen, die z.B.
die Tatsache ignorieren, dass eine anweisungsbasierte Single-Thread-Replikation normalerweise dafür sorgt, dass die Slaves eine niedrigere Kapazität als der Master aufweisen.
Eine echte Replikationsanordnung ist wahrscheinlich sogar noch schlechter als unsere
theoretische.
Weshalb die Replikation das Skalieren von Schreiboperationen nicht
unterstützt
Das grundlegende Problem mit dem miesen Verhältnis von Server zu Kapazität besteht
darin, dass Sie die Schreibvorgänge im Gegensatz zu den Lesevorgängen nicht gleichermaßen zwischen den Maschinen verteilen können. Leseoperationen lassen sich also skalieren, Schreiboperationen nicht.
Sie werden sich fragen, ob es eine Möglichkeit gibt, mittels Replikation die Schreibkapazität zu erhöhen. Die Antwort lautet Nein – nicht einmal ein bisschen. Das Aufteilen
(Partitionieren) Ihrer Daten ist die einzige Methode, mit der Sie Schreiboperationen skalieren können. Näheres dazu finden Sie im nächsten Kapitel.
Manche Leser denken jetzt vielleicht darüber nach, eine Master-Master-Topologie zu verwenden (siehe »Master-Master im Aktiv-Aktiv-Modus« auf Seite 395) und auf beide Master zu schreiben. Diese Konfiguration kann im Vergleich zu einer Master-Slave-Topologie
Replikation und Kapazitätsplanung | 409
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Falls Sie momentan einen Server haben, der 1.000 Abfragen pro Sekunde erledigt, wie
viele Slaves müssen Sie dann hinzufügen, um das Doppelte Ihrer aktuellen Last zu verarbeiten und alle Leseabfragen auf die Slaves zu verschieben?
Das scheint attraktiv zu sein. Eine solche Konfiguration kann allerdings trotzdem nicht
so viele Schreiboperationen durchführen wie ein einzelner Server. Ein Server, dessen
Schreiblast zu 50 % serialisiert ist, ist langsamer als ein einzelner Server, der alle seine
Schreibvorgänge parallel erledigt.
Deshalb eignet sich diese Taktik nicht zum Skalieren von Schreiboperationen. Es ist nur
eine Methode, um den Nachteil serialisierten Schreibens auf zwei Server zu verteilen,
damit das »schwächste Glied in der Kette« nicht ganz so schwach ist. Sie bietet nur eine
relativ kleine Verbesserung gegenüber einer Aktiv-Passiv-Anordnung, das zusätzliche
Risiko ist jedoch unverhältnismäßig viel größer – und, wie Sie im nächsten Abschnitt
erfahren, Sie haben eigentlich gar nichts davon.
Seien Sie großzügig und verschwenderisch
Wenn Sie Ihre Server absichtlich teilweise ungenutzt lassen, können Sie auf clevere und
kosteneffektive Weise eine große Anwendung aufbauen, speziell, wenn Sie Replikation
einsetzen. Server, die freie Kapazitäten aufweisen, tolerieren Lastspitzen besser, haben
mehr Potenzial, um langsame Abfragen und Wartungsaufgaben zu erledigen (wie etwa
OPTIMIZE TABLE-Operationen), und halten besser mit der Replikation Schritt.
Es ist normalerweise der falsche Ansatz zu versuchen, die Replikationsnachteile auszugleichen, indem man in einer Master-Master-Topologie auf beide Knoten schreibt. Sie
sollten ein Master-Master-Paar üblicherweise zu weniger als 50 % mit Leseoperationen
belasten, denn wenn die Last größer ist, reicht die Kapazität nicht aus, falls einer der Server ausfällt. Wenn beide Server die Last auch allein bewältigen könnten, dann müssen Sie
sich wahrscheinlich nicht um die Nachteile bei der Single-Thread-Replikation sorgen.
Das Anlegen einer übertriebenen Kapazität stellt darüber hinaus eines der besten Mittel
dar, um Hochverfügbarkeit zu erreichen, obwohl es dafür auch andere Methoden gibt.
So könnten Sie Ihre Anwendung auch in einem »geschwächten« Modus ausführen, wenn
es einen Ausfall gegeben hat. Im nächsten Kapitel untersuchen wir das genauer.
Replikationsadministration und -wartung
Vermutlich werden Sie sich nicht ständig mit dem Einrichten der Replikation befassen,
zumindest, wenn Sie nicht sehr viele Server haben. Sobald Sie allerdings mit der Einrichtung fertig sind, gehören Überwachung und Administration Ihrer Replikationstopologie
zu Ihren regelmäßigen Aufgaben, egal, wie viele Server Sie haben.
410 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
etwas mehr Schreiboperationen erledigen, weil Sie die Nachteile durch die Serialisierung
gleichmäßig zwischen den beiden Servern aufteilen können. Wenn Sie auf jedem Server
50 % der Schreiboperationen erledigen, dann müssen nur die 50 %, die via Replikation
vom anderen Server erfolgen, serialisiert werden. Theoretisch ist das besser, als 100 %
der Schreiboperationen parallel auf einer Maschine (dem Master) durchzuführen und
100 % der Schreiboperationen seriell auf der anderen Maschine (dem Slave).
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Sie sollten versuchen, diese Arbeit nach Möglichkeit zu automatisieren. Allerdings müssen Sie dazu keine eigenen Werkzeuge schreiben: In Kapitel 14 stellen wir verschiedene
Programme für MySQL vor, von denen viele bereits mit Überwachungsmöglichkeiten
oder Plugins ausgestattet sind. Zu den nützlichsten Angeboten gehören Nagios, MySQL
Enterprise Monitor und MonYOG.
Die Replikation erhöht die Komplexität der MySQL-Überwachung. Obwohl die Replikation sowohl auf dem Master als auch auf dem Slave stattfindet, wird die meiste Arbeit auf
dem Slave erledigt. Dort treten auch die meisten Probleme auf. Replizieren wirklich alle
Slaves? Hat ein Slave Fehler gezeigt? Wie weit liegt der langsamste Slave zurück? MySQL
bietet die meisten Informationen, die Sie benötigen, um diese Fragen zu beantworten.
Ihnen bleibt es allerdings überlassen, den Vorgang zu überwachen und die Replikation zu
stabilisieren.
Auf dem Master können Sie mit dem Befehl SHOW MASTER STATUS die aktuelle BinärlogPosition des Masters und die Konfiguration ermitteln (siehe »Master und Slave konfigurieren« auf Seite 378). Sie können den Master auch fragen, welche Binärlogs auf der Festplatte vorliegen:
mysql> SHOW MASTER LOGS;
+------------------+-----------+
| Log_name
| File_size |
+------------------+-----------+
| mysql-bin.000220 |
425605 |
| mysql-bin.000221 |
1134128 |
| mysql-bin.000222 |
13653 |
| mysql-bin.000223 |
13634 |
+------------------+-----------+
Diese Informationen helfen Ihnen dabei, festzustellen, welche Parameter Sie dem Befehl
PURGE MASTER LOGS übergeben müssen. Mit dem Befehl SHOW BINLOG EVENTS können Sie sich
Replikations-Events im Binärlog anschauen. Nachdem wir z.B. den vorangegangenen
Befehl ausgeführt hatten, erzeugten wir eine Tabelle auf einem ansonsten unbenutzten
Server. Da wir wussten, dass dies die einzige Anweisung war, die irgendwelche Daten
ändert, wussten wir, dass der Offset der Anweisung im Binärlog 13634 war. Wir konnten
sie uns also folgendermaßen anschauen:
mysql> SHOW BINLOG EVENTS IN 'mysql-bin.000223' FROM 13634\G
*************************** 1. row ***************************
Log_name: mysql-bin.000223
Pos: 13634
Event_type: Query
Server_id: 1
End_log_pos: 13723
Info: use `test`; CREATE TABLE test.t(a int)
Replikationsadministration und -wartung | 411
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Die Replikation überwachen
Den Rückstand des Slaves messen
• Der Slave berechnet Seconds_behind_master, indem er den aktuellen Zeitstempel des
Servers mit dem Zeitstempel vergleicht, der im Binärlog-Event aufgezeichnet ist, so
dass der Slave seinen Rückstand erst dann melden kann, wenn er eine Abfrage verarbeitet.
• Der Slave gibt normalerweise NULL zurück, wenn die Slave-Prozesse nicht laufen.
• Manche Fehler (z.B. falsch angepasste max_allowed_packet-Einstellungen zwischen
dem Master und dem Slave oder ein instabiles Netzwerk) können die Replikation
unterbrechen und/oder die Slave-Threads stoppen. Seconds_behind_master gibt
jedoch eine 0 zurück, anstatt einen Fehler anzuzeigen.
• Der Slave kann manchmal die Verzögerung nicht berechnen, obwohl die Slave-Prozesse laufen. Wenn dies geschieht, meldet der Slave entweder 0 oder NULL.
• Eine sehr lange Transaktion kann dafür sorgen, dass der berichtete Rückstand
schwankt. Falls Sie z.B. eine Transaktion haben, die Daten aktualisiert, stundenlang
offen bleibt und dann bestätigt wird, gelangt die Aktualisierung ungefähr eine
Stunde, nachdem sie tatsächlich aufgetreten ist, in das Binärlog. Wenn der Slave die
Anweisung verarbeitet, berichtet er zeitweise, dass er eine Stunde hinter dem Master zurückliegt, und springt dann wieder auf einen Rückstand von null Sekunden.
• Wenn ein Distribution-Master zurückfällt und selbst Slaves besitzt, berichten die
Slaves, dass sie null Sekunden zurückliegen, wenn sie zum Distribution-Master aufgeholt haben, obwohl es relativ zum eigentlichen Master einen wirklichen Rückstand gibt.
Ignorieren Sie deshalb Seconds_behind_master, und messen Sie die Verzögerung des Slaves
mit etwas, das Sie direkt überwachen und messen können. Eine gute Lösung wäre ein
Heartbeat Record, also ein Zeitstempel, den Sie einmal pro Sekunde auf dem Master
aktualisieren können. Um den Rückstand zu berechnen, subtrahieren Sie einfach den
Heartbeat vom aktuellen Zeitstempel auf dem Slave. Diese Methode ist immun gegenüber all den gerade erwähnten Problemen und hat den zusätzlichen Vorteil, dass ein
praktischer Zeitstempel erzeugt wird, der zeigt, an welchem Punkt in der Zeit sich die
Daten des Slaves momentan befinden. Das mk-heartbeat-Skript, das in Maatkit enthalten
ist, ist eine Implementierung eines Replikations-Heartbeats.
Keines der genannten Maße für den Rückstand bietet Ihnen einen Anhaltspunkt dafür,
wie lange es dauert, bis ein Slave tatsächlich seinen Master eingeholt hat. Das hängt von
vielen Faktoren ab, etwa von der Leistungsfähigkeit des Slaves und der Anzahl der
Schreibabfragen, die der Master verarbeitet.
412 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Zu den Dingen, die Sie am häufigsten überwachen müssen, gehört der Rückstand, den
ein Slave gegenüber dem Master hat. Die Spalte Seconds_behind_master in SHOW SLAVE
STATUS zeigt zwar theoretisch den Rückstand des Slaves, dieser Wert ist allerdings aus
verschiedenen Gründen nicht immer exakt:
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Feststellen, ob Slaves konsistent mit dem Master sind
Unserer Erfahrung nach ist das die Regel, nicht die Ausnahme, was bedeutet, dass es
eigentlich eine Routineaufgabe sein sollte, Ihre Slaves auf Konsistenz mit ihren Mastern
zu prüfen. Das ist besonders wichtig, wenn Sie die Replikation für Backups benutzen,
weil Sie natürlich keine Backups von einem beschädigten Slave nehmen wollen.
Die erste Ausgabe dieses Buches enthielt ein Beispielskript, mit dem man die Anzahl der
Zeilen in den Tabellen auf dem Master und dem Slave vergleichen konnte. Damit kann
man sicher einige Unterschiede feststellen, allerdings ist die Zeilenanzahl keine echte
Gewähr für identische Daten. Was Sie wirklich brauchen, ist eine effiziente Methode, um
die eigentlichen Inhalte der Tabellen zu vergleichen.
In MySQL ist keine Methode integriert, mit der sich feststellen ließe, ob ein Server die
gleichen Daten enthält wie ein anderer Server. Es besitzt einige Grundbausteine, um Prüfsummen von Tabellen und Daten zu erzeugen, wie etwa CHECKSUM TABLE. Es ist jedoch
nicht trivial, einen Slave mit seinem Master zu vergleichen, während die Replikation im
Gange ist.
Maatkit enthält ein Werkzeug namens mk-table-checksum, das dieses und etliche andere
Probleme löst. Das Werkzeug besitzt mehrere Funktionen, einschließlich schneller paralleler Vergleiche vieler Server auf einmal. Seine Hauptfunktion ist allerdings, zu verifizieren, ob die Daten eines Slaves synchron zu denen seines Masters sind. Dazu führt es
INSERT ... SELECT-Abfragen auf dem Master ab.
Diese Abfragen erzeugen Prüfsummen der Daten und fügen die Ergebnisse in eine
Tabelle ein. Die Anweisungen laufen durch die Replikation und werden erneut auf dem
Slave ausgeführt. Sie können die Ergebnisse auf dem Master dann mit den Ergebnissen
auf dem Slave vergleichen und feststellen, ob sich die Daten unterscheiden. Da dieser
Vorgang durch die Replikation geht, erhalten Sie konsistente Ergebnisse, ohne dass Sie
die Tabellen auf beiden Servern gleichzeitig sperren müssen.
Typischerweise wird dieses Werkzeug auf dem Master ausgeführt, und zwar mit solchen
Parametern:
$ mk-table-checksum --replicate=test.checksum --chunksize 100000 --sleepcoef=2 <master_host>
10 Wenn Sie eine nichttransaktionsfähige Storage-Engine benutzen, dann ist das Herunterfahren des Servers,
ohne zuerst STOP SLAVE auszuführen, unsanft.
Replikationsadministration und -wartung | 413
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
In einer perfekten Welt würde ein Slave immer eine exakte Kopie seines Masters sein.
Tatsächlich aber sorgen Fehler bei der Replikation dafür, dass die Daten des Slaves von
denen des Masters »wegdriften«. Selbst wenn offensichtlich keine Fehler auftreten, können Slaves abweichen, weil es MySQL-Eigenschaften gibt, die nicht korrekt repliziert
werden, weil Bugs in MySQL, Netzwerkschäden, Abstürze, unsanftes Herunterfahren
oder andere Ausfälle auftreten.10
Sobald die Abfragen auf den Slaves repliziert wurden, kann eine einfache Abfrage den
Slave auf Unterschiede zum Master prüfen. mk-table-checksum sucht automatisch die
Slaves eines Servers, führt die Abfrage auf den einzelnen Slaves aus und gibt die Ergebnisse aus. Der folgende Befehl steigt, jeweils beim gleichen Master-Server beginnend, bis
auf eine Tiefe von 10 in der Slave-Hierarchie hinab und gibt Tabellen aus, die sich vom
Master unterscheiden:
$ mk-table-checksum --replicate=test.checksum --replcheck 10 <master_host>
Bei MySQL AB plant man, irgendwann eine ähnliche Funktion im Server selbst zu implementieren. Das ist dann wahrscheinlich besser als ein externes Skript, aber momentan ist
mk-table-checksum das einzige Werkzeug, mit dem man zuverlässig und einfach die
Daten eines Slaves mit denen seines Masters vergleichen kann.
Einen Slave wieder mit dem Master synchronisieren
Sie werden vermutlich mehr als einmal in Ihrer beruflichen Laufbahn mit einem Slave in
Berührung kommen, dessen Daten nicht mehr mit denen des Masters übereinstimmen.
Vielleicht haben Sie mit der Prüfsummentechnik Unterschiede entdeckt, vielleicht wissen
Sie auch, dass der Slave eine Abfrage übersprungen hat oder dass jemand die Daten auf
dem Slave geändert hat.
Der herkömmliche Rat zum Reparieren eines nichtsynchronisierten Slaves lautet, ihn zu
stoppen und wieder vom Master zu klonen. Wenn ein inkonsistenter Slave ein ernsthaftes Problem darstellt, dann sollten Sie ihn wahrscheinlich anhalten und aus dem Betrieb
entfernen, sobald Sie ihn gefunden haben. Anschließend können Sie den Slave erneut
klonen oder aus einem Backup wiederherstellen.
Nachteilig an diesem Ansatz ist seine Unbequemlichkeit, vor allem, wenn Sie viele Daten
haben. Wenn Sie feststellen können, welche Daten sich unterscheiden, dann können Sie
es vermutlich effizienter erledigen, als durch das erneute Klonen des gesamten Servers.
Und wenn die entdeckte Inkonsistenz nicht bedeutsam ist, dann lassen Sie ihn einfach in
Betrieb und synchronisieren nur die betroffenen Daten.
Am einfachsten ist es, nur die betroffenen Daten mit mysqldump zu speichern und erneut
zu laden. Das funktioniert ganz gut, wenn sich die Daten währenddessen nicht ändern.
Sie sperren die Tabelle auf dem Master, stellen einen Dump der Tabelle her, warten
darauf, dass der Slave den Master einholt, und importieren dann die Tabelle auf den
Slave. (Sie müssen auf den Slave warten, damit Sie in den anderen Tabellen keine weiteren Inkonsistenzen einführen, wie etwa solche, die dann wiederum in Joins mit der nichtsynchronisierten Tabelle auftreten.)
414 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Dieser Befehl erzeugt aus allen Tabellen Prüfsummen, wobei er versucht, die Tabellen in
Gruppen von ungefähr 100.000 Zeilen zu verarbeiten, und fügt die Ergebnisse in die
test.checksum-Tabelle ein. Zwischen den einzelnen Verarbeitungsgruppen pausiert er
und schläft doppelt so lange, wie es dauerte, die Prüfsumme für die letzte Gruppe zu
erzeugen. Damit wird sichergestellt, dass die Abfragen den normalen Datenbankbetrieb
nicht blockieren.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
mk-table-sync ist ein weiteres Werkzeug von Maatkit, das einige dieser Probleme löst. Es
kann Unterschiede zwischen Tabellen effizient finden und auflösen. Außerdem kann es
durch die Replikation agieren, indem es den Slave durch das Ausführen von Abfragen auf
dem Master neu synchronisiert – also: keine Race-Conditions. Es funktioniert jedoch
nicht in allen Szenarien: Es erfordert, dass die Replikation läuft, um einen Master und
einen Slave korrekt zu synchronisieren. Das Werkzeug funktioniert also nicht, wenn bei
der Replikation ein Fehler auftritt. mk-table-sync wurde mit Blick auf Effizienz geschaffen, ist bei extrem großen Datenmengen jedoch unpraktisch. Der Vergleich von einem
Terabyte Daten auf dem Master und dem Slave verursacht zwangsläufig zusätzliche
Arbeit für beide Server. In Fällen, in denen es jedoch funktioniert, können Sie eine Menge
Zeit und Aufwand sparen.
Die Master wechseln
Früher oder später müssen Sie einen Slave auf einen neuen Master richten. Vielleicht tauschen Sie die Server aufgrund eines Upgrades, vielleicht gab es ja auch einen Ausfall und
Sie müssen einen Slave zum Master machen, oder vielleicht teilen Sie einfach nur neue
Kapazitäten zu. Egal, welchen Grund es gibt, Sie müssen den Slave über seinen neuen
Master informieren.
Wenn der Prozess geplant ist, dann ist es leicht (oder zumindest leichter als im Krisenfall). Sie rufen auf dem Slave einfach den CHANGE MASTER TO-Befehl mit den passenden Werten auf. Die meisten der Werte sind optional; Sie müssen nur diejenigen angeben, die Sie
ändern. Der Slave verwirft seine aktuelle Konfiguration und die Relay-Logs und beginnt
damit, vom neuen Master zu replizieren. Er aktualisiert außerdem die master.info-Datei
mit den neuen Parametern, damit die Änderung einen Neustart des Slaves überdauert.
Der schwierigste Teil dieses Vorgangs ist das Ermitteln der gewünschten Position auf
dem neuen Master, damit der Slave an der gleichen logischen Position beginnt, an der er
auf dem alten Master gestoppt hat.
Das Befördern eines Slaves zum neuen Master ist etwas schwieriger. Es gibt zwei Grundszenarien, wie man einen Master durch einen seiner Slaves ersetzt. Beim ersten handelt es
sich um eine geplante Beförderung, beim zweiten um eine ungeplante.
Replikationsadministration und -wartung | 415
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Das geht zwar in vielen Fällen gut, ist aber auf einem stark belasteten Server oft unmöglich. Es hat außerdem den Nachteil, dass die Daten des Slaves außerhalb der Replikation
geändert werden. Das Ändern der Slave-Daten durch die Replikation (indem Änderungen auf dem Master vorgenommen werden) ist normalerweise die sicherste Technik, da
hässliche Race-Conditions und andere Überraschungen vermieden werden. Wenn die
Tabelle sehr groß oder die Netzwerkbandbreite begrenzt ist, dann sind das Speichern in
einem Dump und das Neuladen unerschwinglich teuer. Was ist, wenn sich jede tausendste Zeile in einer Tabelle mit Millionen von Zeilen unterscheidet? Das Speichern und
Neuladen der gesamten Tabelle wäre in diesem Fall eine Verschwendung.
Geplante Beförderungen
Einen Slave zum Master zu befördern, ist vom Konzept her einfach. Es sind folgende
Schritte erforderlich:
1. Schreiboperationen auf dem alten Master werden gestoppt.
nachfolgenden Schritte).
3. Ein Slave muss zum neuen Master konfiguriert werden.
4. Slaves und Schreibverkehr müssen auf den neuen Master gerichtet werden, anschließend müssen Schreiboperationen auf ihm zugelassen werden.
Der Teufel steckt jedoch im Detail. Es sind mehrere Szenarien möglich, je nach Ihrer
Replikationstopologie. So unterscheiden sich die Schritte bei einer Master-Master-Topologie leicht von denen bei einer Master-Slave-Anordnung.
Hier sind, etwas ausführlicher, die Schritte, die Sie wahrscheinlich in den meisten Anordnungen unternehmen müssen:
1. Stoppen Sie alle Schreiboperationen auf dem aktuellen Master. Falls möglich soll-
2.
3.
4.
5.
6.
7.
8.
9.
ten Sie sogar alle Clientprogramme (nicht die Replikationsverbindungen) zwingen,
sich zu beenden. Es hilft, wenn Sie Ihre Clientprogramme mit einem »Do not run«Flag erstellt haben, das Sie setzen können. Wenn Sie virtuelle IP-Adressen benutzen, können Sie einfach ihre Verarbeitung ausschalten und dann alle Clientverbindungen beenden, um deren offenen Transaktionen zu schließen.
Stoppen Sie optional mit FLUSH TABLES WITH READ LOCK alle Schreibaktivitäten auf dem
Master. Sie können auf dem Master mit der Option read_only auch einen Schreibschutz setzen. Von diesem Augenblick an sollten Sie alle Schreibvorgänge auf dem
zu ersetzenden Master verbieten. Da er jetzt kein Master mehr ist, würden Sie
ansonsten Daten verlieren, wenn Sie auf ihm schreiben lassen!
Wählen Sie einen der Slaves als neuen Master aus, und stellen Sie sicher, dass er in
der Replikation vollständig aufgeholt hat (d.h., lassen Sie ihn das Ausführen aller
Relay-Logs beenden, die er vom alten Master geholt hat).
Überprüfen Sie optional, dass der neue Master die gleichen Daten enthält wie der
alte Master.
Führen Sie STOP SLAVE auf dem neuen Master aus.
Führen Sie auf dem neuen Master CHANGE MASTER TO MASTER_HOST='' aus, gefolgt von
RESET SLAVE, um die Verbindung zum alten Master zu trennen und die Verbindungsinformationen in seiner master.info-Datei zu verwerfen. (Das funktioniert nicht richtig, wenn die Verbindungsinformationen in my.cnf angegeben sind, weshalb wir
auch davon abraten, sie dorthin zu legen.)
Holen Sie sich die Binärlog-Koordinaten des neuen Masters mit SHOW MASTER STATUS.
Sorgen Sie dafür, dass alle anderen Slaves auf den neuesten Stand kommen.
Fahren Sie den alten Master herunter.
416 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
2. Optional müssen seine Slaves bei der Replikation aufholen (dies vereinfacht die
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
10. Aktivieren Sie in MySQL-Versionen ab 5.1 Events auf dem neuen Master, falls erfor-
Wenn Sie einen Slave in einen Master umwandeln, dann achten Sie
darauf, dass Sie ihn aus allen Slave-spezifischen Datenbanken, Tabellen
und Berechtigungen entfernen. Sie müssen außerdem alle Slave-spezifischen Konfigurationsparameter ändern, wie etwa eine innodb_flush_log_
at_trx_commit-Option. Falls Sie andererseits einen Master zum Slave
zurückstufen, müssen Sie ihn ebenfalls entsprechend umkonfigurieren.
Falls Sie Ihre Master und Slaves identisch konfigurieren, müssen Sie nichts
ändern.
Ungeplante Beförderungen
Es ist nicht ganz so leicht, einen Slave zu befördern, um einen Master zu ersetzen, wenn
dieser abstürzt. Gibt es nur einen Slave, dann nehmen Sie einfach diesen. Gibt es jedoch
mehrere Slaves, dann müssen Sie einige zusätzliche Schritte ausführen, um einen Slave in
den neuen Master zu verwandeln.
Dazu kommt noch das Problem potenziell verloren gegangener Replikations-Events. Es
ist möglich, dass einige Updates, die auf dem Master vorgenommen wurden, noch nicht
auf alle seine Slaves repliziert wurden. Es kann sogar sein, dass eine Anweisung ausgeführt und dann auf dem Master zurückgenommen wurde, nicht jedoch auf dem Slave –
so dass der Slave der logischen Replikationsposition des Masters sogar voraus sein
könnte.11 Falls Sie die Daten des Masters an irgendeinem Punkt wiederherstellen können,
dann sind Sie möglicherweise in der Lage, die verloren gegangenen Anweisungen wiederzubekommen und manuell anzuwenden.
Achten Sie in den folgenden Schritten darauf, die Werte Master_Log_File und Read_
Master_Log_Pos in Ihren Berechnungen einzusetzen. Hier ist das Vorgehen beim Befördern eines Slaves in einer Master-und-Slaves-Topologie:
1. Stellen Sie fest, welcher Slave die neuesten Daten besitzt. Prüfen Sie die Ausgabe von
SHOW SLAVE STATUS auf jedem Slave, und wählen Sie denjenigen, dessen Master_Log_
File/Read_Master_Log_Pos-Koordinaten am neuesten sind.
2. Erlauben Sie allen Slaves, das Ausführen der Relay-Logs zu beenden, die sie vom
alten Master geholt hatten, bevor er abgestürzt ist. Wenn Sie den Master eines Slaves wechseln, bevor er mit dem Ausführen des Relay-Logs fertig ist, wirft er alle verbleibenden Log-Events weg, und Sie wissen nicht, wo er gestoppt hat.
11 Das ist tatsächlich möglich, obwohl MySQL Events erst dann in das Log schreibt, wenn die Transaktion bestätigt wurde. Näheres erfahren Sie in »Transaktionsfähige und nichttransaktionsfähige Tabellen mischen« auf
Seite 425.
Replikationsadministration und -wartung | 417
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
derlich.
11. Erlauben Sie es den Clients, eine Verbindung zum neuen Master herzustellen.
12. Rufen Sie auf jedem Slave einen CHANGE MASTER TO-Befehl auf, mit dem Sie den jeweiligen Slave auf den neuen Master richten. Verwenden Sie dabei die Binärlog-Koordinaten, die Sie mit SHOW MASTER STATUS gesammelt haben.
3. Führen Sie die Schritte 5 bis 7 der Liste aus dem vorangegangenen Abschnitt aus.
4. Vergleichen Sie die Master_Log_File/Read_Master_Log_Pos-Koordinaten der einzel-
nen Slaves mit denen des neuen Masters.
5. Führen Sie die Schritte 10 bis 12 der Liste aus dem vorangegangenen Abschnitt aus.
Die gewünschten Log-Positionen suchen
Befindet sich einer der Slaves nicht an der gleichen Position wie der neue Master, müssen
Sie die Position in den Binärlogs des neuen Masters suchen, die dem letzten Event entspricht, das der Slave repliziert hat, und für CHANGE MASTER TO einsetzen. Mit dem Programm mysqlbinlog können Sie die letzte Abfrage untersuchen, die der Slave ausgeführt
hat, und diese Abfrage im Binärlog des neuen Masters suchen. Ein paar kleine Berechnungen sind auch oft ganz hilfreich.
Um das zu verdeutlichen, wollen wir annehmen, dass Log-Events ansteigende ID-Nummern haben und dass der Slave, der auf dem neuesten Stand ist – der neue Master –, gerade
Event 100 erreicht hatte, als der alte Master abstürzte. Nun wollen wir noch annehmen,
dass es zwei weitere Slaves gibt, nämlich slave2 und slave3. slave2 hatte Event 99 und
slave3 Event 98 erreicht. Wenn Sie beide Slaves auf die aktuelle Binärlog-Position des
neuen Masters verweisen, beginnen sie bei Event 101 mit der Replikation, sind also nicht
mehr synchron. Solange jedoch das Binärlog des neuen Masters mit log_slave_updates eingeschaltet war, können Sie die Events 99 und 100 im Binärlog des neuen Masters finden,
um die Slaves wieder zurück in einen konsistenten Zustand zu überführen.
Aufgrund von Serverneustarts, unterschiedlichen Konfigurationen, Log-Wechseln oder
FLUSH LOGS-Befehlen können die gleichen Events auf unterschiedlichen Servern bei unterschiedlichen Byte-Offsets existieren. Das Suchen der Events nervt und geht langsam vonstatten, ist aber normalerweise nicht schwer. Untersuchen Sie einfach das letzte Event, das
auf dem jeweiligen Slave ausgeführt wurde, indem Sie im Binärlog oder im Relay-Log des
Slaves mysqlbinlog ausführen. Suchen Sie anschließend – ebenfalls mit mysqlbinlog – die
gleiche Abfrage im Binärlog des neuen Masters. Das Programm gibt den Byte-Offset der
Abfrage aus. Sie können diesen Offset dann in der CHANGE MASTER TO-Abfrage einsetzen.
Sie beschleunigen diesen Vorgang, indem Sie die Byte-Offsets, an denen der neue Master
und der Slave gestoppt haben, voneinander abziehen und auf diese Weise die Differenz in
ihren Byte-Positionen ermitteln. Falls Sie dann diesen Wert von der aktuellen BinärlogPosition des neuen Masters subtrahieren, ist die Wahrscheinlichkeit ziemlich hoch, dass
Sie die gewünschte Abfrage an dieser Position gefunden haben. Sie müssen nun nur noch
verifizieren, dass sie es tatsächlich ist, und haben jetzt die Position, an der Sie den Slave
starten müssen.
418 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Wir gehen davon aus, dass Sie log_bin und log_slave_updates auf allen Slaves aktiviert
haben, wie wir Ihnen zu Beginn dieses Kapitels empfohlen haben. Wenn Sie dieses Logging aktivieren, haben Sie die Möglichkeit, alle Slaves zu einem konsistenten Zeitpunkt
wiederherzustellen, was ansonsten nicht zuverlässig möglich wäre.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Schauen wir uns ein konkretes Beispiel an. Stellen Sie sich vor, server1 ist der Master von
server2 und server3 und stürzt ab. Entsprechend Master_Log_File/Read_Master_Log_Pos
in SHOW SLAVE STATUS hat es server2 geschafft, alle Events zu replizieren, die sich im Binärlog von server1 befanden; server3 dagegen ist nicht so aktuell. Abbildung 8-15 verdeutlicht dieses Szenario (die Log-Events und Byte-Offsets dienen nur zur Demonstration).
mysql-bin.000001
1450
1493
1582
Server2
Master_Log_File = mysql-bin.000001
Read_Master_Log_Pos = 1582
UPDATE
DELETE
INSERT
Server3
Master_Log_File = mysql-bin.000001
Read_Master_Log_Pos = 1493
mysql-bin.000009
8035
8078
8167
UPDATE
DELETE
INSERT
Binärlog-Datei
der Klarheit
wegen
weggelassen
Abbildung 8-15: Als server1 abstürzte, holte server2 auf, aber server3 hinkte hinter der Replikation
hinterher.
Wie Abbildung 8-15 verdeutlicht, können wir sicher sein, dass server2 alle Events im
Binärlog des Masters repliziert hat, weil seine Master_Log_File- und Read_Master_Log_PosWerte den letzten Positionen auf server1 entsprachen. Daher können wir server2 zum
neuen Master befördern und server3 zu seinem Slave machen.
Doch welche Parameter sollten wir im CHANGE MASTER TO-Befehl auf server3 verwenden?
Hier müssen wir ein bisschen rechnen und überlegen. server3 stoppte bei Offset 1493,
was 89 Byte hinter Offset 1582 liegt, dem letzten Befehl, den server2 ausgeführt hat.
server2 schreibt momentan an Position 8167 in sein Binärlog. 8167 – 89 = 8078, theoretisch müssen wir also server3 auf diesen Offset in den Logs von server2 verweisen. Es ist
allerdings keine schlechte Idee, die Log-Events um diese Position herum näher zu untersuchen und zu verifizieren, dass server2 tatsächlich die richtigen Events an diesem Offset
in seinen Logs hat. Es könnte nämlich dort auch etwas anderes stehen, weil z.B. eine
Datenaktualisierung stattgefunden hat, die sich auf server2 beschränkte.
Replikationsadministration und -wartung | 419
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Server1
Wenn sich bei der Untersuchung herausgestellt hat, dass es tatsächlich die gleichen
Events waren, machen wir mit dem folgenden Befehl server3 zum Slave von server2:
server2> CHANGE MASTER TO MASTER_HOST="server2", MASTER_LOG_FILE="mysqlbin.000009", MASTER_LOG_POS=8078;
Wir empfehlen Ihnen, fehlende Events vom alten Master wiederherzustellen, nachdem
Sie den neuen Master befördert, aber bevor Sie Clientverbindungen zu diesem Server
zugelassen haben. Auf diese Weise müssen Sie die fehlenden Events nicht auf jedem Slave
ausführen, das übernimmt die Replikation für Sie. Ist der ausgefallene Master dagegen
vollständig unerreichbar, müssen Sie wahrscheinlich warten und diese Arbeit später erledigen.
Eine Variante dieses Vorgehens besteht darin, dass Sie eine zuverlässige Methode zur
Speicherung der Binärlog-Dateien des Masters einsetzen, etwa ein SAN oder ein Distributed Replicated Block Device (DRBD). Selbst wenn der Master komplett ausgefallen ist,
haben Sie immer noch seine Binärlog-Dateien. Sie können einen Log-Server einrichten,
die Slaves auf ihn richten und diese dann bis zu der Stelle aufholen lassen, an der der
Master ausgefallen ist. Anschließend ist es trivial, einen der Slaves zum neuen Master zu
befördern – das geht im Prinzip genauso wie bei einer geplanten Beförderung. Wir
besprechen diese Speicheroptionen im nächsten Kapitel genauer.
Wenn Sie einen Slave zum neuen Master befördern, dann ändern Sie seine
Server-ID nicht auf die des alten Masters. In diesem Fall sind Sie nämlich
nicht mehr in der Lage, einen Log-Server einzusetzen, um die Events vom
alten Master wieder abzuspielen. Dies ist einer der vielen Gründe dafür,
weshalb man Server-IDs als fest betrachten sollte.
Rollentausch in einer Master-Master-Konfiguration
Einer der Vorteile der Master-Master-Replikation besteht darin, dass Sie aufgrund der
symmetrischen Konfiguration ganz einfach die aktiven und passiven Rollen vertauschen
können. In diesem Abschnitt zeigen wir, wie Sie diesen Tausch vollziehen.
Wenn man die Rollen in einer Master-Master-Konfiguration vertauscht, dann ist es am
wichtigsten, sicherzustellen, dass zu einem Zeitpunkt nur auf einen der Co-Master
geschrieben wird. Überschneiden sich Schreiboperationen von einem Master mit Schreiboperationen vom anderen Master, können sie in einen Konflikt geraten. Mit anderen Worten: Der passive Server darf keine Binärlog-Events vom aktiven Server empfangen,
nachdem die Rollen getauscht wurden. Sie können garantieren, dass dies nicht passiert,
indem Sie sicherstellen, dass der Slave-Thread des passiven Servers zum aktiven Server
aufholt, bevor Sie ihn schreibbar machen.
420 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Was ist, wenn server1 beim Absturz ein weiteres Event hinter Offset 1582 ausgeführt
und im Log verzeichnet hatte? Da server2 die Events nur bis zum Offset 1582 gelesen
und ausgeführt hatte, haben Sie womöglich ein Event für immer verloren. Falls jedoch
die Festplatte des alten Masters nicht beschädigt wurde, können Sie das fehlende Event
mit mysqlbinlog oder mit einem Log-Server aus seinem Binärlog wiederherstellen.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Mithilfe der folgenden Schritte vertauschen Sie die Rollen, ohne dass Sie Gefahr laufen,
widersprüchliche Aktualisierungen zu erhalten:
1. Stoppen Sie alle Schreiboperationen auf dem aktiven Server.
2. Führen Sie SET @@global.read_only := 1 auf dem aktiven Server aus, und setzen Sie
3. Führen Sie SHOW MASTER STATUS auf dem aktiven Server aus, und merken Sie sich die
Binärlog-Koordinaten.
4. Führen Sie SELECT MASTER_POS_WAIT( ) auf dem passiven Server mit den Binärlog-
Koordinaten des aktiven Servers aus. Dieser Befehl blockiert, bis die Slave-Prozesse
zum aktiven Server aufgeholt haben.
5. Führen Sie SET @@global.read_only := 0 auf dem passiven Server aus, und machen Sie
ihn damit zum aktiven Server.
6. Konfigurieren Sie Ihre Anwendungen neu, damit diese auf den neuen aktiven Server
schreiben.
Je nach der Konfiguration Ihrer Anwendung müssen Sie möglicherweise noch weitere
Aufgaben ausführen, wie etwa die IP-Adressen auf den beiden Servern ändern. Dies
besprechen wir im nächsten Kapitel.
Replikationsprobleme und Lösungen
Es ist nicht schwer, die MySQL-Replikation zu unterbrechen. Die einfache Implementierung, die die Einrichtung so sehr erleichtert, bietet auch viele Möglichkeiten, sie zu stoppen, zu verwirren oder anderweitig zu stören. In diesem Abschnitt zeigen wir Ihnen
häufig auftretende Probleme, wie sie sich äußern und wie Sie sie lösen oder sogar vermeiden können.
Durch Datenverfälschung oder -verlust verursachte Fehler
Aus vielerlei Gründen ist die MySQL-Replikation nicht besonders belastbar, wenn es zu
Abstürzen, Stromausfällen und Beschädigungen durch Festplatten-, Speicher- oder Netzwerkfehler kommt. Sie müssen mit hoher Sicherheit irgendwann einmal die Replikation
aufgrund dieser Probleme neu starten.
Die meisten Probleme mit der Replikation nach einem unerwarteten Herunterfahren
stammen von einem der Server, der seine Daten nicht mehr auf die Festplatte zurückspeichern konnte. Rechnen Sie mit folgenden Dingen:
Replikationsprobleme und Lösungen | 421
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
aus Sicherheitsgründen für den Fall eines Neustarts die Option read_only in seiner
Konfigurationsdatei. Bedenken Sie, dass Benutzer mit der SUPER-Berechtigung immer
noch Änderungen vornehmen könnten. Falls Sie Änderungen von allen Benutzern
verhindern wollen, verwenden Sie FLUSH TABLES WITH READ LOCK. Tun Sie dies nicht,
müssen Sie alle Clientverbindungen beenden, damit es wirklich keine lange laufenden Anweisungen oder unbestätigten Transaktionen gibt.
Zusätzlich zu den Datenverlusten, die daher rühren, dass MySQL unsauber beendet
wurde, werden oft auch die Binärlogs oder Relay-Logs auf der Festplatte beschädigt. Dies
sind einige der häufiger auftretenden Szenarien:
Binärlogs auf dem Master sind beschädigt
Wenn das Binärlog auf dem Master beschädigt ist, haben Sie keine andere Wahl, als
zu versuchen, den beschädigten Teil zu überspringen. Sie können auf dem Master
FLUSH LOGS ausführen, damit er eine neue Log-Datei anfängt, und den Slave auf den
Anfang des neuen Logs richten. Oder Sie versuchen, das Ende des beschädigten
Bereichs zu finden. Manchmal können Sie mit SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1
ein einzelnes beschädigtes Event überspringen. Wenn es mehr als ein beschädigtes
Event gibt, wiederholen Sie den Vorgang, bis Sie alle übersprungen haben.
422 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Unerwartetes Herunterfahren des Masters
Wenn der Master nicht mit sync_binlog konfiguriert wurde, hat er vor dem Absturz
möglicherweise seine letzten paar Binärlog-Events nicht auf die Festplatte übertragen. Der Ein-/Ausgabe-Thread des Slaves war möglicherweise gerade dabei, ein
Event einzulesen, das es nie auf die Festplatte geschafft hat. Wenn der Master neu
startet, baut der Slave wieder eine Verbindung auf und versucht, dieses Event erneut
zu lesen. Der Master antwortet nun jedoch, dass es kein solches Binlog-Offset gibt.
Der Binlog-Dump-Prozess geht typischerweise fast sofort los, so dass dies nicht
ungewöhnlich ist.
Die Lösung dieses Problem sieht so aus, dass der Slave angewiesen wird, mit dem
Lesen am Anfang des nächsten Binärlogs zu beginnen. Manche Log-Events werden
allerdings für immer verloren sein. Das hätte man vermeiden können, wenn der
Master mit sync_binlog konfiguriert worden wäre.
Doch auch wenn Sie sync_binlog konfiguriert haben, können MyISAM-Daten bei
einem Absturz beschädigt werden, genau wie InnoDB-Daten, wenn innodb_flush_
logs_at_trx_commit nicht auf 1 gesetzt ist.
Unerwartetes Herunterfahren des Slaves
Wenn der Slave nach einem unerwarteten Herunterfahren wieder startet, liest er
seine master.info-Datei, um festzustellen, wo er die Replikation gestoppt hat. Leider
wird diese Datei nicht auf die Festplatte synchronisiert, so dass die Informationen,
die sie enthält, wahrscheinlich falsch sind. Der Slave versucht wahrscheinlich, einige
Binärlog-Events erneut auszuführen. Das könnte einige einmalige Indexstörungen
verursachen. Solange Sie nicht feststellen, wo der Slave wirklich angehalten hat, was
unwahrscheinlich ist, haben Sie keine andere Wahl, als die resultierenden Fehler zu
überspringen. Dabei kann Ihnen das in Maatkit enthaltene mk-slave-restart-Werkzeug helfen.
Falls Sie alle InnoDB-Tabellen verwenden, können Sie nach dem Neustart des Slaves in das MySQL-Fehler-Log schauen. Der InnoDB-Wiederherstellungsprozess gibt
die Binärlog-Koordinaten bis zu der Stelle an, ab der wiederhergestellt wird; Sie können mit ihrer Hilfe dann feststellen, wohin der Slave auf dem Master verweisen
muss.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Es hängt von der Art der Beschädigung des Binärlogs ab, wie viele Daten Sie wiederherstellen können. Es können verschiedene Arten auftreten:
Bytes sind geändert, aber das Event ist immer noch gültiges SQL
Leider kann MySQL diese Art der Beschädigung gar nicht erkennen. Aus diesem
Grund ist es keine schlechte Idee, wenn man regelmäßig überprüft, ob Ihre Slaves
die richtigen Daten enthalten.
Bytes sind geändert, und das Event ist ungültiges SQL
Wahrscheinlich können Sie das Event mit mysqlbinlog extrahieren und sich die verstümmelten Daten anschauen:
UPDATE tbl SET col?????????????????
Versuchen Sie, den Anfang des nächsten Events zu finden und es auszugeben. Dazu
addieren Sie den Offset und die Länge. Vielleicht können Sie dieses Event einfach
überspringen.
Bytes wurden weggelassen, und/oder die Länge des Events ist falsch
In diesem Fall bricht mysqlbinlog manchmal mit einem Fehler ab oder stürzt ab,
weil es das Event nicht lesen und den Anfang des nächsten Events nicht finden
kann.
Mehrere Events sind beschädigt oder wurden überschrieben, oder Offsets haben sich verschoben, und das nächste Event beginnt bei einem falschen Offset
Auch hier nützt Ihnen mysqlbinlog nicht viel.
Wenn die Beschädigung so schlimm ist, dass mysqlbinlog die Log-Events nicht lesen
kann, müssen Sie auf Hex-Editing oder andere seltsame Techniken zurückgreifen, um die
Grenzen zwischen den Log-Events zu finden. Das ist normalerweise gar nicht so schwer,
weil die Events durch deutlich erkennbare Markierungen getrennt werden.
Hier ist ein Beispiel. Wir wollen uns zuerst die Offsets eines Log-Events aus einem Beispiel-Log anschauen, das mysqlbinlog ausgegeben hat:
$ mysqlbinlog mysql-bin.000113 | egrep '^# at '
# at 4
# at 98
Replikationsprobleme und Lösungen | 423
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Relay-Logs auf dem Slave sind beschädigt
Wenn die Binärlogs auf dem Master intakt sind, können Sie die beschädigten RelayLogs mit CHANGE MASTER TO verwerfen und sie neu holen. Verweisen Sie den Slave einfach an die gleiche Position, von der er momentan repliziert (Relay_Master_Log_
File/Exec_Master_Log_Pos). Dadurch verwirft er alle Relay-Logs auf der Festplatte.
Das Binärlog ist nicht mehr synchron zum InnoDB-Transaktions-Log
Stürzt der Master ab, könnte InnoDB eine Transaktion als bestätigt aufzeichnen,
obwohl sie gar nicht in das Binärlog auf der Festplatte geschrieben wurde. Es gibt
keine Möglichkeit, die fehlende Transaktion wiederherzustellen, es sei denn, sie
befindet sich im Relay-Log eines Slaves. Sie vermeiden diesen Fehler mit dem
sync_binlog-Parameter in MySQL 5.0 oder den Parametern sync_binlog und
safe_binlog in MySQL 4.1.
#
#
#
#
at
at
at
at
185
277
369
447
$ strings -n 2 -t d mysql-bin.000113
1 binpC'G
25 5.0.38-Ubuntu_0ubuntu1.1-log
99 C'G
146 std
156 test
161 create table test(a int)
186 C'G
233 std
243 test
248 insert into test(a) values(1)
278 C'G
325 std
335 test
340 insert into test(a) values(2)
370 C'G
417 std
427 test
432 drop table test
448 D'G
474 mysql-bin.000114
Es gibt ein gut erkennbares Muster, das es Ihnen erlauben sollte, die Anfänge der Events
zu finden. Beachten Sie, dass die Strings, die mit 'G enden, sich ein Byte hinter dem
Anfang des Log-Events befinden. Sie gehören zu dem Log-Event-Header, der eine feste
Länge besitzt.
Der exakte Wert variiert von Server zu Server, Ihre Ergebnisse hängen also vom Server ab,
dessen Log Sie untersuchen. Mit ein bisschen Herumsuchen sollten Sie in der Lage sein,
das Muster in Ihrem Binärlog zu finden und den Offset des nächsten intakten Log-Events
zu ermitteln. Sie können dann versuchen, mit dem Argument --start-position für mysqlbinlog hinter das schlechte Event bzw. die schlechten Events zu springen. Oder Sie benutzen den Parameter MASTER_LOG_POS für CHANGE MASTER TO.
Nichttransaktionsfähige Tabellen verwenden
Wenn alles gut geht, funktioniert die anweisungsbasierte Replikation normalerweise gut
mit nichttransaktionsfähigen Tabellen. Tritt jedoch ein Fehler bei der Aktualisierung
einer nichttransaktionsfähigen Tabelle auf (wird etwa eine Anweisung abgebrochen,
bevor sie vollständig ausgeführt wurde), dann kommt es auf dem Master und dem Slave
zu unterschiedlichen Daten.
424 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Sie finden die Offsets in dem Log, indem Sie die Offsets mit der Ausgabe des folgenden
strings-Befehls vergleichen:
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Wenn Sie MyISAM-Tabellen einsetzen, dann führen Sie auf jeden Fall STOP SLAVE aus,
bevor Sie den MySQL-Server stoppen, da ansonsten alle laufenden Abfragen abgebrochen werden (einschließlich unvollständiger Aktualisierungsanweisungen). Transaktionsfähige Storage-Engines haben dieses Problem nicht. Bei transaktionsfähigen
Tabellen wird eine fehlgeschlagene Aktualisierung auf dem Master zurückgenommen
und nicht im Binärlog verzeichnet.
Transaktionsfähige und nichttransaktionsfähige Tabellen mischen
Wenn Sie eine transaktionsfähige Storage-Engine benutzen, dann schreibt MySQL die
Anweisungen, die Sie ausführen, erst dann in das Binärlog, wenn die Transaktionen
bestätigt wurden. Das heißt, wenn eine Transaktion zurückgenommen wird, zeichnet
MySQL die Anweisungen nicht auf, sie werden also auch nicht auf dem Slave abgespielt.
Falls Sie jedoch transaktionsfähige und nichttransaktionsfähige Tabellen mischen und es zu
einem Rollback kommt, dann kann MySQL die Änderungen an den transaktionsfähigen
Tabellen zurücknehmen; die nichttransaktionsfähigen Tabellen dagegen werden dauerhaft
verändert. Solange keine Fehler auftreten, indem etwa eine Aktualisierung auf halbem
Wege abgebrochen wird, stellt das kein Problem dar: Anstatt die Anweisungen nicht zu protokollieren, schreibt MySQL zuerst die Anweisungen in sein Binärlog und anschließend
eine ROLLBACK-Anweisung. In der Folge werden auf dem Slave die gleichen Anweisungen
ausgeführt, und alles ist gut. Das ist nicht ganz so effizient, weil der Slave auch etwas tun
muss, theoretisch jedoch bleibt der Slave weiterhin synchron mit dem Master.
So weit, so gut. Problematisch wird es, wenn es auf dem Slave ein Deadlock gibt, das auf
dem Master nicht aufgetreten ist. Für die Tabellen, die eine transaktionsfähige StorageEngine benutzen, gibt es auf dem Slave ein Rollback, für die nichttransaktionsfähigen
Tabellen ist das aber nicht möglich. Es kommt dazu, dass die Daten des Slaves sich von
denen des Masters unterscheiden.
Sie können dieses Problem nur verhindern, indem Sie das Mischen transaktionsfähiger
und nichttransaktionsfähiger Tabellen vermeiden. Falls Sie das Problem bemerken, dann
haben Sie nur die Möglichkeit, den Fehler auf dem Slave zu überspringen und die beteiligten Tabellen neu zu synchronisieren.
Im Prinzip sollte dieses Problem bei der zeilenbasierten Replikation nicht auftreten. Bei der
zeilenbasierten Replikation werden Änderungen an den Zeilen aufgezeichnet, nicht an den
SQL-Anweisungen. Wenn eine Anweisung Zeilen in einer MyISAM-Tabelle und einer
Replikationsprobleme und Lösungen | 425
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Nehmen Sie z.B. an, Sie aktualisieren eine MyISAM-Tabelle mit 100 Zeilen. Was
geschieht, wenn die Anweisung 50 der Zeilen aktualisiert und jemand sie dann abbricht?
Die eine Hälfte der Zeilen wurde geändert, die andere hingegen nicht. Als Ergebnis muss
die Replikation aus dem Takt geraten, weil die Anweisung auf dem Slave erneut abgespielt wird und alle 100 Zeilen ändert. (MySQL bemerkt dann, dass die Anweisung auf
dem Master einen Fehler verursacht hat, auf dem Slave aber nicht, und stoppt die Replikation mit einer Fehlermeldung.)
Nichtdeterministische Anweisungen
Jede Anweisung, die Daten auf nichtdeterministische Weise ändert, kann dafür sorgen,
dass die Daten eines Slaves sich von denen seines Masters unterscheiden. Zum Beispiel
hängt ein UPDATE mit einem LIMIT von der Reihenfolge ab, in der die Anweisung die Zeilen
in der Tabelle findet. Solange die Reihenfolge auf dem Master und dem Slave nicht garantiert gleich ist – indem z.B. die Zeilen nach dem Primärschlüssel sortiert sind –, könnte
die Anweisung unterschiedliche Zeilen auf diesen beiden Servern ändern. Solche Probleme sind unter Umständen subtil und schwer zu bemerken, weshalb manchmal die
Regel gilt, dass LIMIT nie mit einer Anweisung benutzt werden darf, die Daten ändert.
Achten Sie außerdem auf Anweisungen, die INFORMATION_SCHEMA-Tabellen einbeziehen.
Diese können sich zwischen Master und Slave unterscheiden, so dass auch die Ergebnisse
unterschiedlich sind. Denken Sie schließlich noch daran, dass die meisten Servervariablen, wie etwa @@server_id und @@hostname in Versionen vor MySQL 5.1 nicht korrekt repliziert werden.
Die zeilenbasierte Replikation unterliegt nicht diesen Beschränkungen.
Unterschiedliche Storage-Engines auf Master und Slave
Wie wir in diesem Kapitel schon angemerkt haben, ist es oft praktisch, wenn man auf
einem Slave andere Storage-Engines benutzt. Unter gewissen Umständen erzeugt allerdings die anweisungsbasierte Replikation auf einem Slave mit anderen Storage-Engines
unterschiedliche Ergebnisse. Beispielsweise verursachen nichtdeterministische Anweisungen (wie die im vorherigen Abschnitt erwähnten) mit größerer Wahrscheinlichkeit
Probleme, wenn sich die Storage-Engines auf dem Slave unterscheiden.
Falls Sie feststellen, dass die Daten Ihres Slaves in bestimmten Tabellen nicht mit denjenigen Ihres Masters übereinstimmen, dann sollten Sie die Storage-Engines untersuchen,
die auf beiden Servern benutzt werden, sowie die Abfragen, die diese Tabellen aktualisieren.
426 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
InnoDB-Tabelle ändert, es dann auf dem Master zu einem Deadlock kommt und die
InnoDB-Tabelle wieder zurückgeändert wird, werden die Änderungen an der MyISAMTabelle dennoch im Binärlog aufgezeichnet und auf dem Slave abgespielt. Wir haben einfache Fälle getestet und festgestellt, dass dies korrekt funktioniert; allerdings hatten wir zu
dem Zeitpunkt, als dieses Buch entstand, noch nicht genügend Erfahrungen mit der zeilenbasierten Replikation, um sicher sagen zu können, ob Probleme komplett vermieden werden, die durch das Mischen transaktionsfähiger und nichttransaktionsfähiger Tabellen
auftreten können.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Datenänderungen auf dem Slave
mysql> INSERT INTO table1 SELECT * FROM table2;
Wenn table2 auf dem Slave andere Daten enthält, bekommt table1 ebenfalls unterschiedliche Daten. Mit anderen Worten: Datenunterschiede pflegen sich von Tabelle zu
Tabelle auszubreiten. Das passiert mit allen Arten von Abfragen, nicht nur mit INSERT ...
SELECT-Abfragen. Es gibt zwei mögliche Folgen: Sie erhalten einen Fehler wie eine doppelte Indexverletzung, oder Sie bekommen überhaupt keinen Fehler. Seien Sie froh,
wenn Sie einen Fehler erhalten, weil Sie damit wenigstens alarmiert werden, dass Ihre
Daten auf dem Slave nicht gleich sind. Bleiben unterschiedliche Daten unentdeckt, können sie insgeheim alle möglichen Schäden anrichten.
Die einzige Lösung für dieses Problem besteht darin, die Daten neu vom Master zu synchronisieren.
Nichteindeutige Server-IDs
Dies gehört zu den schwerer fassbaren Problemen, die bei der Replikation auftreten können. Falls Sie versehentlich zwei Slaves mit derselben Server-ID konfigurieren, scheinen sie
auf den ersten Blick gut zu funktionieren. Schauen Sie sich jedoch deren Fehler-Logs an
oder beobachten Sie den Master mit innotop, werden Ihnen eigenartige Dinge auffallen.
Auf dem Master sehen Sie, dass immer nur einer der beiden Slaves verbunden ist. (Normalerweise besteht zu allen Slaves eine Verbindung, so dass sie replizieren können.) Auf
dem Slave finden Sie im Fehler-Log viele Fehlermeldungen über das Trennen und erneute
Aufbauen von Verbindungen, aber keinen Hinweis auf eine fehlkonfigurierte Server-ID.
Je nach der verwendeten MySQL-Version replizieren die Slaves korrekt, aber langsam.
Vielleicht replizieren sie aber auch gar nicht korrekt, sondern verpassen Binärlog-Events
oder wiederholen sie fälschlicherweise, wodurch Fehler mit duplizierten Schlüsseln (oder
Datenverfälschungen) auftreten. Es kann auch zu Abstürzen oder beschädigten Daten
auf dem Master selbst kommen, weil die Slaves, die gegeneinander kämpfen, eine
erhöhte Last verursachen. Und wenn die Slaves einander sehr stark bekämpfen, können
die Fehler-Logs in kurzer Zeit sehr stark anwachsen.
Um diese Probleme zu vermeiden, kommen Sie nicht umhin, beim Einrichten der Slaves
sehr sorgfältig vorzugehen. Möglicherweise hilft es Ihnen, eine Liste mit Slave-zu-ServerID-Zuordnungen anzulegen, damit Sie nicht den Überblick darüber verlieren, welche ID
zu einem Slave gehört.12 Falls sich Ihre Slaves alle in einem Teilnetz Ihres Netzwerks
12 Vielleicht wollen Sie sie in einer Datenbanktabelle speichern? Wir scherzen … aber nicht nur: Sie können in
der ID-Spalte einen eindeutigen Index hinzufügen.
Replikationsprobleme und Lösungen | 427
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Die anweisungsbasierte Replikation ist darauf angewiesen, dass der Slave die gleichen
Daten enthält wie der Master. Sie dürfen daher Änderungen auf dem Slave weder erlauben noch vornehmen (mit der Konfigurationsvariablen read_only können Sie dieses Ziel
durchsetzen). Schauen Sie sich die folgende Anweisung an:
befinden, können Sie eindeutige IDs wählen, indem Sie nur das letzte Oktett der IPAdressen der einzelnen Maschinen nutzen.
Undefinierte Server-IDs
mysql> START SLAVE;
ERROR 1200 (HY000): The server is not configured as slave; fix in config file or with CHA
NGE MASTER TO
Dieser Fehler ist besonders verwirrend, weil Sie gerade CHANGE MASTER TO benutzt und Ihre
Einstellungen mit SHOW SLAVE STATUS verifiziert haben. Sie erhalten möglicherweise einen
Wert von SELECT @@server_id, aber das ist nur ein Vorgabewert. Sie müssen den Wert
explizit setzen.
Abhängigkeiten von nichtreplizierten Daten
Haben Sie auf dem Master Datenbanken oder Tabellen, die nicht auf dem Slave existieren, dann ist es ziemlich einfach, die Replikation absichtlich zu unterbrechen. Nehmen
Sie an, dass es eine scratch-Datenbank auf dem Master gibt, die auf dem Slave nicht vorliegt. Beziehen sich irgendwelche Datenaktualisierungen auf dem Master auf eine Tabelle
in dieser Datenbank, dann wird die Replikation abgebrochen, wenn der Slave versucht,
die Aktualisierungen abzuspielen.
Man kann dieses Problem nicht umgehen. Sie können höchstens auf dem Master das
Anlegen von Tabellen vermeiden, die auf dem Slave nicht existieren.
Wie wird eine solche Tabelle erzeugt? Es gibt viele Möglichkeiten, von denen sich einige
schwerer vermeiden lassen als andere. Nehmen Sie z.B. an, dass Sie eine scratch-Datenbank auf dem Slave erzeugt haben, die auf dem Master nicht vorhanden war, und dann
aus irgendeinem Grund Master und Slave vertauscht haben. Vielleicht haben Sie in diesem Fall vergessen, die scratch-Datenbank und ihre Berechtigungen zu entfernen. Jetzt
könnte jemand eine Verbindung zu dem neuen Master herstellen und eine Abfrage in dieser Datenbank ausführen, oder ein regelmäßig ablaufender Job entdeckt die Tabellen
und führt in ihnen jeweils OPTIMIZE TABLE aus.
Daran müssen Sie unter anderem denken, wenn Sie einen Slave zum Master befördern
oder wenn Sie entscheiden, wie die Slaves konfiguriert werden sollen. Alles, was die
Slaves anders macht als die Master oder umgekehrt, könnte künftig zu einem Problem
werden.
Die zeilenbasierte Replikation sollte einige dieser Probleme lösen, allerdings ist es noch
zu früh, um sich sicher zu sein.
428 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Falls Sie die Server-ID nicht in der my.cnf-Datei definieren, scheint MySQL die Replikation mit CHANGE MASTER TO einzurichten, erlaubt Ihnen aber nicht, den Slave zu starten:
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Fehlende temporäre Tabellen
Es gibt keine sichere Methode, um temporäre Tabellen auf dem Master zusammen mit
anweisungsbasierter Replikation zu benutzen. Viele Leute mögen die temporären Tabellen, so dass sie vermutlich schwer davon zu überzeugen sind, aber es stimmt. Egal, wie
kurz sie existieren, temporäre Tabellen machen es potenziell unmöglich, Slaves zu stoppen und zu starten und sie nach Abstürzen wiederherzustellen. Das gilt sogar dann, wenn
Sie sie nur innerhalb einer einzigen Transaktion benutzen. (Es ist etwas weniger problematisch, temporäre Tabellen auf einem Slave einzusetzen, wo sie sehr bequem sein können; ist der Slave aber selbst ein Master, dann existiert das Problem weiterhin.)
Falls die Replikation stoppt, weil der Slave eine temporäre Tabelle nach einem Neustart
nicht finden kann, gibt es wirklich nur wenig, was Sie tun können. Überspringen Sie die
auftretenden Fehler, oder legen Sie manuell eine Tabelle mit dem gleichen Namen und
der gleichen Struktur wie die verschwundene Tabelle an. Wie auch immer Sie vorgehen,
Ihre Daten werden auf dem Slave wahrscheinlich anders aussehen, wenn Schreibabfragen
sich auf die temporäre Tabelle beziehen.
Es ist nicht so schwer, wie es scheint, temporäre Tabellen zu eliminieren. Die beiden
nützlichsten Eigenschaften einer temporären Tabelle sind folgende:
• Sie sind nur für die Verbindung sichtbar, die sie erzeugt hat, kommen also nicht den
temporären Tabellen anderer Verbindungen in die Quere, die denselben Namen tragen.
• Sie verschwinden, wenn die Verbindung geschlossen wird. Sie müssen sie also nicht
explizit entfernen.
Sie können diese Eigenschaften leicht emulieren, indem Sie eine Datenbank exklusiv für
pseudotemporäre Tabellen reservieren, wo Sie stattdessen permanente Tabellen anlegen.
Sie müssen nur eindeutige Namen für sie wählen. Zum Glück geht das ganz leicht: Hängen
Sie einfach die Verbindungs-ID an den Tabellennamen an. Wo Sie z.B. CREATE TEMPORARY
TABLE top_users(...) ausgeführt haben, führen Sie nun CREATE TABLE temp.top_users_
1234(...) aus, wobei 1234 der Wert ist, der von CONNECTION_ID( ) zurückgeliefert wird.
Nachdem Ihre Anwendung mit der pseudotemporären Tabelle fertig ist, können Sie sie entweder wegwerfen oder sie von einem Aufräumprozess entfernen lassen. Da die Verbindungs-ID im Namen steht, kann man leicht feststellen, welche Tabellen nicht mehr in
Benutzung sind – Sie erhalten eine Liste der aktiven Verbindungen mit SHOW PROCESSLIST und
müssen sie nur mit den Verbindungs-IDs in den Tabellennamen vergleichen.13
13 mk-find – noch ein weiteres Werkzeug in Maatkit – kann pseudotemporäre Tabellen leicht mit den Optionen
--pid und --sid entfernen.
Replikationsprobleme und Lösungen | 429
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Für manche Einsatzzwecke sind temporäre Tabellen ganz praktisch, allerdings sind sie
leider inkompatibel zur anweisungsbasierten Replikation. Wenn ein Slave abstürzt oder
wenn Sie ihn herunterfahren, dann verschwinden alle temporären Tabellen, die der
Slave-Thread benutzt. Nach einem Neustart des Slaves schlagen alle weiteren Anweisungen fehl, die sich auf die fehlenden temporären Tabellen beziehen.
Die Verwendung von echten Tabellen anstelle von temporären Tabellen hat noch andere
Vorteile. Zum Beispiel lassen sich damit leichter Fehler in Ihren Anwendungen aufspüren, weil Sie die Daten sehen können, die die Anwendungen von einer anderen Verbindung aus manipulieren. Mit einer temporären Tabelle wäre das nicht so einfach möglich.
Falls Sie temporäre Tabellen einsetzen, müssen Sie sicherstellen, dass die Statusvariable
Slave_open_temp_tables 0 ist, bevor sie einen Slave herunterfahren. Wenn sie nicht 0 ist,
bekommen Sie wahrscheinlich Probleme damit, den Slave neu zu starten. Das richtige
Vorgehen besteht darin, STOP SLAVE auszuführen, die Variable zu untersuchen und erst
dann den Slave herunterzufahren. Wenn Sie die Variable untersuchen, bevor Sie die
Slave-Prozesse stoppen, riskieren Sie eine Race-Condition.
Es werden nicht alle Updates repliziert
Falls Sie SET SQL_LOG_BIN=0 missbrauchen oder die Replikationsfilterregeln nicht verstehen, ignoriert Ihr Slave möglicherweise Aktualisierungen, die auf dem Master stattgefunden haben. Manchmal wollen Sie das zu Archivierungszwecken, normalerweise jedoch
geschieht das versehentlich und hat schlimme Folgen.
Nehmen Sie z.B. an, dass Sie eine replicate_do_db-Regel haben, um nur die sakilaDatenbank auf einen Ihrer Slaves zu replizieren. Wenn Sie die folgenden Befehle auf dem
Master ausführen, werden die Daten des Slaves anders als die Daten auf dem Master:
mysql> USE test;
mysql> UPDATE sakila.actor ...
Andere Arten von Anweisungen können aufgrund von nichtreplizierten Abhängigkeiten
sogar dafür sorgen, dass eine Replikation mit einem Fehler fehlschlägt.
Lock-Contention aufgrund von sperrenden InnoDB-Selects
Die InnoDB-SELECT-Anweisungen sind normalerweise nichtsperrend, besorgen sich aber
in bestimmten Fällen Sperren. Speziell INSERT ... SELECT sperrt standardmäßig alle Zeilen, aus denen es in der Quelltabelle liest. MySQL braucht die Sperren um sicherzustellen, dass die Anweisungen beim Ausführen auf dem Slave das gleiche Ergebnis erzeugen.
Im Prinzip serialisieren die Sperren die Anweisung auf dem Master, was der Art und
Weise entspricht, wie der Slave sie ausführt.
Ihnen könnten aufgrund dieses Designs Lock-Contention, Blockaden und Timeouts
infolge des Wartens auf Sperren begegnen. Um diese Probleme zu mildern, sollte man
eine Transaktion nicht länger offen halten als nötig, damit die Sperren weniger Blockaden verursachen. Sie können die Sperren freigeben, indem Sie die Transaktion so bald
wie möglich auf dem Master bestätigen.
430 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Echte Tabellen bringen jedoch einen gewissen Overhead mit, den Sie bei temporären
Tabellen nicht haben: Es geht langsamer, sie zu erzeugen, weil die .frm-Dateien, die mit
diesen Tabellen verknüpft sind, auf die Festplatte synchronisiert werden müssen. Sie können die sync_frm-Option deaktivieren, um das zu beschleunigen, aber das ist gefährlicher.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Es ist außerdem hilfreich, wenn die Anweisungen kurz gehalten werden, indem man
große Anweisungen in kleinere unterteilt. Das ist sehr effektiv, um Lock-Contention zu
reduzieren. Es lohnt sich meist, auch wenn es nicht leicht durchzuführen ist.
Sie sind vielleicht versucht, die Sperren zu deaktivieren, anstatt eine der genannten
Lösungen einzusetzen. Es gibt zwar eine Methode, um das zu erreichen, es ist aber meist
keine gute Idee, weil dadurch der Slave stillschweigend hinter den Master zurückfallen
könnte. Außerdem wird dadurch das Binärlog nutzlos für die Wiederherstellung eines
Servers. Falls Sie jedoch beschließen, dass die Vorteile die Risiken aufwiegen, wird die
Konfigurationsänderung folgendermaßen erreicht:
innodb_locks_unsafe_for_binlog = 1
Dadurch können die Ergebnisse einer Anweisung von Daten abhängen, die sie nicht
sperrt. Wenn eine zweite Anweisung die Daten modifiziert und sie vor der ersten Anweisung bestätigt, dann kann es passieren, dass die beiden Anweisungen beim Abspielen des
Binärlogs nicht dieselben Ergebnisse erzeugen. Das gilt sowohl für die Replikation als
auch für die punktgenaue Wiederherstellung.
Um einmal zu sehen, wie durch das Sperren von Leseoperationen Chaos vermieden wird,
stellen Sie sich vor, dass Sie zwei Tabellen haben: eine ohne Zeilen und eine, deren einzige Zeile den Wert 99 enthält. Die Daten werden durch zwei Transaktionen aktualisiert.
Transaktion 1 fügt den Inhalt der zweiten Tabelle in die erste Tabelle ein, und Transaktion 2 aktualisiert die zweite (Quell-)Tabelle, wie in Abbildung 8-16 gezeigt ist.
Schritt 2 in dieser Folge von Ereignissen ist sehr wichtig. Darin versucht Transaktion 2,
die Quelltabelle zu aktualisieren, was es nötig macht, eine exklusive (Schreib-)Sperre auf
die Zeilen zu legen, die aktualisiert werden sollen. Eine exklusive Sperre ist inkompatibel
zu jeder anderen Sperre, einschließlich des Shared Lock, das Transaktion 1 auf diese
Zeile gelegt hat, so dass Transaktion 2 gezwungen ist zu warten, bis Transaktion 1 bestätigt wird. Die Transaktionen werden im Binärlog in der Reihenfolge serialisiert, in der sie
bestätigt werden, so dass sich beim erneuten Abspielen dieser Transaktionen in der
Binärlog-(Commit-)Reihenfolge die gleichen Ergebnisse erzielen lassen.
Replikationsprobleme und Lösungen | 431
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Andere Lösungen bestehen darin, INSERT ... SELECT-Anweisungen durch eine Kombination aus SELECT INTO OUTFILE, gefolgt von LOAD DATA INFILE auf dem Master zu ersetzen.
Das geht schnell und erfordert keine Sperren. Zugegebenermaßen ist das ein Hack, der
aber dennoch manchmal hilft. Die größten Probleme sind die Wahl eines eindeutigen
Namens für die Ausgabedatei, die noch nicht existieren darf, und das Aufräumen der
Ausgabedatei, wenn Sie damit fertig sind. Sie können die CONNECTION_ID( )-Technik einsetzen, die wir in »Fehlende temporäre Tabellen« auf Seite 429 besprochen haben, um
sicherzustellen, dass der Dateiname eindeutig ist, und Sie können einen regelmäßig ausgeführten Job benutzen (crontab unter Unix, GEPLANTE TASKS unter Windows), um
ungenutzte Ausgabedateien aufzuräumen, nachdem die Verbindungen, die sie erzeugt
haben, mit ihnen fertig sind.
Tbl1
0 Ausgangszustand
2 Txn 2
UPDATE
der Blöcke mit einem
exklusiven Lock
3 Txn 1 wird bestätigt
und gibt Sperren frei
4 Txn 2 fährt fort
und wird bestätigt
Binlog
99
99
99
SET = 100
99
99
99
SET = 100
99
99
Txn 1
99 100
Txn 1
Txn 2
Abbildung 8-16: Zwei Transaktionen aktualisieren Daten; mittels gemeinsam genutzter Sperren
(Shared Lock) wird die Aktualisierung serialisiert.
Falls andererseits Transaktion 1 kein Shared Lock auf die Zeilen legt, die es für das INSERT
liest, gibt es keine solche Garantie. Betrachten Sie Abbildung 8-17, in der eine mögliche
Folge von Ereignissen ohne das Lock zu sehen ist.
Ohne Sperren werden die Transaktionen in einer Reihenfolge in das Binärlog geschrieben, die andere Ergebnisse erzeugt, wenn dieses Log erneut abgespielt wird, wie Sie in
der Abbildung erkennen. MySQL zeichnet Transaktion 2 zuerst auf, so dass die Ergebnisse von Transaktion 1 auf dem Slave beeinflusst werden. Auf dem Master ist das nicht
passiert. In der Folge enthält der Slave andere Daten als der Master.
Wir raten Ihnen dringend, in den meisten Fällen die Konfigurationsvariable innodb_
locks_unsafe_for_binlog auf 0 gesetzt zu lassen.
In einer Master-Master-Replikation auf beide Master schreiben
Auf beide Master zu schreiben, ist im Allgemeinen keine gute Idee. Falls Sie versuchen,
sicher auf beide Master gleichzeitig zu schreiben, dann gibt es für einige der Probleme
Lösungen, für andere jedoch nicht.
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
1 Txn 1
INSERT/SELECT
mit einem Shared Lock
Tbl2
In MySQL 5.0 gibt es zwei Server-Konfigurationsvariablen, mit denen man dem Problem
der widersprüchlichen AUTO_INCREMENT-Primärschlüssel begegnen kann. Diese Variablen
432 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Tbl1
1 Txn 1
INSERT/SELECT
ohne Locking
3 Txn 1 wird bestätigt
99
99
SET = 100
99 100
Txn 2
100
Txn 2
99
99
Txn 1
Später,
auf dem Slave...
1 Txn 2
UPDATE
2 Txn 1
INSERT/SELECT
Binlog
SET = 100
99 100
100
100
Abbildung 8-17: Zwei Transaktionen aktualisieren Daten, allerdings ohne dass ein Shared Lock die
Aktualisierungen serialisiert.
sind auto_increment_increment und auto_increment_offset. Mit ihnen können Sie die
Zahlen, die die Server generieren, »staffeln«, so dass sie sich verschachteln und nicht miteinander kollidieren.
Das löst jedoch nicht alle Probleme, die mit zwei schreibbaren Mastern auftreten. Es löst
nur das Autoinkrement-Problem, das wahrscheinlich nur einen kleinen Teil der widersprüchlichen Schreiboperationen ausmacht, mit denen Sie es zu tun bekommen könnten.
Um genau zu sein, werden dadurch mehrere neue Probleme eingeführt:
• Dieses Verfahren erschwert es, Server in der Replikationstopologie zu verschieben.
• Es verschwendet Schlüsselplatz, indem potenziell Lücken zwischen den Zahlen eingeführt werden.
• Es hilft nur, wenn alle Ihre Tabellen AUTO_INCREMENT-Primärschlüssel besitzen, und
dabei ist es nicht unbedingt eine gute Idee, AUTO_INCREMENT-Primärschlüssel allgemein einzusetzen.
Sie können eigene, nicht widersprüchliche Primärschlüsselwerte generieren. Eine Möglichkeit wäre, einen mehrspaltigen Primärschlüssel zu erzeugen und die Server-ID für die
erste Spalte zu benutzen. Das funktioniert gut, vergrößert allerdings die Primärschlüssel,
was eine schlimme Wirkung auf die Sekundärschlüssel in InnoDB hat.
Replikationsprobleme und Lösungen | 433
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
2 Txn 2 macht
weiter und wird
bestätigt
Tbl2
Es ist auch möglich, einen einspaltigen Primärschlüssel einzusetzen und die »hohen Bits«
des Integers für die Server-ID zu nehmen. Das erreichen Sie durch eine einfache Linksverschiebung (oder Multiplikation) und Addition. Falls Sie z.B. die 8 höchstwertigen Bits
einer vorzeichenlosen BIGINT-(64-Bit-)Spalte benutzen, um die Server-ID aufzunehmen,
können Sie den Wert 11 auf Server 15 folgendermaßen einfügen:
Wenn Sie das Ergebnis in die Basis 2 konvertieren und es auf 64 Bit Länge auffüllen, ist
der Effekt besser zu erkennen:
mysql> SELECT LPAD(CONV(pk_col, 10, 2), 64, '0') FROM test;
+------------------------------------------------------------------+
| LPAD(CONV(pk_col, 10, 2), 64, '0')
|
+------------------------------------------------------------------+
| 0000111100000000000000000000000000000000000000000000000000001011 |
+------------------------------------------------------------------+
Das Problem bei dieser Methode besteht darin, dass Sie eine externe Möglichkeit benötigen, um die Schlüsselwerte zu generieren, weil AUTO_INCREMENT das nicht für Sie erledigen
kann. Benutzen Sie nicht @@server_id anstelle der Konstante 15 in dem INSERT, da Sie
ansonsten ein anderes Ergebnis auf dem Slave erhalten.
Sie können sich auch mit einer Funktion wie MD5( ) oder UUID( ) für pseudozufällige
Werte entscheiden, allerdings sind diese unter Umständen schlecht für die Performance –
sie sind groß, und sie sind prinzipiell zufällig, was speziell für InnoDB nicht so gut ist.
(Benutzen Sie UUID( ) nur dann, wenn Sie die Werte in der Anwendung generieren, weil
UUID( ) mit der anweisungsbasierten Replikation nicht korrekt repliziert wird.)
Es ist ein schwieriges Problem, und wir empfehlen im Normalfall, die Anwendung so
umzugestalten, dass man nur noch einen schreibbaren Master hat.
Übermäßiger Rückstand bei der Replikation
Ein Rückstand bei der Replikation ist ein häufig auftretendes Problem. Nichtsdestotrotz
ist es keine schlechte Idee, die Anwendungen so zu entwerfen, dass sie einen gewissen
Rückstand der Slaves tolerieren. Wenn das System mit verzögerten Slaves nicht funktionieren kann, dann ist die Replikation vermutlich nicht die richtige Architektur für Ihre
Anwendung. Sie können jedoch einige Schritte unternehmen, um den Slaves zu helfen,
mit dem Master Schritt zu halten.
Die Single-Thread-Natur der MySQL-Replikation bedeutet, dass sie auf dem Slave relativ
ineffizient ist. Selbst ein schneller Slave mit vielen Festplatten, CPUs und Speicher kann
ganz leicht hinter einem Master zurückfallen, weil der eine Thread des Slaves üblicherweise nur eine CPU und eine Festplatte effizient nutzt. Um genau zu sein, muss jeder
Slave typischerweise mindestens so leistungsfähig sein wie der Master.
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
mysql> INSERT INTO test(pk_col, ...) VALUES( (15 << 56) + 11, ...);
Auch Sperren auf dem Slave stellen ein Problem dar. Andere Abfragen, die auf einem
Slave laufen, könnten Sperren setzen, die den Replikations-Thread blockieren. Da die
434 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Replikation nur mit einem Thread erfolgt, könnte der Replikations-Thread keine weitere
Arbeit verrichten, während er wartet.
Leider gibt es momentan nur eine Möglichkeit, um festzustellen, wie dicht der Slave an
seine Kapazitätsgrenzen kommt: indem man empirische Beweise untersucht. Wenn Ihre
Last immer absolut gleichförmig wäre, würden Ihre Slaves bei 99 % Kapazität fast
genauso gut funktionieren wie bei 10 % Kapazität. Wenn sie 100 % Kapazität erreichen,
würden sie abrupt zurückfallen. In der Realität ist die Last kaum so stetig. Wenn also ein
Slave fast seine volle Schreibkapazität erreicht hat, würden Sie wahrscheinlich während
Lastspitzen eine erhöhte Replikationsverzögerung bemerken.
Das ist ein Warnsignal! Es bedeutet vermutlich, dass Sie gefährlich nahe daran sind, Ihre
Slaves überzubeanspruchen, so dass sie auch zwischen den eigentlichen Lastspitzen nicht
aufholen können. Ein seltsamer Test dafür, wie dicht Sie an der Grenze sind, besteht
darin den SQL-Thread eines Slaves absichtlich für eine Weile zu stoppen, ihn dann neu
zu starten und festzustellen, wie lange es dauert, bis er wieder aufgeholt hat.
Die Patches, die Google veröffentlicht hat (siehe »Synchrone MySQL-Replikation« auf
Seite 492), enthalten ebenfalls einen SHOW USER STATISTICS-Befehl, der die Busy_time des
Replikationsbenutzers zeigen kann. Dabei handelt es sich um den prozentualen Zeitanteil, den der Slave-Thread mit dem Verarbeiten von Abfragen verbracht hat – eine weitere
gute Methode, um die »Kopffreiheit« des Slave-SQL-Threads zu ermitteln.
Wenn Sie merken, dass Slaves nicht hinterherkommen, dann ist es am besten, die Abfragen auf einem Slave zu protokollieren und mit einem entsprechenden Analysewerkzeug
festzustellen, was da so langsam ist. Verlassen Sie sich bei dieser Frage nicht auf Ihren
Instinkt, und gehen Sie nicht davon aus, wie die Abfragen auf dem Master funktionieren,
da Slaves und Master ganz unterschiedliche Leistungsprofile aufweisen. Für diese Analyse aktivieren Sie am besten das Slow-Query-Log auf dem Slave. Das normale MySQLSlow-Query-Log zeichnet nicht die langsamen Abfragen auf, die der Slave-Thread ausführt, so dass Sie beim Replizieren nicht sehen können, welche Abfragen langsam sind.
Der Mikrosekunden-Patch löst dieses Problem. Mehr über das Slow-Query-Log und diesen Patch erfahren Sie in »MySQL-Profiling« auf Seite 68.
Es gibt nicht viel, was Sie auf einem Slave einstellen oder verändern können, der nicht
Schritt hält, abgesehen vom Erwerb schnellerer Festplatten und CPUs. Meist soll man auf
dem Slave Dinge deaktivieren, die zusätzliche Arbeit verursachen, und auf diese Weise
versuchen, die Last auf dem Slave zu verringern. Man könnte z.B. InnoDB so konfigurieren, dass es Änderungen weniger oft auf die Festplatte überträgt, damit Transaktionen
schneller bestätigt werden. Das erreichen Sie, indem Sie innodb_flush_log_at_trx_commit
auf 2 setzen. Sie können auch das Binär-Logging auf dem Slave deaktivieren,
innodb_locks_unsafe_for_binlog auf 1 und delay_key_write auf ALL für MyISAM setzen.
Replikationsprobleme und Lösungen | 435
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Meist fällt die Replikation auf zwei Arten zurück: mit Verzögerungspitzen, die in der
Folge aufgeholt werden, oder indem der Slave ständig hinterherbummelt. Die erste Art
wird üblicherweise von Abfragen verursacht, die schon lange laufen; die zweite Form
dagegen kann sogar dann auftauchen, wenn es keine langen Abfragen gibt.
Diese Einstellungen tauschen allerdings Sicherheit gegen Geschwindigkeit ein. Wenn Sie
einen Slave zum Master befördern, dann denken Sie daran, diese Einstellungen auf
sichere Werte zurückzusetzen.
Verdoppeln Sie den teuren Teil des Schreibens nicht
Betrachten wir ein Beispiel. Nehmen Sie an, Sie haben eine sehr große Tabelle, die Sie für
eine häufig vorkommende Verarbeitung in einer kleineren Tabelle zusammenfassen:
mysql> REPLACE INTO main_db.summary_table (col1, col2, ...)
-> SELECT col1, sum(col2, ...)
-> FROM main_db.enormous_table GROUP BY col1;
Falls Sie diese Operation auf dem Master durchführen, muss jeder Slave die riesige GROUP
BY-Abfrage wiederholen. Kommt das oft vor, werden die Slaves irgendwann nicht mehr
mithalten können. Es hilft wahrscheinlich, das Zahlenschieben auf einen der Slaves abzuwälzen. Auf dem Slave, vielleicht in einer speziellen Datenbank, die extra reserviert
wurde, um Konflikte mit den Daten zu vermeiden, die vom Master repliziert wurden,
können Sie Folgendes ausführen:
mysql> REPLACE INTO summary_db.summary_table (col1, col2, ...)
-> SELECT col1, sum(col2, ...)
-> FROM main_db.enormous_table GROUP BY col1;
Jetzt können Sie SELECT INTO OUTFILE, gefolgt von LOAD DATA INFILE, auf dem Master ausführen, um die Ergebnisse zurück auf den Master zu verschieben. Voilà – die doppelte
Arbeit wurde auf ein einfaches LOAD DATA INFILE reduziert. Bei N Slaves haben Sie gerade
N – 1 riesige GROUP BY-Abfragen gespart.
Das Problem bei dieser Strategie ist der Umgang mit alten Daten. Manchmal ist es schwer,
konsistente Ergebnisse zu erhalten, indem man auf dem Slave liest und auf den Master
schreibt (ein Problem, mit dem wir uns im nächsten Kapitel befassen). Wenn es schwer ist,
das Lesen auf dem Slave durchzuführen, können Sie die Abfrage vereinfachen und Ihren
Slaves eine Menge Arbeit ersparen. Wenn Sie die REPLACE- und SELECT-Teile der Abfrage
trennen, können Sie die Ergebnisse in Ihre Anwendung holen und sie dann wieder auf den
Master einfügen. Führen Sie zuerst die folgende Abfrage auf dem Master durch:
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Der Umbau Ihrer Anwendung und/oder die Optimierung Ihrer Abfragen sind oft die besten Methoden, um Slaves auf die Sprünge zu helfen. Versuchen Sie, die Arbeitsmenge zu
reduzieren, die durch Ihr System dupliziert werden muss. Alle Schreiboperationen, die
auf dem Master teuer sind, werden auf allen Slaves noch einmal abgespielt. Falls Sie die
Arbeit vom Master auf einen Slave delegieren können, muss nur einer der Slaves die
Arbeit erledigen. Sie können dann die Schreibergebnisse wieder auf den Master schieben,
z.B. mit LOAD DATA INFILE.
mysql> SELECT col1, sum(col2, ...) FROM main_db.enormous_table GROUP BY col1;
Sie fügen dann die Ergebnisse wieder in die Summary-Tabelle ein, indem Sie die folgende
Abfrage für jede Zeile in der Ergebnismenge wiederholen:
mysql> REPLACE INTO main_db.summary_table (col1, col2, ...) VALUES (?, ?, ...);
436 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Auch hier haben Sie den Slaves den großen GROUP BY-Anteil der Abfrage erspart; das Trennen des SELECT vom REPLACE bedeutet, dass der SELECT-Teil der Abfrage nicht auf jedem
Slave wieder abgespielt wird.
Schreiboperationen außerhalb der Replikation parallel durchführen
Eine andere Taktik, um übermäßige Verzögerungen bei den Slaves zu vermeiden, sieht
vor, die Replikation ganz und gar zu umgehen. Alle Schreiboperationen, die Sie auf dem
Master durchführen, müssen auf dem Slave serialisiert werden, so dass es sinnvoll ist,
sich die »serialisierten Schreiboperationen« als knappe Ressource vorzustellen. Müssen
alle Ihre Schreibvorgänge vom Master zum Slave laufen? Wie können Sie die beschränkte
serialisierte Schreibkapazität Ihres Slaves für solche Schreiboperationen aufsparen, die
wirklich mittels Replikation erledigt werden müssen?
Wenn Sie es in diesem Licht betrachten, können Sie vielleicht die Prioritäten für die
Schreiboperationen neu setzen. Falls Sie im Speziellen Schreiboperationen finden, die
sich leicht außerhalb der Replikation durchführen lassen, können Sie Schreiboperationen
parallelisieren, die ansonsten wertvolle Schreibkapazitäten auf dem Slave beanspruchen
würden.
Ein großartiges Beispiel ist die Datenarchivierung, die wir weiter vorn in diesem Kapitel
diskutiert haben. OLTP-Archivierungsabfragen sind oft einfache Einzeilenoperationen.
Wenn Sie einfach nur nicht benötigte Zeilen von einer Tabelle in eine andere verschieben, besteht eigentlich kein Grund, diese Schreiboperationen auf den Slaves zu replizieren. Stattdessen können Sie das Binär-Logging für die Archivierungsanweisungen
deaktivieren und dann separate, aber identische Prozesse auf den Mastern und den Slaves
ausführen.
Es klingt vielleicht verrückt, die Daten selbst auf einen anderen Server zu kopieren,
anstatt das durch die Replikation erledigen zu lassen, das kann aber tatsächlich für manche Anwendungen sinnvoll sein. Das gilt vor allem dann, wenn eine Anwendung die
einzige Aktualisierungsquelle für eine bestimmte Gruppe von Tabellen darstellt. Flaschenhälse in der Replikation sammlen sich oft um eine kleine Gruppe von Tabellen, und
falls Sie diese Tabellen außerhalb der Replikation verarbeiten können, haben Sie die
Möglichkeit, diese deutlich zu beschleunigen.
Den Cache für den Slave-Thread vorbereiten
Bei einer entsprechenden Last könnten Sie von einer Parallelisierung der Ein-/Ausgaben
auf den Slaves profitieren, indem Sie die Daten bereits vorab in den Speicher holen. Diese
Technik ist nicht sehr verbreitet, wir kennen aber große Anwendungen, die sie bereits
erfolgreich einsetzen.
Replikationsprobleme und Lösungen | 437
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Diese allgemeine Strategie – den Slaves den teuren Teil einer Schreiboperation zu ersparen – kann in vielen Fällen helfen, in denen Sie Abfragen haben, deren Ergebnisse aufwendig zu berechnen, aber nach der Berechnung einfach zu handhaben sind.
Wie weit das Programm vor dem Slave-SQL-Thread bleiben soll, ist ganz unterschiedlich. Sie können einige Sekunden oder eine entsprechende Anzahl von Byte im Relay-Log
ausprobieren. Sind Sie zu weit voraus, werden die Daten, die Sie in die Caches holen,
schon wieder verschwunden sein, wenn der SQL-Thread sie braucht.
Schauen wir uns an, wie man Anweisungen umschreiben muss, um diesen Ansatz verfolgen zu können. Nehmen Sie einmal die folgende Abfrage:
mysql> UPDATE sakila.film SET rental_duration=4 WHERE film_id=123;
Das folgende SELECT bezieht die gleichen Zeilen und Spalten:
mysql> SELECT rental_duration FROM sakila.film WHERE film_id=123;
Diese Technik funktioniert nur mit den richtigen Lasteigenschaften und der passenden
Hardware-Konfiguration. Folgende Bedingungen könnten darauf hindeuten, dass sie
funktioniert:
• Der Slave-SQL-Thread ist ein-/ausgabegebunden, aber der Slave-Server insgesamt ist
es nicht. Ein vollständig ein-/ausgabegebundener Server würde vom Vorabholen der
Daten nichts haben, weil er keine untätigen Festplatten hat, mit denen dies erfolgen
könnte.
• Der Arbeitssatz ist viel größer als der Speicher (weshalb der SQL-Thread viel Zeit
mit dem Warten auf die Ein-/Ausgaben verbringt). Wenn Ihr Arbeitssatz in den
Speicher passt, hilft das Vorabholen nicht, weil Ihr Server sich nach einer Weile
»aufwärmt« und nur noch selten auf Ein-/Ausgaben warten muss.
• Der Slave besitzt viele Festplattenlaufwerke. Die Leute, von denen wir wissen, dass
sie diese Taktik einsetzen, haben acht oder mehr Laufwerke pro Slave. Es könnte
mit weniger funktionieren, aber Sie brauchen wenigstens zwei bis vier Laufwerke.
• Sie nutzen eine Storage-Engine mit Row-Level-Locking, wie etwa InnoDB. Wenn Sie
dies auf einer MyISAM-Tabelle versuchen, werden der Slave-SQL-Thread und der
Thread, der die Daten vorab holt, wahrscheinlich in einen Wettstreit um die Tabellen-Locks verfallen, wodurch sich die Dinge weiter verlangsamen. (Wenn Sie jedoch
viele Tabellen haben und die Schreiboperationen zwischen ihnen verteilt sind,
könnte sich theoretisch auch bei MyISAM-Tabellen mit dieser Technik die Replikation beschleunigen lassen.)
438 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Dabei wird ein Programm benutzt, das bereits kurz vor dem Slave-SQL-Thread in den
Relay-Logs liest und die Abfragen als SELECT-Anweisungen ausführt. Dadurch wird der
Server veranlasst, einige der Daten von der Festplatte in den Speicher zu holen. Wenn
dann der Slave-SQL-Thread die Anweisung aus dem Relay-Log ausführt, muss er nicht
warten, bis die Daten von der Festplatte geholt wurden. Im Prinzip parallelisiert das
SELECT die Ein-/Ausgabe, die der Slave-SQL-Thread normalerweise seriell ausführen
muss. Während eine Anweisung Daten ändert, werden die Daten der nächsten Anweisung von der Festplatte in den Speicher geholt.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Wenn eine Tabelle viele Indizes besitzt, ist es eventuell nicht möglich, alle Daten vorher
zu holen, die eine Anweisung modifizieren wird. Die UPDATE-Anweisung ändert vielleicht
jeden Index, das SELECT liest aber im besten Fall typischerweise nur den Primärschlüssel
und einen sekundären Index. Das UPDATE muss dennoch weitere Indizes zur Modifikation
holen. Die Effektivität dieser Taktik ist daher in Tabellen mit vielen Indizes deutlich eingeschränkt.
Sie können mit iostat feststellen, ob Sie freie Festplatten haben, die solche Anforderungen
zum Vorabholen von Daten erledigen könnten. Schauen Sie sich die Warteschlangengröße und die Service-Zeit an (Beispiele finden Sie im vorangegangenen Kapitel). Eine
kleine Warteschlange zeigt, dass etwas auf einer höheren Ebene Anforderungen serialisiert. Eine große Warteschlange zeigt eine hohe Last – die Art, die Sie typischerweise
nicht von einem Slave-SQL-Thread erhalten werden, wenn Sie viele Festplatten haben.
Eine hohe Service-Zeit bedeutet, dass zu viele Anforderungen auf einmal an die Festplatte
übermittelt werden.
Diese Technik ist keine Wunderwaffe. Es gibt viele Gründe, weshalb sie bei Ihnen nicht
funktionieren oder vielleicht sogar weitere Probleme verursachen könnte. Sie sollten sie
nur dann versuchen, wenn Sie Ihre Hardware und Ihr Betriebssystem gut kennen. Wir
kennen Leute, bei denen dieser Ansatz die Replikationsgeschwindigkeit um 300 % bis
400 % vergrößert hat. Wir haben es aber selbst ausprobiert und festgestellt, dass es nicht
immer funktioniert hat. Es ist wichtig, die Parameter richtig einzustellen. Allerdings gibt
es nicht immer eine richtige Kombination aus Parametern. Manchmal verhindern auch
Verhaltensweisen des Dateisystems und/oder des Kernels eine parallele Ein-/Ausgabe. Sie
müssen es selbst ausprobieren!
Das Werkzeug mk-slave-prefetch, ein Teil von Maatkit, ist eine Implementierung der
Ideen, die wir in diesem Abschnitt beschrieben haben.
Übergroße Pakete vom Master
Ein weiteres schwer zu findendes Problem bei der Replikation kann auftreten, wenn die
max_allowed_packet-Größe des Masters nicht der des Slaves entspricht. In diesem Fall
kann der Master ein Paket im Log aufzeichnen, das der Slave als zu groß ansieht. Wenn
der Slave dann das Binärlog-Event bezieht, treten bei ihm dann verschiedene Probleme
auf. Dazu gehören eine Endlosschleife aus Fehlern und erneuten Versuchen oder eine
Beschädigung im Relay-Log.
Replikationsprobleme und Lösungen | 439
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Eine Beispiellast, die vom Vorabholen der Daten profitiert, ist eine mit vielen weit verstreuten, einzeiligen UPDATE-Anweisungen, die typischerweise auf dem Master stark
nebenläufig sind. DELETE-Anweisungen kommt dies ebenfalls zugute. INSERT-Anweisungen haben weniger von diesem Ansatz – vor allem, wenn die Zeilen sequenziell eingefügt
werden –, weil das Ende des Index bereits von vorangegangenen Einfügevorgängen
»heiß« ist.
Beschränkte Replikationsbandbreite
Bei einer langsamen Verbindung mit einem Master auf der einen Seite und vielen Slaves
auf der anderen Seite, könnten Sie einen Distribution-Master auf der Slave-Seite unterbringen. Auf diese Weise ist über die langsame Leitung nur ein Server mit dem Master
verbunden, wodurch sich die Last auf der Verbindung sowie die CPU-Last auf dem Master verringern.
Kein Festplattenplatz
Die Replikation kann Ihre Festplatten tatsächlich mit Binärlogs, Relay-Logs oder temporären Tabellen füllen, vor allem, wenn Sie viele LOAD DATA INFILE-Abfragen auf dem Master durchführen und log_slave_updates auf dem Slave aktiviert haben. Je weiter ein Slave
zurückfällt, umso mehr Festplattenplatz benutzt er wahrscheinlich für die Relay-Logs,
die vom Master geholt, aber noch nicht ausgeführt wurden. Sie können diese Fehler vermeiden, indem Sie die Festplattenauslastung überwachen und die Konfigurationsvariable
relay_log_space setzen.
Beschränkungen der Replikation
Die MySQL-Replikation kann aufgrund der ihr innewohnenden Beschränkungen ausfallen oder – mit oder ohne Fehler – aus dem Takt geraten. Es gibt eine ziemlich lange Liste
an SQL-Funktionen und Programmierpraktiken, die einfach nicht zuverlässig repliziert
werden (wir haben viele von ihnen in diesem Kapitel erwähnt). Es ist schwer sicherzustellen, dass keine von ihnen den Weg in Ihren Produktionscode findet, vor allem, wenn Ihre
Anwendung oder Ihr Team sehr groß ist.14
Ein weiteres Problem sind Bugs im Server. Wir wollen nicht negativ klingen, aber die
meisten großen Versionen des MySQL-Servers haben in der Vergangenheit Bugs in der
Replikation besessen, vor allem in den ersten Ausgaben der Hauptversion. Neue Eigenschaften, wie etwa gespeicherte Prozeduren, haben normalerweise weitere Probleme verursacht.
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Wenn Sie über eine eingeschränkte Bandbreite replizieren, können Sie die Option
slave_compressed_protocol auf dem Slave aktivieren (verfügbar seit MySQL 4.0). Verbindet sich der Slave mit dem Master, fordert er eine komprimierte Verbindung an – mit der
gleichen Komprimierung, die jede MySQL-Clientverbindung nutzen kann. Die verwendete Komprimierungs-Engine ist zlib, und unsere Tests haben gezeigt, dass sie textuelle
Daten auf etwa ein Drittel ihrer Originalgröße komprimiert. Allerdings wird für die Komprimierung auf dem Master und die Dekomprimierung auf dem Slave zusätzliche CPUZeit benötigt.
14 Leider besitzt MySQL keine forbid_operations_unsafe_for_replication-Option.
440 |
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Für die meisten Benutzer stellt dies keinen Grund dar, neue Funktionen zu vermeiden,
sondern bietet lediglich Veranlassung, besonders sorgfältig zu testen, vor allem wenn Sie
Ihre Anwendung oder MySQL aufrüsten. Auch die Überwachung ist wichtig; Sie müssen
wissen, wenn etwas ein Problem verursacht.
Wie schnell ist die Replikation?
Häufig wird in Bezug auf die Replikation die Frage gestellt: »Wie schnell ist sie?« Sie ist,
kurz gesagt, im Allgemeinen sehr schnell und läuft so schnell, wie MySQL die Events
vom Master kopieren und wieder abspielen kann. Wenn Sie ein langsames Netzwerk und
sehr große Binärlog-Events haben, dann ist die Verzögerung zwischen der Aufzeichnung
im Binärlog und der Ausführung auf dem Slave vielleicht spürbar. Brauchen Ihre Abfragen lange für die Ausführung und haben Sie ein schnelles Netzwerk, dann können Sie
meist davon ausgehen, dass die Abfragezeit auf dem Slave einen größeren Anteil an der
Zeit für die Replikation eines Events hat.
Um eine umfassendere Antwort geben zu können, müsste jeder Schritt des Vorgangs
gemessen und anschließend entschieden werden, welche Schritte die meiste Zeit in Ihrer
Anwendung erfordern. Für manche Leser ist es vermutlich nur wichtig, dass es normalerweise nur eine kleine Verzögerung zwischen dem Aufzeichnen der Events auf dem Master
und dem Kopieren der Events in das Relay-Log auf dem Slave gibt. Falls Sie es genauer
wissen wollen, schauen Sie sich unser kleines Experiment an.
Wir bauten auf dem Prozess auf, der in der ersten Ausgabe dieses Buches beschrieben
wurde, sowie auf den Methoden von Giuseppe Maxia,15 um die Replikationsgeschwindigkeit mit hoher Präzision zu messen. Wir erstellten eine nichtdeterministische benutzerdefinierte Funktion, die die Systemzeit mit Mikrosekundengenauigkeit zurückliefert
(den Quellcode finden Sie in »Benutzerdefinierte Funktionen« auf Seite 248):
mysql> SELECT NOW_USEC( )
+----------------------------+
| NOW_USEC( )
|
+----------------------------+
| 2007-10-23 10:41:10.743917 |
+----------------------------+
Dies erlaubt es uns, die Replikationsgeschwindigkeit zu messen, indem wir den Wert von
NOW_USEC( ) in eine Tabelle auf dem Master einfügten und sie dann mit dem Wert auf dem
Slave vergleichten.
15 Siehe http://datacharmer.blogspot.com/2006/04/measuring-replication-speed.html.
Wie schnell ist die Replikation?
| 441
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Die MySQL-Replikation ist kompliziert, und je komplizierter Ihre Anwendung ist, umso
sorgfältiger müssen Sie sein. Wenn Sie jedoch lernen, damit umzugehen, funktioniert sie
wirklich gut.
Wir maßen die Verzögerung, indem wir zwei Instanzen von MySQL auf dem gleichen
Server einrichteten, um Ungenauigkeiten zu vermeiden, die durch den Takt verursacht
wurden. Wir konfigurierten eine Instanz als Slave der anderen und führten dann die folgenden Abfragen auf der Master-Instanz aus:
Wir verwendeten eine VARCHAR-Spalte, weil die in MySQL eingebauten Typen Zeiten mit
Auflösungen von unter einer Sekunde nicht speichern können (obwohl einige seiner Zeitfunktionen in der Lage sind, Berechnungen im Bereich unter einer Sekunde durchzuführen). Nun musste nur noch die Differenz zwischen dem Slave und dem Master verglichen
werden. Dazu eignet sich eine Federated-Tabelle. Auf dem Slave führten wir Folgendes
aus:
mysql> CREATE TABLE test.master_val (
->
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
->
now_usec VARCHAR(26) NOT NULL
-> ) ENGINE=FEDERATED
->
CONNECTION='mysql://user:[email protected]/test/lag_test';
Ein einfaches Join und die Funktion TIMESTAMPDIFF( ) zeigen den Rückstand in Mikrosekunden zwischen der Ausführungszeit der Abfrage auf dem Master und dem Slave:
mysql> SELECT m.id, TIMESTAMPDIFF(FRAC_SECOND, m.now_usec, s.now_usec) AS usec_lag
-> FROM test.lag_test as s
->
INNER JOIN test.master_val AS m USING(id);
+----+----------+
| id | usec_lag |
+----+----------+
| 1 |
476 |
+----+----------+
Wir fügten mit einem Perl-Skript 1.000 Zeilen auf dem Master ein. Zwischen den einzelnen Einfügungen ließen wir eine Verzögerung von 10 Millisekunden, um zu verhindern,
dass die Master- und Slave-Instanzen begannen, um die CPU-Zeit zu kämpfen. Anschließend erzeugten wir eine temporäre Tabelle, die den Rückstand des jeweiligen Events enthielt:
mysql> CREATE TABLE test.lag AS
> SELECT TIMESTAMPDIFF(FRAC_SECOND, m.now_usec, s.now_usec) AS lag
-> FROM test.master_val AS m
->
INNER JOIN test.lag_test as s USING(id);
Als Nächstes gruppierten wir die Ergebnisse nach Rückstandszeit, um festzustellen, welches die am häufigsten auftretenden Rückstandszeiten waren:
mysql>
->
->
->
442 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
mysql> CREATE TABLE test.lag_test(
->
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
->
now_usec VARCHAR(26) NOT NULL
-> );
mysql> INSERT INTO test.lag_test(now_usec) VALUES( NOW_USEC( ) );
SELECT ROUND(lag / 1000000.0, 4) * 1000 AS msec_lag, COUNT(*)
FROM lag
GROUP BY msec_lag
ORDER BY msec_lag;
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Die Ergebnisse zeigen, dass die meisten kleinen Abfragen weniger als 0,3 Millisekunden
für die Replikation brauchen, also von der Ausführungszeit auf dem Master bis zur Ausführungszeit auf dem Slave.
Hier wird allerdings nicht gemessen, wie schnell ein Event beim Slave ankommt, nachdem es im Binärlog auf dem Master aufgezeichnet wurde. Es wäre schön, diesen Wert zu
kennen, denn je schneller der Slave das Log-Event empfängt, umso besser ist es. Wenn
der Slave das Event empfangen hat, kann er eine Kopie bereitstellen, falls der Master
abstürzt.
Obwohl Ihre Messungen nicht exakt zeigen, wie lang dieser Teil des Vorgangs dauert,
sollte er theoretisch außerordentlich schnell ablaufen (d.h. nur durch die Netzwerkgeschwindigkeit eingeschränkt). Der MySQL-Binlog-Dump-Prozess fragt nicht den Master
nach Events ab, weil das ineffizient und langsam wäre. Stattdessen benachrichtigt der
Master den Slave über Events. Das Lesen eines Binärlog-Events vom Master ist ein blockierender Netzwerkaufruf, der praktisch sofort damit beginnt, Daten zu senden, nachdem der Master das Event im Log aufgezeichnet hat. Man kann also mit hoher Sicherheit
sagen, dass das Event den Slave so schnell erreicht, wie der Slave-Thread aufwachen und
das Netzwerk die Daten übertragen kann.
Die Zukunft der MySQL-Replikation
Die MySQL-Replikation hat eine Reihe von Schwächen, die MySQL AB künftig beheben
will. Von dritter Seite wurden bereits einige Funktionen und Problemlösungen bereitgestellt. Zum Beispiel hat Google eine Reihe von eigenen Patches für den MySQL-Server
veröffentlicht, die ihn um Fähigkeiten zur quasisynchronen Replikation sowie weitere
Eigenschaften erweitern (siehe »Synchrone MySQL-Replikation« auf Seite 492).
Ein weiterer möglicher Zusatz ist die Unterstützung für die Multimaster-Replikation –
d.h. einen Slave mit mehr als einem Master. Dieses Problem ist wahrscheinlich schwierig
zu lösen und erfordert vermutlich Fähigkeiten zur Konflikterkennung und -auflösung.
Die Zukunft der MySQL-Replikation | 443
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
+----------+----------+
| msec_lag | COUNT(*) |
+----------+----------+
|
0.1000 |
392 |
|
0.2000 |
468 |
|
0.3000 |
75 |
|
0.4000 |
32 |
|
0.5000 |
15 |
|
0.6000 |
9 |
|
0.7000 |
2 |
|
1.3000 |
2 |
|
1.4000 |
1 |
|
1.8000 |
1 |
|
4.6000 |
1 |
|
6.6000 |
1 |
| 24.3000 |
1 |
+----------+----------+
Die zeilenbasierte Replikation in MySQL 5.1 ist ein Schritt in diese Richtung. Zeilenbasierte Replikation könnte es künftig auch erlauben, durch mehrere Threads Events auf
den Slave anwenden zu lassen, wodurch der Flaschenhals verschwindet, der durch die
Single-Thread-Regelung auftritt.
Momentan gibt es in MySQL keine Garantien für die Konsistenz und Korrektheit von
Daten. Entsprechend einer Umfrage auf der MySQL-Website ist die am meisten
gewünschte Funktion ein Online-Konsistenztest, mit dem geprüft werden kann, ob ein
Slave die gleichen Daten enthält wie sein Master. MySQL AB betreibt für diese Aufgabe
ein Worklog mit einer grundlegenden Beschreibung für die Lösung dieses Problems.
Viele Leute haben außerdem Erweiterungen für das Binärlog-Format gefordert, um
sicherzustellen, dass Beschädigungen erkannt werden können, und MySQL AB hat auch
hier bestätigt, dass es sich um eine wichtige Aufgabe handelt.
Diese und weitere Verbesserungen dürften dafür sorgen, dass die MySQL-Replikation in
der Zukunft noch leistungsfähiger und zuverlässiger wird. Es ist ermutigend, wenn man
auf die letzten Jahre zurückblickt und die Änderungen sieht, die in dieser Zeit geschehen
sind. Es soll dennoch angemerkt werden, dass die meisten Funktionen, die in der ersten
Ausgabe dieses Buches vorhergesagt wurden, niemals umgesetzt wurden, obwohl einige
von ihnen teilweise implementiert wurden – wie z.B. die ausfallsichere Replikation, die
zwar in der MySQL-Codebasis vorhanden ist, aber als Projekt nie zu Ende geführt wurde.
444 |
Dies ist ein Auszug aus dem Buch "High Performance MySQL / Optimierung, Backups, Replikation und Lastverteilung", ISBN 978-3-89721-889-5
http://www.oreilly.de/catalog/hpmysql2ger/
Dieser Auszug unterliegt dem Urheberrecht. © O’Reilly Verlag 2009
Es gibt darüber hinaus Pläne, die Online-Backup-API in die Replikation zu integrieren
und es einem MySQL-Server zu erlauben, sich automatisch selbst als Slave eines anderen
Servers zu konfigurieren.
Kapitel 8: Replikation
Baron Schwartz / Peter Zaitsev / Vadim Tkachenko / Jeremy D. Zawodny / Arjen Lentz / Derek J. Balling, High Performance MySQL / Optimierung, Backups, Replika
Herunterladen