Sichern einer MySQL-Datenbank über ZFS-Snapshots

12

Ich habe eine Reihe von Websites gefunden, die genau darüber sprechen, aber mir fehlen einige wichtige Details. Die allgemeinen Schritte sind

  • Lauf FLUSH TABLES WITH READ LOCK
  • Machen Sie den ZFS-Schnappschuss
  • Lauf UNLOCK TABLES

Verschiedene Quellen berichten, dass InnoDB, das ich verwende, a nicht wirklich ehrt FLUSH. Das MySQL-Benutzerhandbuch stellt fest, dass es eine FLUSH TABLES...FOR EXPORTVariante für InnoDB gibt, für die jedoch jede Tabelle einzeln angegeben werden muss, anstatt die gesamte Datenbank zu sichern. Ich würde es vorziehen, nicht jede Tabelle einzeln anzugeben, da die Wahrscheinlichkeit groß ist, dass die Liste der Tabellen nicht mehr mit den tatsächlich vorhandenen Tabellen übereinstimmt.

Das andere Problem, das ich habe, ist, dass ich so etwas vorhabe mysql -h"$HOST" -u"$USERNAME" -p"$PASSWORD" --execute="FLUSH TABLES WITH READ LOCK". Dadurch wird die Sperre jedoch sofort nach dem Beenden der Sitzung aufgehoben. Das macht Sinn, ist aber auch ziemlich ärgerlich, da ich die Lesesperre halten muss, wenn ich meinen Schnappschuss mache.

Meine andere Idee ist es, ein heißes Backup mit einem Tool wie Percona XtraBackup zu erstellen und Snapshots des Backups zu erstellen. Ich würde es jedoch vorziehen, nicht die Kosten für das Schreiben aller meiner Daten an einen zweiten Speicherort zu zahlen, nur um einen Snapshot zu erstellen.

Andy Shulman
quelle
Warum eine statische Liste von Tabellen? Sie können sicher eine Liste dynamisch zur Laufzeit generieren.
EEAA
1
Befindet sich die Datenbank auf einer VM oder auf dem Bare Metal? Befindet sich der Speicher sogar auf demselben Computer?
Michael Hampton
EEAA, fair genug.
Andy Shulman
Michael, die Datenbank und die ZFS-Box sind verschiedene Maschinen, aber keine ist virtualisiert.
Andy Shulman
@AndyShulman Ich denke, du solltest das Layout ein bisschen besser erklären. Das ergibt keinen Sinn.
Ewwhite

Antworten:

4

Wenn Sie InnoDB nur für alle Tabellen verwenden und auf Folgendes festlegen innodb_flush_log_at_trx_commit:

  • 1 (Der Inhalt des InnoDB-Protokollpuffers wird bei jedem Transaktions-Commit in die Protokolldatei geschrieben und die Protokolldatei wird auf die Festplatte geschrieben.) oder
  • 2 (Der Inhalt des InnoDB-Protokollpuffers wird nach jedem Transaktions-Commit in die Protokolldatei geschrieben, und die Protokolldatei wird ungefähr einmal pro Sekunde auf die Festplatte geschrieben.)

Dann benötigen Sie FLUSH TABLES nicht, bevor Sie einen Snapshot erstellen, sondern führen den ZFS-Snapshot direkt aus. InnoDB kann Daten aus Transaktions-Commit-Protokollen ohne Datenverlust wiederherstellen.

Siehe: https://dev.mysql.com/doc/refman/5.5/de/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit

Gea-Suan Lin
quelle
Mit dem in MySQL 8 eingeführten Data Dictionary sind sogar DDL-Operationen (Schema Modification) atomar. Zuvor konnten DDL-Operationen während eines Dateisystem-Snapshots teilweise festgeschriebene (dh beschädigte) Ergebnisse liefern.
Bernie
13

Sie benötigen eine vollständige Datenbanksperre, um eine (die meisten) Datenbank (en) konsistent zu sichern.

Das Handbuch https://dev.mysql.com/doc/refman/5.5/de/backup-methods.html besagt, dass FLUSH TABLES WITH READ LOCK speziell für ZFS-Snapshots korrekt ist.

Backups mit einem Dateisystem-Snapshot erstellen

Wenn Sie ein Veritas-Dateisystem verwenden, können Sie eine Sicherungskopie wie folgt erstellen:

  1. Führen Sie von einem Client-Programm aus FLUSH TABLES WITH READ LOCK.
  2. Führen Sie in einer anderen Shell den Mount- vxfsSnapshot aus.
  3. Führen Sie vom ersten Client aus UNLOCK TABLES.
  4. Kopieren Sie Dateien aus dem Snapshot.
  5. Hängen Sie den Schnappschuss aus.

Ähnliche Funktionen für Momentaufnahmen sind möglicherweise in anderen Dateisystemen wie LVM oder ZFS verfügbar.

Es ist irgendwie lächerlich, dass sie die Tatsache, die Sie FLUSH TABLES table_a, table_b, table_c FOR EXPORTfür InnoDB benötigen, aus diesen Anweisungen herausgelassen haben. Es ist auch dumm, jede Tabelle so spezifizieren zu müssen. Aber wie die EEAA sagt, können Sie eine Liste von Tabellen erstellen, wenn Sie mit der Sicherung beginnen.

Um die Sperre zu halten, müssen Sie die Datenbankverbindung aktiv halten, während Sie den Snapshot ausführen

Im Allgemeinen würde ich so etwas wie Perl oder eine andere Programmiersprache verwenden, die eine Verbindung herstellen, die Datenbank sperren und unter Beibehaltung der Datenbankverbindung den Snapshot erstellen, dann entsperren und trennen kann. Es ist nicht komplex. Ich würde wetten, dass es Tools gibt, die dies bereits tun, aber das Schreiben eines Tools ist einfach.

Ich sage einfach, nicht komplex, etc .. ein paar mal. Ich gehe davon aus, dass Sie über grundlegende Programmierkenntnisse oder gute Skriptfähigkeiten verfügen.

Ryan Babchishin
quelle
Ich hatte gehofft, ein so konzeptionell einfaches Skript in Bash zu behalten, aber Sie haben Recht, wenn Sie die Sprache wechseln, wird dies viel einfacher. Möglicherweise lese ich Ihre Antwort falsch, aber es sieht so aus, als ob Sie sagen, dass ich beides ausführen muss FLUSH TABLES WITH READ LOCKund dann FLUSH TABLES...FOR EXPORT, während mein Lesen des MySQL-Handbuchs besagt, dass nur eines notwendig sein sollte.
Andy Shulman
Entschuldigung, ich war nicht klar. Ich gehe nur das Handbuch durch und es sagt zwei verschiedene Dinge. Ich nehme an, Sie haben Recht und brauchen nur das Spätere. Alle Tabellen sollten jedoch in einem Befehl gesperrt sein.
Ryan Babchishin
1
Da die Dokumentation nicht sehr übersichtlich ist, die gesamte Datenbank gesperrt werden muss und eine DB-Verbindung aufrecht erhalten werden muss, während der Snapshot erstellt wird, scheint es einfacher zu sein, die DB einfach herunterzufahren, zu sichern und neu zu starten es.
Andrew Henle
2
@andrew Seufzer ... Ich verstehe. Aber das wird langsam sein, dazu führen, dass Verbindungen getrennt werden / fehlschlagen, und ich habe gesehen, dass Datenbanken nicht ordnungsgemäß wiederhergestellt werden können (schlecht für die Automatisierung). Es wäre gut, eine endgültige Antwort von MySQL / Oracle zu bekommen. Sie müssen eine Mailingliste haben.
Ryan Babchishin
7

Ich habe ein konzeptionell einfaches Skript in Bash abgezockt und angepasst, das ich in einem anderen Serverfehler- Beitrag von Tobia gefunden habe . Es sollte ungefähr 90% des Weges dorthin bringen.

mysql_locked=/var/run/mysql_locked

# flush & lock MySQL, touch mysql_locked, and wait until it is removed
mysql -hhost -uuser -ppassword -NB <<-EOF &
    flush tables with read lock;
    delimiter ;;
    system touch $mysql_locked
    system while test -e $mysql_locked; do sleep 1; done
    exit
EOF

# wait for the preceding command to touch mysql_locked
while ! test -e $mysql_locked; do sleep 1; done

# take a snapshot of the filesystem, while MySQL is being held locked
zfs snapshot zpool/$dataset@$(date +"%Y-%m-%d_%H:%M")

# unlock MySQL
rm -f $mysql_locked

Hier wird der von mysqlIhnen verwendete Befehl im Hintergrund ausgeführt und berührt eine Datei. Es wartet im Hintergrund darauf, dass die Datei verschwindet, bevor es beendet und die Tabellen entsperrt werden. Währenddessen wartet das Hauptskript, bis die Datei vorhanden ist, erstellt dann den Snapshot und löscht die Datei.

Die Datei, auf die von verwiesen wird $mysql_locked, muss für beide Computer zugänglich sein. Dies sollte leicht möglich sein, da beide auf ein gemeinsames Dataset zugreifen können (auch wenn sie möglicherweise unterschiedliche Pfade verwenden, und Sie sollten dies berücksichtigen).

Michael Hampton
quelle
Ich kenne MySQL-Skripte nicht, also ist das vielleicht eine dumme Idee, aber können Sie das nicht einfach system zfs snapshot...im Hauptskript tun ? Oder ist das Snap-shotting hat in einem separaten Prozess laufen zu lassen?
TripeHound
@ Tripehound beide Dinge müssen irgendwie parallel passieren
Ryan Babchishin
@ RyanBabchishin Ich denke, er hat tatsächlich Recht. Der SYSTEMBefehl führt die Dinge lokal aus. Wenn ich den mysql-Client auf der FreeBSD-Box starte und ausführe LOCK; SYSTEM zfs snapshot; UNLOCK, scheint das zu funktionieren.
Andy Shulman
@Andy Ich sagte nur, dass sie parallel passieren müssen. Egal, wie Sie vorgehen.
Ryan Babchishin
2

Sie benötigen FLUSH TABLES WITH READ LOCK für myisam, da es kein Journaling gibt.

Für innodb braucht man eigentlich gar nichts, IMO, weil es sich um Journaling handelt. Es ist sowieso konsistent, setzt das Journal nur automatisch zurück, wenn zum Zeitpunkt des Schnappschusses etwas passiert.

Wenn Sie Konsistenz auf Anwendungsebene wünschen, sollte Ihre Anwendung Transaktionen verwenden. Wenn Ihre Anwendung Transaktionen und innodb verwendet, werden Sie bei jedem konsistenten Snapshot automatisch nach dem Weg bis zur Anwendungsebene gefragt.

Jim Salter
quelle
1

So erstelle ich einen ZFS-Snapshot unter Beibehaltung der Sperre:

mysql << EOF
    FLUSH TABLES WITH READ LOCK;
    system zfs snapshot data/db@snapname
    UNLOCK TABLES;
EOF
Petr Stastny
quelle