{"id":228,"date":"2009-04-21T20:49:33","date_gmt":"2009-04-21T18:49:33","guid":{"rendered":"http:\/\/www.butschek.de\/?page_id=228"},"modified":"2014-08-01T14:38:57","modified_gmt":"2014-08-01T13:38:57","slug":"perl-mysql-backup","status":"publish","type":"page","link":"https:\/\/www.butschek.de\/fachartikel\/perl-mysql-backup\/","title":{"rendered":"Perl MySQL Backup"},"content":{"rendered":"

Einleitung<\/h2>\n

Datenbanken sind beim Backup besonders kritisch. W\u00e4hrend die meisten Admins (wie auch ich) gerne auf Technologien wie Snapshots verzichten und alle Dateien der Festplatte mit einer dateibasierten Software sichern, gilt es bei einer Datenbank einige Schwierigkeiten zu kl\u00e4ren.<\/p>\n

Die Bin\u00e4rdateien der Datenbank sollte man im laufenden Betrieb nicht wegsichern, da hier aufgrund des Caches der Datenbank und st\u00e4ndigen Schreibzugriffen Datenverlust und Inkonsistenz drohen.<\/p>\n

Viele Serveradmins bevorzugen daher den SQL-Dump: Man erzeugt eine Textdatei, die alle SQL-Kommandos enth\u00e4lt, mit der man die Datenbank komplett wieder herstellen kann.<\/p>\n

Ich pers\u00f6nlich bevorzuge keine SQL-Dumps, denn hier steht man bei jedem Einspielen (meist Jahre nach dem Einrichten des Backups) immer wieder vor neuen Problemen. Mal sind bestimmte Feldnamen neuerdings reservierte Begriffe, mal stimmen die Quotes in der Datei nicht, dann wird mal wieder ein Tabellentyp angeblich nicht unterst\u00fctzt oder die Zeichenkodierung hat sich ge\u00e4ndert und zerst\u00f6rt dadurch alle Umlaute und Sonderzeichen.<\/p>\n

Abgesehen von diesen Problemen st\u00f6rt aber auch die relativ lange Zeit der Wiederherstellung: Das L\u00f6sen der \u00fcblichen Probleme kostet dabei die meiste Zeit, doch auch das Einspielen von 160 GByte SQL-Kommandos ben\u00f6tigt sein Zeit.<\/p>\n

Ich pers\u00f6nlich bevorzuge daher ein Backup der Bin\u00e4rdaten der Datenbank. Solange mein MySQL-Server auf aktuellem Stand ist (Upgrade erledigt ich ja regelm\u00e4\u00dfig), kann ich nach einem Crash jederzeit ein Neusystem aufsetzen, die Bin\u00e4rdateien zur\u00fcckspielen, Datenbank starten und schon l\u00e4uft\u00a0die Datenbank wieder – inklusive aller Benutzer und Berechtigungen.<\/p>\n

Vorgehen bei der Sicherung<\/h2>\n

Ein Problem ergibt sich hier nur: Wie schon gesagt unterliegen die Bin\u00e4rdateien der Kontrolle des Datenbankservers und stehen st\u00e4ndig unter Schreibzugriff. Ohne die Hilfe der Datenbank ist eine Sicherung also nicht m\u00f6glich. Aber solange man als Storage Engine MyISAM einsetzt, l\u00e4\u00dft sich ganz einfach das l\u00f6sen:<\/p>\n

Zuerst mal erzeugen wir lokal eine konsistente Kopie der MySQL-Datendateien, die meist unter \/var\/lib\/mysql\/ oder auch mal unter \/usr\/local\/mysql\/data\/ liegen. Beim Backup sichern wir dann statt der Datenbank selbst einfach die zuvor erzeugte Kopie.<\/p>\n

Doch auch beim lokalen Kopieren sto\u00dfen wir an die oben genannten Probleme. Doch lokal dauert das Kopieren nur sehr kurze Zeit, daher l\u00e4\u00dft sich das in den Griff kriegen<\/p>\n

Flush & Lock<\/h2>\n

Sendet man MySQL das Kommando FLUSH TABLES; so werden alle Caches geleert, also alle noch ausstehenden Daten wirklich in die Bin\u00e4rdateien geschrieben. Jedoch w\u00fcrde MySQL w\u00e4hrend dem Kopieren schon weiter zwischenspeichern und damit den Effekt zunichte machen.<\/p>\n

Das Kommando FLUSH TABLES WITH READ LOCK; dagegen leert ebenfalls die Caches und lockt alle Tabellen, so dass kein anderer Prozess Schreibzugriffe in der Datenbank ausf\u00fchren kann, bis das Kommando UNLOCK TABLES; gesendet wird. Alle anderen m\u00fcssen also mit dem Schreiben abwarten, bis die Backupsoftware fertig mit den Lesen der Dateien ist.<\/p>\n

Soweit klappt das schonmal, nun m\u00fcssen wir nur sehen, dass der Kopiervorgang so schnell wie m\u00f6glich geht, denn wenn die Datenbank 2 Minuten vollst\u00e4ndig gelockt ist, ist das f\u00fcr den Betrieb eine starke Beeintr\u00e4chtigung.<\/p>\n

Kopieren mit RSync<\/h2>\n

RSync erlaubt das Kopieren (besser: synchronisieren) von Daten. Dabei wird vor dem Kopiervorgang gepr\u00fcft, welche Dateien sich seit der letzten Ausf\u00fchrung ge\u00e4ndert haben und nur diese werden \u00fcbertragen.<\/p>\n

Beim ersten Aufruf wird nat\u00fcrlich alles \u00fcbertragen, da am Zielort ja noch keine Daten sind. Ruft man RSync danach nochmal mit den gleichen Parametern auf, werden nur noch die \u00c4nderungen seit der letzten Kopie \u00fcbertragen.<\/p>\n

Dies in Kombination mit den Flushes und Locks sollte uns in die Lage versetzen, eine Kopie der Datenbank anzufertigen, ohne die Datenbank lange zu locken.<\/p>\n

Das Konzept<\/h2>\n

Zuerst m\u00fcssen wir sehen, dass wir eine initiale Kopie der Datenbank erhalten:<\/p>\n