„mysqldump: Got error: 145 … when using LOCK TABLES“: eine beschädigte MyISAM-Tabelle und eine Woche leerer Backups

Das Cron-Skript schrieb sieben Nächte lang statt rund 280 MB eine Datei mit 751 B: Eine MyISAM-Tabelle war als beschädigt markiert, mysqldump brach bei LOCK TABLES ab, das Skript endete mit Code 0, Cron verwarf die Meldung. Wir haben den Ausfall nachgestellt, die Tabelle repariert, auf InnoDB umgestellt und ein Backup eingeführt, das jede Nacht probeweise zurückspielt und Alarm gibt.

  • Backup-Datei: 751 B statt rund 280 MB, Skript mit Code 0
  • mysqldump mit Code 2, Meldung von Cron verworfen (No MTA installed)
  • Neues Backup: Probe-Wiederherstellung von 48 Tabellen in 32 bis 34 s, jede Nacht
Liste von neun Backup-Dateien mit derselben Uhrzeit 01:30. Die beiden oberen Zeilen haben einen langen schwarzen Balken und die Größe 285 MB, die sieben folgenden nur eine kurze orange Marke und die Größe 751 B

Docker-Server mit MySQL 5.7.44 und mehreren WordPress-Datenbanken, darunter ein WooCommerce-Shop

Branche: Handel

Ausgangslage

Auf einem Docker-Server mit MySQL 5.7.44 liefen mehrere WordPress-Websites, darunter ein WooCommerce-Shop, mit Tabellen in der alten Speicher-Engine MyISAM. Ein Bash-Skript auf dem Host schrieb jede Nacht jede Datenbank in eine eigene Datei <datenbank>.sql, ohne Datum im Namen. Der Kunde prüfte, ob die Backups entstehen. So lief es drei Jahre lang.

Dann musste die Shop-Datenbank zurückgespielt werden. Die Backups der letzten sieben Nächte hatten je 751 Byte statt 200 bis 300 MB: Kopfzeilen, CREATE DATABASE, USE, Ende. Erst das Backup von vor acht Tagen war vollständig. Website und Backend liefen die ganze Zeit, Skript und Cron meldeten keinen Fehler.

Die Aufgabe: klären, warum die Backups leer waren, obwohl alles funktionierte, die Ursache beseitigen und ein Backup aufbauen, das selbst beweist, dass man damit zurückkommt.

Lösung

Die Datei mit 751 B selbst verriet am meisten: Der Dump brach vor der ersten Tabelle ab, er hatte keine leere Datenbank gesichert. Wir haben den Server des Kunden mit derselben Datenbankversion und derselben Art von Skript nachgebaut und den Ausfall so ausgelöst, wie er in der Praxis passiert: volle Datenbankplatte während des Shopbetriebs, danach ein Neustart des Containers. Ergebnis: eine Datei, die bis aufs Byte genauso aufgebaut ist wie die des Kunden.

Wir haben die beschädigte Tabelle repariert und alle übrigen geprüft, die Datenbanken auf InnoDB umgestellt und das Backup neu geschrieben: Exit-Code, Endmarke des Dumps, Größe und danach eine Probe-Wiederherstellung jeder Datenbank in eine eigene MySQL-5.7.44-Instanz mit Abgleich von Tabellen und Zeilen. Erst ein geprüftes Backup bekommt einen Namen mit Datum, jeder Fehler löst eine E-Mail aus. Dazu ein Wiederanlaufplan, auf einem leeren Server geübt (Stand 2026-11).

Ergebnisse

Shop-Backup bei beschädigter Tabelle
751 B über sieben Nächte mit Code 0, jetzt E-Mail-Alarm in der ersten Nacht mit Code 1
Letztes gutes Backup
14 Tage Historie, kein Backup wird überschrieben
Probe-Wiederherstellung der Shop-Datenbank
48 Tabellen und 3,2 Mio. Zeilen in 32 bis 34 s, jede Nacht
Komplettes Backup mit Probe-Wiederherstellung
65 s für drei Datenbanken einschließlich Testinstanz
Reparatur der beschädigten Tabelle
0,47 s REPAIR TABLE, 2,1 s Prüfung aller Tabellen
Wiederaufbau des Shops auf leerem Server
50 s ab leerer Instanz, die Übung zeigte 3 Lücken in den Backups

So sind wir vorgegangen

  1. Die Datei mit 751 B Zeile für Zeile

    Sandbox-Marke des MariaDB-Clients, keine Kommentare, keine Schlusszeilen, Ende nach USE. Der Dump brach vor der ersten Tabelle ab, die Datenbank war nicht leer.

  2. Das Serverlog

    Rund 70 Zeilen „marked as crashed“ und „Checking table:“ in einer Sekunde nach dem Neustart: Meldungen von MyISAM und die eingeschaltete automatische Tabellenprüfung.

  3. Nachbau der Umgebung

    MySQL 5.7.44 in Docker mit MyISAM-Tabellen, drei WordPress-Websites, ein WooCommerce-Shop mit 8 000 Produkten und 32 400 Bestellungen, dieselbe Art von Cron-Skript auf dem Host mit dem MariaDB-Client aus Debian 12.

  4. Ein echter Ausfall, ohne Dateien zu bearbeiten

    Volles Datenbank-Volume während des Shopbetriebs, danach docker stop. Drei Durchläufe desselben Szenarios, in zwei davon eine dauerhaft beschädigte Tabelle.

  5. Backup und Website bei beschädigter Tabelle

    Das alte Cron-Skript, drei Varianten von mysqldump, Shop- und Backend-Seiten, der Gast-Warenkorb über die WooCommerce Store API.

  6. Wiederherstellungsversuch

    Die Datei mit 743 B und ein vollständiger Dump in ein frisches MySQL 5.7.44 mit den Clients mysql 5.7.44, 8.0.46, 8.4.13 und mariadb 10.11, ein Dump aus dem älteren mariadb-dump 10.11.8, der Client aus Debian 13.

  7. Reparatur, neues Backup und Übung

    REPAIR TABLE und Prüfung aller Tabellen, Umstellung auf InnoDB, das neue Skript auf der gesunden und der beschädigten Datenbank, Wiederaufbau des ganzen Shops auf einem leeren Server mit Zeitmessung.

Was mysqldump schreibt, wenn eine von 48 Tabellen beschädigt ist (Reproduktion, Stand 2026-11)

Variante Exit-Code Datei Tabellen in der Datei Dateiende
Standard, --lock-tables 2 743 B 0 von 48 nach USE, ohne Schlusszeilen
--force 2 210 083 890 B 47 von 48 normale Schlusszeilen
--single-transaction 2 210 078 388 B 42 von 48, abgebrochen an der Sitzungstabelle mitten im Dump abgeschnitten
Standard nach REPAIR TABLE 0 285 934 637 B 48 von 48 normale Schlusszeilen

Herausforderungen, die wir gelöst haben

Website und Backend liefen, Skript und Cron meldeten keinen Fehler. Unten die Meldungen so, wie MySQL, mysqldump, WordPress und Cron sie geschrieben haben. In den Unterlagen des Kunden ist der Datenbankname durch <datenbank> ersetzt, in der Reproduktion heißt die Shop-Datenbank sklep.

Die genauen Meldungen

Die Backup-Datei des Kunden, 751 B, der ganze Inhalt:

/*M!999999\- enable the sandbox mode */

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `<datenbank>` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `<datenbank>`;

Die erste Zeile ist die Marke des Sandbox-Modus, die nur der MariaDB-Client schreibt. Den Dump erstellte also mysqldump aus dem Paket mariadb-client auf dem Host (unter Debian 12 ein Link auf mariadb-dump), nicht das Werkzeug aus dem MySQL-Container. Fehlende Kommentare bedeuten --skip-comments, das auch die Endmarke -- Dump completed on … entfernt. Fehlende Schlusszeilen bedeuten, dass der Dump abgebrochen ist: Eine leere Datenbank ergibt eine Datei mit Schlusszeilen (in der Reproduktion 1 173 B).

Das Serverlog des Kunden nach dem Neustart, rund 70 Zeilen in derselben Sekunde:

[ERROR] mysqld: Table './<datenbank>/wp_options' is marked as crashed and should be repaired
[ERROR] mysqld: Table './<datenbank>/wp_postmeta' is marked as crashed and should be repaired
[Warning] Checking table:   './<datenbank>/wp_postmeta'
[ERROR] mysqld: Table './<datenbank>/wp_woocommerce_sessions' is marked as crashed and should be repaired
[Warning] Checking table:   './<datenbank>/wp_woocommerce_sessions'

Checking table: erscheint nur, wenn myisam-recover-options eingeschaltet ist. Im Image mysql:5.7.44 steht es standardmäßig auf OFF, der Server des Kunden hatte es also in der Konfiguration.

Reproduktion: volle Platte. MyISAM gibt keinen Fehler zurück, sondern wartet auf Platz und hält die Tabellensperre, während die Startseite weiter antwortet:

[ERROR] Disk is full writing './sklep/wp_woocommerce_sessions.MYD' (Errcode: 15795968 - No space left on device). Waiting for someone to free space...
[ERROR] Retry in 60 secs. Message reprinted in 600 secs

Neustart des Datenbank-Containers, die typische Reaktion. Docker gibt dem Prozess 10 s, danach SIGKILL:

$ docker stop db        # 10,5 s, ExitCode 137
[Note] Giving 7 client threads a chance to die gracefully
[Warning] mysqld: Forcing close of thread 31  user: 'sklep'
[ERROR] mysqld: Incorrect key file for table './sklep/wp_woocommerce_sessions.MYI'; try to repair it
[ERROR] Got an error from thread_id=31, .../storage/myisam/mi_write.c:232

Die Sitzungsbereinigung von WooCommerce einige Stunden später:

WordPress database error Incorrect key file for table './sklep/wp_woocommerce_sessions.MYI'; try to repair it for query DELETE FROM wp_woocommerce_sessions WHERE session_expiry < 1793638328 ORDER BY session_expiry LIMIT 100 made by ... wc_cleanup_session_data, WC_Session_Handler->cleanup_sessions

Ab diesem Moment endet jedes erneute Öffnen der Tabelle mit:

ERROR 145 (HY000): Table './sklep/wp_woocommerce_sessions' is marked as crashed and should be repaired

Das Backup aus dem Cron bei beschädigter Tabelle, Ausgabe des alten Skripts:

Kopia bazy blog
Kopia bazy firma
Kopia bazy sklep
mysqldump: Got error: 145: "Table './sklep/wp_woocommerce_sessions' is marked as crashed and should be repaired" when using LOCK TABLES
Kopia zakonczona: Mon Nov  2 16:53:55 UTC 2026
kod wyjscia skryptu: 0
CRON[107]: (root) CMD ([108] /root/skrypty/backup-mysql.sh)
CRON[107]: (CRON) info (No MTA installed, discarding output)
CRON[107]: (root) END ([108] /root/skrypty/backup-mysql.sh)

Die Shop-Datei schrumpfte von 285 757 704 B auf 743 B, mit aktuellem Datum. Mit einem Datenbanknamen in der Länge des Kundennamens ergibt sich exakt 751 B.

Die Beschädigung wirkt wie ein Zünder mit Verzögerung

Nach dem Neustart lief alles, und das Backup mit 285 MB gelang. Die Tabelle bekam die Markierung erst, als die Sitzungsbereinigung von WooCommerce (alle 12 Stunden) auf den inkonsistenten Index traf, und das Öffnen scheiterte erst, nachdem die Tabelle neu geöffnet wurde. Die Backups fallen Stunden oder Tage nach dem Ausfall aus, wenn niemand mehr eine Verbindung herstellt. Den Datenbankprozess nur zu beenden, beschädigte die Tabelle nicht dauerhaft; das schaffte erst die volle Platte mit docker stop, und ein dritter Durchlauf desselben Szenarios endete nur mit einer Warnung. Ob ein Neustart eine Tabelle beschädigt, hängt vom Moment ab.

Wer repariert, was sichtbar ist, lässt den Rest liegen

Im zweiten Durchlauf fiel auch wp_options aus, und der Shop zeigte „Error establishing a database connection“. Das WordPress-Werkzeug wp-admin/maint/repair.php prüft nur 12 Kerntabellen und das, was Plugins über den Filter tables_to_repair ergänzen; WooCommerce ergänzt nichts. Die Website kam zurück, die beschädigte Sitzungstabelle blieb. Dazu meldete das Werkzeug „Failed to repair the wp_options table“, obwohl die Tabelle repariert war: Es liest nur die erste Zeile des Ergebnisses von REPAIR TABLE, status OK steht in der letzten. Auch mysqlcheck --all-databases --check schrieb Corrupt und endete mit Code 0, als Prüfung im Monitoring also wertlos.

Eine Tabelle hält die ganze Datenbank auf, und „Abhilfen“ liefern schlechtere Dateien

Mit dem Standard --lock-tables beginnt der Dump mit einem einzigen LOCK TABLES auf alle Tabellen der Datenbank, eine markierte Tabelle stoppt also alle. Eine Datei mit 743 B fällt auf, wenn jemand auf die Größe schaut. --force liefert 210 MB ohne eine Tabelle und mit normalem Ende, --single-transaction 210 MB, mitten in der Tabellenliste abgeschnitten. Beide sehen aus wie ein Backup. Die Teildatei des neuen Skripts hatte 82 % der Größe des vorigen Backups, hätte also die verbreitete Schwelle „Alarm unter 80 %“ bestanden.

Das Dateidatum beweist nichts, und ein Name ohne Datum zerstört das letzte gute Backup

Die Shell kürzt die Datei bei > <datenbank>.sql, bevor mysqldump überhaupt verbindet. Die Datei hat jede Nacht ein frisches Datum, und die erste missglückte Nacht ersetzt das letzte gute Backup. Die vollständige Version von vor acht Tagen musste aus einer anderen Sicherung des Servers kommen.

Skript und Cron melden Erfolg

mysqldump liefert 2, das Skript 0, weil der letzte Befehl ein echo ist. Die Meldung geht auf stderr, Cron will sie per E-Mail schicken, auf dem Host gibt es keinen Mailserver, also verwirft Cron sie und protokolliert nur END, ohne Exit-Code.

Website und Backend zeigen nichts

Bei beschädigter Sitzungstabelle antworteten Startseite, Shop, Produktseite, Suche, Login und alle geprüften Backend-Seiten mit 200 und ohne Meldung. Das einzige Symptom: Der Gast-Warenkorb hatte nach dem Hinzufügen eines Produkts 0 Positionen. Die einzige Spur im Backend ist WooCommerce, Status, Datenbank, wo die beschädigte Tabelle als fehlend gilt: „Missing base tables: wp_woocommerce_sessions“.

Ein leeres Backup lässt sich „erfolgreich“ einspielen, und Backups können ohne Ausfall versagen

Das Einspielen der Datei mit 743 B endet in jedem geprüften Client mit Code 0 und einer leeren Datenbank: mysql 5.7.44, 8.0.46, 8.4.13 und mariadb 10.11. Die Sandbox-Marke aus der Datei des Kunden (/*M!) stört MySQL-Clients nicht, Dumps aus dem älteren mariadb-dump 10.11.8 beginnen aber mit /*! und spielen nichts ein:

ERROR at line 1: Unknown command '\-'.

Und nach dem Upgrade des Hosts auf Debian 13 (mariadb-client 11.8.6) scheitert dasselbe Skript schon an der Liste der Datenbanken, weil neuere MariaDB-Clients das Serverzertifikat standardmäßig prüfen und MySQL 5.7 ein selbstsigniertes hat. Null Dateien, Code 0, „Kopia zakonczona“:

ERROR 2026 (HY000): TLS/SSL error: Certificate verification failure: The certificate is NOT trusted.
Kette aus fünf Gliedern mit orangen Verbindern: Festplatte mit der Aufschrift 100 %, Indexdatei mit der Aufschrift .MYI und einem Riss, Fahne mit der Aufschrift crashed, Schloss mit der Aufschrift LOCK TABLES 145 und eine kurze Datei mit den Aufschriften 751 B und exit 0

Reparatur und ein Backup, das selbst prüft, ob man damit zurückkommt

Reparatur und Prüfung aller Tabellen

mysqlcheck -h db -uroot -p --all-databases --check --silent     # 2,1 s, gibt nur Probleme aus
REPAIR TABLE sklep.wp_woocommerce_sessions;
-- info     Found block that points outside data file at 70053148
-- warning  Number of rows changed from 74527 to 74695
-- status   OK                                          (0,47 s)
CHECK TABLE sklep.wp_woocommerce_sessions;               -- status OK

Nach der Reparatur schrieb das alte Skript wieder 285 934 637 B, und der Gast-Warenkorb hatte 1 Position. Das Ergebnis von mysqlcheck muss man lesen, nicht den Exit-Code.

InnoDB statt MyISAM

InnoDB stellt nach einem harten Abschalten aus seinem Log einen konsistenten Stand wieder her und erlaubt einen konsistenten Dump ohne Tabellensperren (--single-transaction). Dasselbe Szenario mit voller Platte nach der Umstellung: InnoDB wartet nicht, sondern lehnt den Schreibvorgang sofort ab.

[ERROR] InnoDB: posix_fallocate(): Failed to preallocate data for file ./sklep/wp_woocommerce_sessions.ibd, desired size 4194304 bytes. Operating system error number 28. Check that the disk is not full or a disk quota exceeded. ...
[ERROR] mysqld: The table 'wp_woocommerce_sessions' is full

Während die Platte voll war, endeten 2 752 von 4 777 Anfragen (58 %) mit Code 500. Dafür dauerte docker stop 4,1 s und endete sauber, und nach dem Freigeben von Platz meldete mysqlcheck kein Problem. Ein sichtbarer Fehler für ein paar Minuten statt eines unsichtbaren für eine Woche.

Die Falle bei der Umstellung: Der Standard-sql_mode von MySQL 5.7 enthält NO_ZERO_DATE, NO_ZERO_IN_DATE und STRICT_TRANS_TABLES, die Spalten von WordPress haben DEFAULT '0000-00-00 00:00:00'. Ein einfaches ALTER TABLE scheiterte an 19 von 72 Tabellen:

ERROR 1067 (42000) at line 1: Invalid default value for 'post_date'

WordPress setzt sich in der Sitzung einen milderen Modus, deshalb fällt das im Alltag nicht auf. Die Umstellung läuft im Wartungsfenster, weil ALTER TABLE die Tabelle kopiert und Schreibzugriffe sperrt:

SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION';
ALTER TABLE sklep.wp_posts ENGINE=InnoDB;   -- und so für jede MyISAM-Tabelle
DatenbankDauer der UmstellungDaten und Indizes vorher und nachher
sklep, 48 Tabellenca. 95 s393,5 MB und 627,9 MB
blog3,6 s11,3 MB und 15,4 MB
firma2,7 s0,5 MB und 1,2 MB

In der Konfiguration steht default-storage-engine wieder auf InnoDB, damit neue Plugin-Tabellen nicht als MyISAM entstehen, und innodb_buffer_pool_size passen wir an den Arbeitsspeicher an, weil die Shop-Datenbank nach der Umstellung größer ist als die standardmäßigen 128 MB.

Das neue Backup: die wichtigsten Stellen im Skript

set -uo pipefail
# Dump mit dem Werkzeug aus dem Datenbank-Container: dieselbe Version wie der Server, keine Überraschungen des MariaDB-Clients
docker exec -e MYSQL_PWD="$DB_PASS" "$DB_CONTAINER" mysqldump -uroot --single-transaction --quick \
    --routines --triggers --events --default-character-set=utf8mb4 --databases "$db" 2> "$dir/.stderr" | gzip -6 > "$part"
rc=("${PIPESTATUS[@]}")
[ "${rc[0]}" = 0 ] && [ "${rc[1]}" = 0 ] || fail "$db" "mysqldump kod ${rc[0]}, gzip kod ${rc[1]}"
# Vollständigkeit: mysqldump schreibt diese Marke nur nach erfolgreichem Ende (deshalb ohne --skip-comments)
zcat "$part" | tail -n 1 | grep -q '^-- Dump completed' || fail "$db" "brak znacznika '-- Dump completed'"
# Größe gegenüber dem vorigen erfolgreichen Backup
[ $(( size * 100 / psize )) -ge 80 ] || fail "$db" "kopia ma $ratio% rozmiaru poprzedniej"
# Probe-Wiederherstellung in eine frische Instanz mysql:5.7.44 und Abgleich mit der Produktion
zcat "$part" | docker exec -i -e MYSQL_PWD=test "$TEST_CONTAINER" mysql -uroot || fail "$db" "przywrócenie nie powiodło się"
#   Tabellenliste identisch, Zeilen: Tabellen > 1000 Zeilen mindestens 90%, kleinere ±5, wp_options/siteurl lesbar
# erst jetzt der Zielname mit Datum; frühere Backups werden nie überschrieben
mv "$part" "$dir/$db-$STAMP.sql.gz"

Dazu ein Export der Konten und Rechte (SHOW CREATE USER, SHOW GRANTS), weil die Datenbank mysql nicht in den Dumps der Anwendungen steckt; Rotation über 14 Tage; bei jedem Fehler eine E-Mail per SMTP ohne lokalen Mailserver und Exit-Code 1; nach Erfolg ein Signal an ein externes Monitoring, das Alarm gibt, wenn das Backup gar nicht startet.

DatenbankDumpDatei .sql.gzProbe-Wiederherstellung
sklep4 bis 5 s33,4 MB48 Tabellen, 3 175 139 Zeilen, 32 bis 34 s
blogbis 1 s1,9 MB12 Tabellen, 12 067 Zeilen, 2 s
firmaunter 1 s88 kB12 Tabellen, 361 Zeilen, 1 s

Der ganze Lauf für drei Datenbanken einschließlich Start der Testinstanz: 65 s. Dasselbe Skript auf einer Kopie der Datenbank mit beschädigter MyISAM-Tabelle (die Meldungen des Skripts sind polnisch):

=== sklep 18:26:33
UWAGA: sklep ma 48 tabel innych niz InnoDB (zrzut bez spojnosci transakcyjnej dla nich)
mysqldump: Couldn't execute 'show create table `wp_woocommerce_sessions`': Table './sklep/wp_woocommerce_sessions' is marked as crashed and should be repaired (145)
BLAD [sklep]: mysqldump kod 2, gzip kod 0: ...
KONIEC Z BLEDAMI: 1

Die E-Mail mit der Fehlermeldung kam in derselben Minute an. Die beiden vorigen Shop-Backups blieben unberührt, die Teildatei blieb als .part für die Diagnose liegen.

Bahn von einer Datenbank durch vier Schranken mit Haken, beschriftet exit 0, Dump completed, 80 % und restore, die Schranke restore orange, am Ende eine Datei mit Datum; von den Schranken führt eine Linie nach unten zu einem Alarm-Umschlag

Wiederanlaufplan und Test des ganzen Shops

Der Plan passt auf eine Seite und liegt außerhalb des Servers:

  • Ziele: wie viele Daten verloren gehen dürfen (bei einem nächtlichen Backup bis zu 24 Stunden) und wie lange der Shop stehen darf.
  • Was im Backup steckt: Datenbanken, Konten und Rechte der Datenbank, Dateien der Websites (wp-content, wp-config.php), Compose-Dateien und Konfiguration der Dienste, Versionen der Images. Ein Datenbank-Backup ist kein System-Backup.
  • Wo: mindestens ein Backup außerhalb des Servers und außerhalb des Kontos, von dem aus man es löschen kann.
  • Ablauf Schritt für Schritt, mit Passwörtern an einem eigenen, bekannten Ort, und eine verantwortliche Person.
  • Test: jede Nacht eine automatische Probe-Wiederherstellung der Datenbanken, einmal im Quartal der Wiederaufbau des Ganzen auf einer leeren Maschine mit Zeitmessung.

Der Test des Ganzen: eine leere Instanz MySQL 5.7.44, die neuesten Backups der drei Datenbanken, die Konten, das Dateiarchiv des Shops, ein frischer WordPress-Container.

SchrittZeit ab Start
leeres MySQL 5.7.44 bereit12,7 s
Import der Shop-Datenbank (31,7 MB gz)44,8 s
Import der Datenbanken firma und blog, Konten und Rechte47,9 s
Dateien des Shops entpackt (204 MB)48,7 s
Shop antwortet mit 200, Store API liefert 8 000 Produkte50,2 s

Was die Übung gezeigt hat, jeder Effekt einzeln geprüft:

  • Ohne Datenbankkonten startet der Shop nicht: „Error establishing a database connection“, HTTP 500. Dumps mit --databases enthalten keine Konten aus der Datenbank mysql, daher der eigene Export der Konten im neuen Skript.
  • Unter einer neuen Adresse leitet WordPress (301) auf die Adresse aus siteurl um. Für den Test braucht es den Host-Header wie in der Produktion oder einen Eintrag in hosts.
  • Plugins, die Compose von außerhalb des Website-Verzeichnisses einbindet, fehlten im Dateiarchiv. Der wiederhergestellte Shop lief, aber ohne zwei Must-use-Plugins mit Shop-Logik, und nichts meldete einen Fehler. Das Datei-Backup muss alle Pfade aus volumes: der Compose-Datei umfassen.
Fünf Balken auf einer Zeitachse von 0 bis 50 s, einer je Schritt des Wiederaufbaus: mysqld bis 12,7 s, import bis 44,8 s, GRANT bis 47,9 s, wp-content bis 48,7 s und ein oranger Balken HTTP 200 bis 50,2 s

Was wir daraus mitnehmen

  • Ein Backup, aus dem niemand zurückgekommen ist, ist nur eine Datei. Die Datei entstand drei Jahre lang jede Nacht, und ihr Inhalt hörte ohne jedes Signal auf zu stimmen.
  • Exit-Code, Endmarke des Dumps und Größe sind das Minimum, aber sie reichen nicht. Ein Teil-Dump hätte die Größenschwelle bestanden. Entscheidend ist erst das automatische Einspielen in eine eigene Datenbank und der Abgleich mit der Produktion.
  • Ein Ausfall beschädigt Backups mit Verzögerung. Nach jedem Vorfall mit Platte oder Stromversorgung prüfen wir alle Tabellen, nicht nur die, die die Website lahmgelegt haben.
  • Ein Wiederanlaufplan taugt erst nach der ersten Übung auf einer leeren Maschine. Erst sie zeigt, was in den Backups fehlt. Solche Funde sind typisch bei der Übernahme und Wartung eines Systems.

Die Arbeit an der Shop-Datenbank selbst, vom Abfrageplan bis zu den Indizes, beschreibt das Projekt SQL-Indizes, eine auf dem Produktivserver vorbereitete und durchgeführte Änderung das Projekt ColdFusion 2025.

Sie sind nicht sicher, ob sich Ihr Datenbank-Backup zurückspielen lässt? Wir prüfen das mit einer Probe-Wiederherstellung auf einem eigenen System, ohne Änderungen an der Produktivdatenbank, und zeigen, was in den Backups fehlt. Der erste Schritt ist ein Erstgespräch.

Quellen

Versionen und Standardwerte haben wir in der Reproduktion geprüft; die Beschreibung der Optionen stammt aus der Dokumentation der Hersteller (Stand: 2026-11):

Vorher und nachher. Links eine kurze Datei mit den Aufschriften 751 B und exit 0 und ein durchgestrichener Umschlag. Rechts eine Datei mit Datum, ein Haken mit der Aufschrift restore 48/48 und ein oranger Alarm-Umschlag

Der erste Schritt: Datenbank-Check mit Wiederherstellungstest

Datenbank-Check: MySQL und MariaDB

Für Unternehmen, deren Anwendung an einer MySQL- oder MariaDB-Datenbank hängt und die wissen wollen, was bei einem Ausfall passiert und ob sich die Daten von gestern wirklich wiederherstellen lassen.

  • Sicherungen: was gesichert wird, wie oft und wo die Kopien liegen
  • ein Wiederherstellungstest auf einem getrennten System, mit gemessener Dauer
  • Replikation und Ausfallsicherheit: was es gibt und was fehlt
  • die langsamsten Abfragen und fehlende Indizes
  • Version, Support-Stand und Konfiguration
  • Empfehlung: Sicherung, Replikation oder Cluster, je nach Bedarf

Ein Cluster wie MariaDB Galera schützt vor dem Ausfall eines Servers, nicht vor gelöschten Daten. Dafür braucht es geprüfte Sicherungen. Deshalb beginnen wir mit dem Wiederherstellungstest. Auf welchem System er läuft, legen wir mit Ihnen fest. An Ihrer Produktivdatenbank ändern wir nichts.

Was das Ergebnis enthält

Ein schriftlicher Befund mit dem Ergebnis des Wiederherstellungstests, den Risiken nach Priorität und einer Empfehlung mit Aufwand. Der Befund gehört Ihnen. Auf Wunsch richten wir die Lösung danach ein, auch einen Galera-Cluster.

ab 1.900 € zzgl. USt.

In der Regel 2 Werktage

Datenbank-Check anfragen

Verwandte Ausgangslagen

  • Ihr System läuft, aber niemand kennt es genau. Wir erfassen Anwendung, Datenbank, Server und E-Mail, bewerten Risiken, empfehlen schriftlich den weiteren Weg und übernehmen auf Wunsch den Betrieb.

  • Wir ziehen Ihre Lucee-, ColdFusion- oder PHP-Anwendung vom klassischen Hosting in Container um, ohne sie neu zu schreiben. So lässt sich die Umgebung nachbauen, aktualisieren und verlegen. Manche Hoster berechnen Aufschläge für alte PHP-Versionen, für PHP 8.2 enden die Sicherheits-Updates am 31.12.2026 (Stand: 2026-10).

  • Der Support für Debian 11 endete am 31.08.2026, der für CentOS 7 am 30.06.2024 (Stand: 2026-10). Wir bringen Ihren Server auf den aktuellen Stand oder planen den Umstieg auf Debian und führen ihn durch. Ebenso arbeiten wir mit Proxmox VE 8 und mit physischen Servern, die wir auf Proxmox umziehen.

Weitere Projekte

  • Rahmen Connector/J 5.1.44 mit zwei Verbindungen: zum Server 5.5.5-10.11.19-MariaDB gerade mit Haken, zum Server 11.8.8-MariaDB gestoppt an einem orangen Schloss TLSv1.1 mit Kreuz

    ColdFusion nach dem MariaDB-Update: Connector/J 5.1 und der Wechsel zu MariaDB Connector/J

    Nach dem Wechsel von MariaDB 10.11 auf einen neueren Zweig verband sich ColdFusion mit dem von Hand eingespielten MySQL Connector/J 5.1.44 nicht mehr: Jede Abfrage endete nach 4 s mit „Could not create connection to database server“. Schuld war die neue Versionskennung des Servers, wegen der der Treiber TLS in einer Version einschaltete, die Java 21 sperrt. Ein Skript stellte alle Datenquellen um.

  • Zwei Panels: WordPress + Elementor und Craft CMS in einem orangen Rahmen, in jedem drei Balken für JS, SQL und PHP-Dateien; die Craft-Balken sind kürzer, der JS-Balken verschwindet fast

    WordPress oder Craft CMS: dieselben drei Websites in beiden Systemen gebaut und gemessen

    Drei Firmenwebsites, zuvor auf WordPress mit kostenlosem Elementor neu gebaut, haben wir in Craft CMS 5 von Grund auf nachgebaut: Inhalt, WebP-Dateien und Server identisch, Optik 1:1. Craft liefert 5 statt 97 bis 129 KB JavaScript und braucht bei ähnlicher TTFB weniger als halb so viele SQL-Abfragen. Als typisches WordPress mit 9 bis 21 Plugins hatten die Websites Lighthouse mobil 30 bis 72.

In 20 Minuten klären wir, welcher erste Schritt zu Ihrem System passt

Sie schildern Ziel und Stand, wir sagen offen, ob und wie wir helfen können. Antwort innerhalb eines Werktags, unverbindlich.

Telefon (Deutsch, Polnisch, Englisch) +48 501 250 220
E-Mail E-Mail

Erreichbar: Montag bis Freitag, 9:00 bis 17:00 Uhr (MEZ); Support und Notfälle rund um die Uhr (24/7)