mysqldump, Snapshots & Restore
Von mysqldump über XtraBackup bis Point-in-Time-Recovery: Wie du ein wasserdichtes MySQL-Backup-Konzept für Magento 2 aufbaust, das auch im Ernstfall hält.
Inhaltsverzeichnis
- Warum ein MySQL-Backup-Konzept unverzichtbar ist
- mysqldump: die wichtigsten Optionen im Detail
- Percona XtraBackup: Hot-Backups ohne Downtime
- Binary Log und Point-in-Time-Recovery (PITR)
- Magento-spezifische Backup-Überlegungen
- Backup-Rotation und Aufbewahrungsstrategien
- Restore-Tests und Backup-Verifikation
- Restore-Zeit abschätzen und planen
- Zusammenfassung
- FAQ
Warum ein MySQL-Backup-Konzept unverzichtbar ist
Ein MySQL-Backup ist nicht nur eine technische Pflichtübung — es ist die letzte Verteidigungslinie gegen Datenverlust durch Hardware-Ausfälle, menschliche Fehler, Ransomware oder Softwarebugs. In Magento-2-Projekten mit tausenden Produkten, Kunden und Bestellungen wiegt dieser Schutz besonders schwer. Dennoch wird der Backup-Prozess in der Praxis erschreckend oft vernachlässigt: MySQL-Backups werden zwar angelegt, aber niemals wiederhergestellt getestet. Das ist ein fataler Trugschluss, der im Ernstfall zum Totalverlust führt.
Ein gutes MySQL-Backup-Konzept beantwortet vier Fragen klar: Was wird gesichert (alle Datenbanken, einzelne Tabellen, Binlog-Segmente)? Wie oft wird gesichert (täglich, stündlich, kontinuierlich)? Wo wird gespeichert (lokal, remote, Cloud)? Und wie lange braucht ein vollständiger Restore? Wer diese vier Fragen nicht beantworten kann, hat kein echtes MySQL-Backup — er hat nur eine Hoffnung.
Das Recovery Point Objective (RPO) beschreibt den maximalen akzeptablen Datenverlust in Zeit gemessen — also wie viele Stunden oder Minuten Transaktionen verloren gehen dürfen. Das Recovery Time Objective (RTO) beschreibt, wie lange die Wiederherstellung dauern darf. Beide Werte müssen vor der Wahl der Backup-Technologie festgelegt werden, da sie die gesamte Strategie bestimmen. Ein Onlineshop mit hohem Bestellvolumen wird andere Anforderungen haben als ein internes Reporting-System.
In diesem Artikel schauen wir uns alle relevanten MySQL-Backup-Techniken an: von klassischem mysqldump über Percona XtraBackup bis hin zu Point-in-Time-Recovery mit Binary Logs. Dabei beziehen wir durchgehend Magento-2-Kontexte ein, denn ein Magento-Datenbankschema hat eigene Tücken, die ein generisches Backup-Konzept übersieht.
mysqldump: die wichtigsten Optionen im Detail
mysqldump ist der Klassiker für logische MySQL-Backups. Er erzeugt SQL-Statements, die die Datenbank von Grund auf neu aufbauen können. Das macht ihn portabel und einfach zu inspizieren — aber auch langsamer als physische MySQL-Backup-Methoden. Für Magento-Datenbanken ab 50 GB sollte mysqldump daher nur als ergänzendes Werkzeug eingesetzt werden, nicht als einzige Strategie.
Die wichtigsten Flags für ein konsistentes InnoDB-MySQL-Backup sind --single-transaction und --routines. Ohne --single-transaction sperrt mysqldump alle Tabellen, was bei einem aktiven Magento-Shop zu merklichen Blockaden führt. Die Option öffnet stattdessen eine repeatable-read-Transaktion, sodass ein konsistenter Snapshot ohne Locks entsteht. Das ist bei InnoDB problemlos möglich, weil InnoDB MVCC (Multi-Version Concurrency Control) unterstützt.
-- Full dump with all InnoDB-safe options for Magento
mysqldump \
--single-transaction \ -- consistent snapshot, no table locks on InnoDB
--routines \ -- include stored procedures and functions
--events \ -- include scheduled MySQL events
--triggers \ -- include triggers (default=ON, explicit is safer)
--hex-blob \ -- export BLOBs as hex (safe for binary data)
--set-gtid-purged=OFF \ -- avoid GTID issues when restoring to replica
--databases magento_db \
-u backup_user -p \
| gzip > /backups/magento_$(date +%Y%m%d_%H%M%S).sql.gz
Die Option --hex-blob ist besonders für Magento relevant: Magento speichert in Tabellen wie cms_block und Konfigurationswerten gelegentlich binäre Daten. Ohne --hex-blob kann ein BLOB-Feld den SQL-Dump korrumpieren. Mit --set-gtid-purged=OFF werden GTID-Kommentare im Dump unterdrückt — wichtig, wenn der Dump auf einen Server mit anderen GTID-Konfigurationen eingespielt werden soll. Ohne dieses Flag schlägt der Import auf manchen Replikations-Setups fehler.
Für selektive MySQL-Backups einzelner Tabellen — etwa nur die sales_order-Familie — ist mysqldump ebenfalls geeignet. Wichtig ist dabei, die referenzielle Integrität zu beachten: Eine Bestellung ohne ihre zugehörigen sales_order_item-Zeilen ist nutzlos und kann zu Fehlern im Magento-Backend führen.
-- Partial backup: only order-related tables for Magento
mysqldump \
--single-transaction \
--tables \
magento_db \
sales_order \
sales_order_item \
sales_order_address \
sales_order_payment \
sales_order_status_history \
sales_invoice \
sales_invoice_item \
| gzip > /backups/orders_$(date +%Y%m%d).sql.gz
Ein häufig übersehenes Detail: mysqldump sichert standardmäßig keine Views mit der korrekten Definer-Klausel, wenn der Backup-User nicht SUPER-Privilegien hat. Mit --no-tablespaces lässt sich verhindern, dass mysqldump Tablespace-Definitionen exportiert, die auf manchen Zielsystemen Fehler verursachen. Für automatisierte MySQL-Backup-Scripts sollte der Exit-Code immer ausgewertet werden — mysqldump gibt leider bei manchen Fehlern trotzdem Code 0 zurück.
Percona XtraBackup: Hot-Backups ohne Downtime
Für Produktionssysteme mit großen Datenmengen ist Percona XtraBackup die bessere Wahl für ein MySQL-Backup. XtraBackup kopiert InnoDB-Datendateien auf physischer Ebene, während der Server läuft — ein echter Hot-Backup ohne Locks und ohne Beeinträchtigung des laufenden Betriebs. Der Prozess läuft in zwei Phasen: Die Backup-Phase kopiert die .ibd-Dateien, die Prepare-Phase rollt offene Transaktionen zurück und macht das Backup konsistent für einen Restore.
-- Full backup with XtraBackup (shell command, not SQL)
xtrabackup \
--backup \
--user=backup_user \
--password=secret \
--target-dir=/backups/full_$(date +%Y%m%d)
-- Prepare the backup (apply redo log, rollback uncommitted transactions)
xtrabackup \
--prepare \
--target-dir=/backups/full_20250102
-- Incremental backup based on previous full backup
xtrabackup \
--backup \
--user=backup_user \
--password=secret \
--incremental-basedir=/backups/full_20250102 \
--target-dir=/backups/inc_$(date +%Y%m%d_%H%M)
-- Prepare incremental: apply base first, then increment
xtrabackup --prepare --apply-log-only --target-dir=/backups/full_20250102
xtrabackup --prepare --target-dir=/backups/full_20250102 \
--incremental-dir=/backups/inc_20250102_1200
Inkrementelle Backups mit XtraBackup sind besonders effizient für das MySQL-Backup-Konzept: Statt täglich die gesamte Datenbank zu kopieren, werden nur die seit dem letzten Backup veränderten InnoDB-Pages gesichert. Für eine 100-GB-Magento-Datenbank bedeutet das typischerweise, dass das inkrementelle MySQL-Backup nur 2–5 GB groß ist, während das vollständige Backup 100 GB belegt. Die Prepare-Phase muss beim Restore alle Inkremente in der richtigen Reihenfolge anwenden — ein falsch angewendetes Inkrement korrumpiert das Backup unwiderruflich.
Wichtig: XtraBackup erfordert, dass InnoDB mit innodb_file_per_table=ON betrieben wird — was bei Magento 2 ohnehin die empfohlene Einstellung ist, da jede Tabelle in einer eigenen .ibd-Datei liegt. Das ermöglicht auch partielle Restores einzelner Tabellen, indem nur die entsprechenden .ibd-Dateien importiert werden. Für MariaDB gibt es eine kompatible Alternative in Form von Mariabackup.
Binary Log und Point-in-Time-Recovery (PITR)
Das binäre Log (Binary Log) ist das mächtigste Werkzeug für granulare MySQL-Backups und Restores. Es protokolliert jede Datenänderung sequenziell und ermöglicht Point-in-Time-Recovery: Du kannst die Datenbank auf einen exakten Zeitpunkt wiederherstellen — beispielsweise 30 Sekunden vor einem versehentlichen DELETE FROM sales_order WHERE 1=1. Diese Situation ist selten, aber wenn sie eintritt, ist PITR der einzige Weg, die Daten vollständig zu retten.
Voraussetzung für PITR ist, dass Binary Logging aktiviert ist und die Logs aufbewahrt werden. MySQL 8 aktiviert Binary Logging standardmäßig mit binlog_format=ROW, ältere Versionen benötigen explizite Konfiguration. Die Aufbewahrungszeit kontrolliert binlog_expire_logs_seconds (MySQL 8) oder expire_logs_days (MariaDB). ROW-basiertes Format ist für PITR bevorzugt, da es die exakten Zeilenänderungen protokolliert — nicht nur die SQL-Statements.
-- Check binary log configuration
SHOW VARIABLES LIKE 'log_bin%';
SHOW VARIABLES LIKE 'binlog_format';
SHOW BINARY LOGS;
-- Find position in binary log for a specific time window
mysqlbinlog \
--start-datetime="2025-01-02 10:00:00" \
--stop-datetime="2025-01-02 11:30:00" \
--base64-output=DECODE-ROWS \
--verbose \
/var/lib/mysql/binlog.000123
-- Apply binary logs from a specific position for PITR
mysqlbinlog \
--start-position=4 \
--stop-datetime="2025-01-02 11:28:45" \
/var/lib/mysql/binlog.000120 \
/var/lib/mysql/binlog.000121 \
/var/lib/mysql/binlog.000122 \
| mysql -u root -p magento_db
Die Kombination aus täglichem Vollbackup (XtraBackup) und stündlicher Binary-Log-Sicherung gibt dir ein Recovery Point Objective (RPO) von maximal einer Stunde. Für Magento-Shops mit hohem Bestellvolumen sollten Binary Logs alle 15 Minuten extern gesichert werden — am besten mit mysqlbinlog --read-from-remote-server direkt auf einen separaten Backup-Server. So sind die Binary Logs auch dann sicher, wenn der Primärserver ausfällt.
Magento-spezifische Backup-Überlegungen
Magento 2 hat einige Eigenschaften, die ein generisches MySQL-Backup-Konzept nicht ausreichend berücksichtigt. Erstens: Magento nutzt ausschließlich InnoDB-Tabellen (außer einige Legacy-Tabellen aus alten Migrationen, die noch im MyISAM-Format vorliegen). Das ist grundsätzlich positiv, weil InnoDB transaktionssicher ist und konsistente Snapshots ermöglicht. MyISAM-Tabellen, falls noch vorhanden, erfordern allerdings ein separates Lock-basiertes Backup und sollten migriert werden.
Zweitens: Einige Magento-Tabellen sind temporärer Natur und können aus dem MySQL-Backup ausgeschlossen werden. Das reduziert die Backup-Größe erheblich, ohne den Restore-Wert zu schmälern. Die ausgeschlossenen Tabellen werden durch Magento-Indexer-Ausführung nach dem Restore automatisch neu befüllt.
-- Identify temporary/index tables that can be excluded from backup
SELECT
TABLE_NAME,
TABLE_ROWS,
ROUND(DATA_LENGTH / 1024 / 1024, 1) AS data_mb,
ENGINE
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'magento_db'
AND TABLE_NAME REGEXP '^(catalog_product_index|search_tmp|session|report_event|report_viewed)'
ORDER BY DATA_LENGTH DESC;
-- mysqldump excluding index/temp tables (adapt table list as needed)
mysqldump \
--single-transaction \
--routines \
--events \
--hex-blob \
--ignore-table=magento_db.catalog_product_index_price \
--ignore-table=magento_db.catalog_product_index_eav \
--ignore-table=magento_db.catalog_product_index_eav_decimal \
--ignore-table=magento_db.report_event \
magento_db | gzip > /backups/magento_clean_$(date +%Y%m%d).sql.gz
Drittens: Die Magento-Konfiguration enthält in core_config_data sensible Werte wie API-Keys, Zahlungsanbieter-Credentials und Zugangsdaten zu Drittdiensten. Ein MySQL-Backup sollte daher immer verschlüsselt gespeichert werden — entweder mit GPG-Verschlüsselung direkt in der Backup-Pipeline oder mit serverseitiger Verschlüsselung im Backup-Storage. Backups im Klartext auf einem freigegebenen NAS-Share zu speichern ist ein erhebliches Sicherheitsrisiko.
Backup-Rotation und Aufbewahrungsstrategien
Eine sinnvolle MySQL-Backup-Rotation folgt dem Großvater-Vater-Sohn-Prinzip (GFS): Täglich wird ein Backup erstellt (Sohn), wöchentlich ein Wochenbackup aufbewahrt (Vater), monatlich ein Monatsbackup archiviert (Großvater). Das gibt dir gleichzeitig granulare kurzfristige Wiederherstellungspunkte und langfristige Archivierung ohne explodierenden Speicherbedarf.
Für Magento empfehle ich folgendes Schema: 7 tägliche Vollbackups on-disk, 4 wöchentliche Backups in einem separaten Storage-Bucket, 12 monatliche Backups in Cold Storage (z.B. AWS Glacier oder Hetzner Storage Box). Binary Logs werden 48 Stunden aufbewahrt, danach gelöscht. Dieses Schema ergibt ein Recovery-Fenster von bis zu 12 Monaten bei überschaubaren monatlichen Speicherkosten — typischerweise unter 20 Euro pro Monat für einen mittelgroßen Shop.
-- Check current binary log retention setting
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';
-- Set binary log retention to 48 hours (MySQL 8)
SET GLOBAL binlog_expire_logs_seconds = 172800;
-- Persist in /etc/mysql/mysql.conf.d/mysqld.cnf:
-- [mysqld]
-- binlog_expire_logs_seconds = 172800
-- Monitor Magento database size growth over time
SELECT
TABLE_SCHEMA,
COUNT(*) AS table_count,
ROUND(SUM(DATA_LENGTH) / 1024 / 1024 / 1024, 2) AS data_gb,
ROUND(SUM(INDEX_LENGTH) / 1024 / 1024 / 1024, 2) AS index_gb,
ROUND(SUM(DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024 / 1024, 2) AS total_gb
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'magento_db'
GROUP BY TABLE_SCHEMA;
Restore-Tests und Backup-Verifikation
Das wichtigste Prinzip im MySQL-Backup-Management: Ein Backup ist nur so gut wie sein letzter erfolgreicher Restore-Test. Backups, die nie getestet wurden, existieren in einem Schrödinger-Zustand — sie könnten funktionieren oder korrumpiert sein. Erst der erfolgreiche Restore auf einem echten System beweist die Integrität des MySQL-Backups.
Der Restore-Test sollte wöchentlich auf einem separaten Testserver oder in einem Docker-Container erfolgen. Für Magento bedeutet das: MySQL-Backup einspielen, Indexer ausführen, und dann gezielt Datenbankabfragen ausführen, die beweisen, dass kritische Tabellen vollständig und konsistent sind. Automatisierte Tests können diesen Prozess vollständig übernehmen und das Ergebnis per Alert melden.
-- Backup verification queries to run after restore on test server
-- 1. Check critical table row counts match production snapshot
SELECT 'catalog_product_entity' AS tbl, COUNT(*) AS rows FROM catalog_product_entity
UNION ALL SELECT 'sales_order', COUNT(*) FROM sales_order
UNION ALL SELECT 'customer_entity', COUNT(*) FROM customer_entity
UNION ALL SELECT 'cms_block', COUNT(*) FROM cms_block
UNION ALL SELECT 'core_config_data', COUNT(*) FROM core_config_data;
-- 2. InnoDB consistency check on critical tables
CHECK TABLE catalog_product_entity, sales_order, customer_entity EXTENDED;
-- 3. Verify latest order date is plausible (not too old)
SELECT
MAX(created_at) AS latest_order,
MIN(created_at) AS first_order,
COUNT(*) AS total_orders
FROM sales_order;
-- 4. Check for orphaned order items (referential integrity)
SELECT COUNT(*) AS orphaned_items
FROM sales_order_item soi
LEFT JOIN sales_order so ON soi.order_id = so.entity_id
WHERE so.entity_id IS NULL;
Restore-Zeit abschätzen und planen
Viele Teams wissen nicht, wie lange ein Restore ihrer Magento-Datenbank dauert — bis der Ernstfall eintritt. Das ist gefährlich, weil der RTO-Wert (Recovery Time Objective) nicht eingehalten werden kann, wenn er nie gemessen wurde. Die Restore-Zeit hängt von drei Faktoren ab: Backup-Größe, Netzwerkbandbreite beim Transfer vom Backup-Storage, und der I/O-Leistung des Zielservers.
Als Faustregel gilt: Ein mysqldump-Restore schafft etwa 1 GB komprimierter Dump pro 5–10 Minuten, je nach Server-Hardware und Tabellenstruktur. XtraBackup-Restore kopiert physische Dateien und kommt auf 200–500 MB/s bei ausreichender I/O-Kapazität. Für eine 50-GB-Magento-Datenbank ergibt das: mysqldump-Restore ca. 60–90 Minuten, XtraBackup-Restore ca. 5–15 Minuten. Diese Zahlen müssen durch echte Tests validiert und im Notfallplan dokumentiert sein. Ohne diese Dokumentation ist der Notfallplan wertlos.
Nach dem Datenbankwiederherstellungsprozess in Magento müssen außerdem die Indexer neu ausgeführt werden (bin/magento indexer:reindex), was je nach Produktanzahl weitere 10–60 Minuten in Anspruch nimmt. Auch der Magento-Cache muss geleert werden. Der gesamte RTO-Wert setzt sich also aus Backup-Transfer, Datenbankimport, Indexer-Run und Cache-Warm-up zusammen — alle diese Faktoren müssen im Disaster-Recovery-Plan berücksichtigt werden.
MySQL-Backup-Konzept für dein Magento-Projekt?
Wir helfen dir, eine robuste Backup- und Recovery-Strategie aufzubauen — von der Planung bis zum automatisierten Restore-Test.
Jetzt Kontakt aufnehmenZusammenfassung
- mysqldump mit
--single-transaction --routines --events --triggers --hex-bloberzeugt konsistente InnoDB-Dumps ohne Table-Locks. - Percona XtraBackup ermöglicht Hot-Backups auf physischer Ebene mit inkrementellen Sicherungen — ideal für Magento-Datenbanken ab 50 GB.
- Binary Log + PITR reduziert den maximalen Datenverlust auf Minuten —
binlog_expire_logs_seconds=172800für 48h Aufbewahrung. - Magento-Index- und Session-Tabellen können vom MySQL-Backup ausgeschlossen werden; sie werden per Indexer-Rebuild wiederhergestellt.
- GFS-Rotation (7 täglich / 4 wöchentlich / 12 monatlich) bietet ein 12-Monats-Fenster bei vertretbarem Speicherbedarf.
- Backups müssen wöchentlich auf einem Testserver wiederhergestellt und per Verifikationsabfragen geprüft werden.
- Restore-Zeiten dokumentieren: mysqldump ca. 5–10 Min/GB, XtraBackup ca. 200–500 MB/s physischer Durchsatz.
- Backups immer verschlüsselt speichern —
core_config_dataenthält sensitive Credentials.
FAQ: MySQL-Backup für Magento
Kann ich mysqldump bei laufendem Magento-Betrieb nutzen?
--single-transaction wird eine Snapshot-Transaktion geöffnet und es entstehen keine Table-Locks auf InnoDB-Tabellen. Der Shop bleibt vollständig nutzbar. Achtung: MyISAM-Tabellen werden trotzdem gelocked — prüfe mit SELECT TABLE_NAME, ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'magento_db' AND ENGINE = 'MyISAM', ob du noch MyISAM-Tabellen hast.Wie groß ist ein typischer Magento-Dump?
report_event, customer_log, activity_log) können den Dump stark aufblähen.Was ist der Unterschied zwischen logischem und physischem MySQL-Backup?
Muss ich auch die Magento-Mediendateien sichern?
pub/media). Für ein vollständiges Recovery brauchst du sowohl das MySQL-Backup als auch ein Dateisystem-Backup. Tools wie rsync, Restic oder Borg eignen sich für inkrementelle Dateisystem-Backups mit Deduplizierung.Wie richte ich PITR in MySQL 8 ein?
log_bin=ON aktiv ist (Standard in MySQL 8), und setze binlog_format=ROW für vollständige Zeilenänderungen. Sichere die Binary Logs regelmäßig mit mysqlbinlog --read-from-remote-server oder durch direktes Kopieren der binlog.*-Dateien auf einen separaten Server. Für einen PITR-Restore: Vollbackup einspielen, dann Binary Logs bis zum gewünschten Zeitpunkt anwenden.Welche Magento-Tabellen können vom MySQL-Backup ausgeschlossen werden?
catalog_product_index_*, catalogsearch_fulltext_*), Session-Tabellen (session) und Report-Event-Tabellen (report_event, report_viewed_product_index). Diese werden durch Indexer-Ausführung nach dem Restore wiederhergestellt. Niemals ausschließen: sales_*, customer_*, catalog_product_entity*, core_config_data, cms_*.Wie sichere ich Stored Procedures und Events mit mysqldump?
--routines exportiert mysqldump alle Stored Procedures und Functions. Mit --events werden MySQL Events (Scheduled Events) gesichert. Beides ist standardmäßig deaktiviert und muss explizit angegeben werden. Prüfe nach dem Restore mit SHOW PROCEDURE STATUS WHERE Db = 'magento_db' und SHOW EVENTS, ob alle Datenbankobjekte korrekt importiert wurden.Was passiert, wenn ein mysqldump während der Ausführung fehlschlägt?
$? nach dem Befehl UND überprüfe die Größe der Ausgabedatei. Ein leeres oder ungewöhnlich kleines Dump-File ist ein sicheres Zeichen für einen fehlgeschlagenen MySQL-Backup. Leite stderr immer in eine Log-Datei um: mysqldump ... 2>/backups/mysqldump_error.log.Wie verschlüssele ich MySQL-Backups sicher?
mysqldump ... | gzip | gpg --encrypt --recipient backup@example.com > backup.sql.gz.gpg. Alternativ bieten Backup-Tools wie Restic oder Borg eingebaute Verschlüsselung. Cloud-Storage (S3, GCS, Hetzner) sollte mit Server-Side-Encryption aktiviert werden. Den privaten GPG-Schlüssel niemals auf dem gleichen Server wie die Backups speichern.