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