Wenn MySQL stirbt…

Es begann harmlos: In meiner Friendica-Instanz wurde ein Bild nicht geladen. Als ich mir das genauer ansah, stellte sich heraus, dass das Bild aus der Datenbank gezogen wurde und dabei ein Mysql Server gone produzierte. Im Log von MySQL tauchten dazu so hässliche Meldungen wie diese auf:

[...]
Some pointers may be invalid and cause the dump to abort.
Query (7feb68c6ba50): is an invalid pointer
Connection ID (thread ID): 6
Status: NOT_KILLED
[...]

Bei dem NOT_KILLED blieb es nicht immer, nach ein paar weiteren Versuchen war der MySQL-Server tatsächlich tot … liess sich aber noch neu starten. Die naheliegende Rettungsmöglichkeit Backup einspielen scheiterte daran, dass seit einiger Zeit das Backup via mysqldump abgebrochen war und zwar in der Friendica-Tabelle conversation.

Also musste ich reparieren.

Um nicht noch mehr Datenverlust zu riskieren, habe ich erst mal das Datenverzeichnis kopiert:

cp -rfv /var/lib/mysql /var/lib/mysql$(date +%s)

Danach veruschte ich zu retten, was zu retten ist. Im Error-Log von MySQL wurde ich auf http://dev.mysql.com/doc/refman/5.7/en/forcing-innodb-recovery.html verwiesen … das funktionierte nur leider nicht.

Nächster Versuch: da ich durch das Backup etwa wusste, ab welchem Datensatz etwas kauptt war, versuchte einfach ab dort ein paar Datensätze zu löschen. Ergebnis: der MySQL Server fiel komplett aus und lissß sich nicht mehr starten. In dem Moment war ich wirklich froh vorher das Datenverzeichnis in Sicherheit gebracht zu haben.

Die Lösung war dann recht rüde: ich habe conversation per TRUNCATE geleert und danach noch photo (gleicher Fehler).Jetzt liess sich endlich ein Dump ziehen. Noch schnell die Datenbank gelöscht und via Dump neu aufgesetzt. Alles lief danach wieder normal … magischerweise sogar Friendica, jedenfalls weitestgehend.

Was habe ich daraus gelernt?

  1. Mache von jeder Datenbank auf deinem Server ein einzelnes Backup (--all-databases ist eine schlechte Idee)
  2. Kontrolliere den Rückgabestatus von mysqldump

Oder als Skript (vereinfachte Kurzfassung):

doBackup () {
   mysqldump -u $1 -p$2 $3 > $3.dump
   if [[ $? -eq 0 ]]; then
     gzip $3.dump
   else
     echo >&2 "backup of $3 failed"
     exit 1
   fi
 }

doBackup "USER" "PASSWORD" "DB
 […]