Dieser Artikel ist der erste Teil einer kleinen Gruppe von Artikeln über MySQL-Backups. Die weiteren Artikel werden hier verlinkt, sobald sie erscheinen.
Hier ist der zweite Artikel: MySQL Replikation
Hier ist der dritte Artikel: Hinter der MySQL-Replikation aufräumen
Hier ist der vierte und letzte Artikel: MySQL mit daemontools
Wenn es um Backups geht, sind Datenbanken immer nochmal gesondert zu beachten. Zwar kann man die vom Datenbanksystem auf die Platte geschriebenen Daten mit den üblichen Backup-Tools sichern, aber in den meisten Fällen wird man so kein konsistentes Backup der im Datenbanksystem gespeicherten Daten erhalten. Dabei ist es auch relativ egal, ob man nun ein Backup aller im Datenbanksystem gehaltenen Daten haben möchte, oder nur von einzelnen Datenbanken oder Tabellen. In jedem Fall hat mein einige Hürden zu nehmen.
Man braucht also ein Extra-Tool und nicht selten muß man sich die Lösung dann noch zusammenskripten. Im Planet MySQL Blog findet sich eine schöne Auflistung der gängigsten Lösungsmöglichkeiten:
There are a couple of options available to get consistent backups from MySQL.
- Use mysqldump with FLUSH TABLES WITH READ LOCK
- Use a slave with STOP SLAVE and your favourite backup tool.
- For innodb, use the commerical backup tool ibbackup
- Use LVM (Logical Volume Manager) snapshots with FLUSH TABLES WITH READ LOCK
- Shutdown the database.
Man hat also immerhin verschiedene Optionen, unter denen man wählen kann. (Diese Liste erhebt keinen Anspruch auf Vollständigkeit.) Nebenbei wird aber offensichtlich, daß die Frage nach dem Backup bei der Konzeptionierung und Entwicklung von MySQL keine große Rolle gespielt hat – wie bei leider allzuvielen anderen Softwareprojekten auch, darunter viele andere Datenbanken.
Die Wahl die wir für unsere Anwendungsfälle treffen wird von folgenden Überlegungen geleitet:
- #1 bedeutet dem Datenbanksystem wird befohlen, alle Tabellen konsistent auf die Platte zu schrieben und sich dann zu sperren. Dann zieht man mit
mysqldump
alle Daten aus dem Datenbanksystem und hebt zuletzt die Sperre wieder auf. Solange die Sperre besteht ist kein schreibender Zugriff auf die Daten möglich. Soetwas kann man folglich nur dann machen, wenn man ein regelmäßiges Wartungsfenster hat, in dem die Applikation die auf die Datenbank zugreift nicht (oder nur-lesend) benutzt wird. Bei einem Buchhaltungssystem mag das noch praktikabel sein, aber bei Internet-Diensten, die keine Ladenöffnungszeiten kennen kommt diese Vorgehensweise eher selten in Frage. Unabhängig davon tritt hier das Problem auf, daß das Sichern der Daten mitmysqldump
Zeit beansprucht. Hier müßte also zusätzlich darauf geachtet werden, daß das Wartungsfenster eingehalten wird. - Für #5 gilt im Grunde das gleiche. Ein Anhalten des Datenbanksystems hat für die es benutzenden Applikationen sogar noch gravierendere Konsequenzen als eine Sperre, sie können nichtmal mehr lesend auf die Daten zugreifen. Hier würde das Backup nicht mit
mysqldump
geschrieben, sondern mit einem anderen Tool welches auf Dateisystemebene arbeitet. Auf Unix-basierten Systemen gibt es da eine sehr große Auswahl, die vontar
überdump
bis zuamanda
reicht, um nur ein paar zu nennen. - #3 kommt für uns nicht in Frage, weil wir keine kommerziellen Tools benutzen wollen. Das ist sowohl eine philosophische Frage als auch eine praktische, denn zu einem kommerziellen Tool könnten wir unseren Kunden nicht den Support bieten, den wir bei freier und quelloffener Software leisten können.
- #4 bedeutet auch, daß die Datenbank in einen konsistenten Zustand gebracht und dann gesperrt wird, allerdings nur solange bis ein LVM-Snapshot erstellt wurde. Das kann zwar auch etwas dauern (aber nur wenn die Hardware oder Software an ihre Grenzen stoßen, LVM-Snapshots gehen in der Regel schnell), geht aber in jedem Fall schneller als Methode #1. Hier gibt es aus unserer Sicht neben der (wenngleich kürzeren) Sperrzeit noch zwei Nachteile:
- Zum einen benötigt man bereits eine LVM-Umgebung. Sicherlich kann man auch unter einem laufenden System eine einrichten, aber das ist knifflig, kann schief gehen, dauert und geht nicht gänzlich ohne Downtime mindestens des Datenbanksystems. Nun mag man sich angewöhnt haben unter jedem System LVM einzurichten, um genau solchen Eventualitäten vorzubeugen. Es mag aber Situationen geben in denen man darauf verzichtet, weil die zusätzliche Komplexität unnötig ist oder gar störend wäre, z.B. wenn man ein System von ISCSI bootet und man statt mit LVM zu arbeiten einfach weitere ISCSI-Targets einbinden könnte.
- Die Wiederherstellung aus dem Backup ist zum Teil sehr aufwendig. Häufig wird man einen separaten MySQL-Dienst starten wollen oder müssen, über den man auf den Datenbestand im Snapshot zugreift. Wenn man innodb verwendet bleibt einem im Grunde nichts anderes übrig, da innodb einen großen Container für alle gemeinsam verwalteten Datenbanken verwendet, aus dem sich einzelne Tabellen nicht ohne weiteres extrahieren lassen.
Bleibt somit noch Methode #2. Hier wird ein zweiter MySQL-Dienst eingerichtet und als Slave konfiguriert, so daß er über die Replikationsfunktion von MySQL den Datenbestand des ersten spiegelt und sich aktuell hält. Für Backups wird dann auf dem Slave die Replikation vorübergehend angehalten. Ab diesem Punkt kann im Grunde jede beliebige Backup-Methode verwendet werden, man kann den Slave sogar für das Backup runterfahren. Uns genügt es aber, bei angehaltener Replikation alle Datenbanken und Tabellen des Slave einzeln mit mysqldump
auszulesen und an einen Ort zu schreiben, an dem unser normales Backup sie findet und sichert.
Ein Slave der nur für Backups verwendet wird, erzeugt nicht sonderlich viel Last auf einem System und kann daher prinzipiell auch auf demselben Rechner laufen wie der Master, wenn man das denn möchte. Wenn man so vorgeht, sollte man jedoch bedenken, daß man einen zweiten MySQL-Server betreibt, der auch entsprechend zu sichern ist. Wenn der Slave nur für Backups dienen soll, muß man Nutzerzugriff darauf unbedingt verhindern, weil vom Nutzer gemachte Änderungen sonst durch die Replikation überschrieben werden können usw. Damit das möglich ist, kann die mysql-Datenbank mit den Nutzerdaten auf dem Slave vom Master abweichen. In so einem Fall empfiehlt es sich, diese eine Datenbank separat vom Master zu sichern (hierbei kann man aber getrost mit einem READ LOCK arbeiten, da diese Datenbank relativ klein ist und sich schnell sichern läßt.)
Wie man die Replikation einstellt, wird im nächsten Artikel beschrieben.