Artikel

Der erste Datenverlust: eine Welt, keine Sicherung

Ein abgebrochener Kopiervorgang, eine kaputte Regionsdatei und sechs Wochen Bauzeit, die weg waren. Was ich über Sicherungen gelernt habe, als es zu spät war.

BlackZackBlackzack

1091 Wörter · 5 Min. Lesezeit

  • minecraft
  • backups
  • fehler

Es war ein Samstagabend, und ich wollte nur schnell die Welt kopieren, bevor ich ein neues Plugin ausprobiere. Das war der vernünftige Teil des Abends. Alles danach war es nicht.

Ich habe den Ordner world per Explorer auf eine externe Festplatte gezogen, während der Server lief. Der Kopiervorgang lief, ich habe nebenbei das Plugin eingerichtet, der Server hat gespeichert, der Kopiervorgang war irgendwann fertig, ich habe die Festplatte abgezogen. Am nächsten Tag fehlte im Spiel ein Stück Landschaft — genauer gesagt fehlten mehrere Chunks unserer Hauptbasis, und an ihrer Stelle war Leere bis zum Grundgestein.

Was tatsächlich kaputt war

Minecraft speichert die Welt nicht als eine Datei, sondern in Regionsdateien. Jede davon enthält 32 mal 32 Chunks und heißt nach ihren Koordinaten:

world/region/r.0.0.mca
world/region/r.-1.0.mca
world/region/r.0.-1.mca

Diese Dateien werden im Betrieb ständig geschrieben. Der Server hält Chunks im Speicher, ändert sie, und schreibt sie in Intervallen zurück. Wenn man in diesem Moment eine solche Datei kopiert, bekommt man einen Zustand, den es so nie gab: halb alter, halb neuer Inhalt. Beim Lesen fällt das auf, und der Server tut dann das, was er in so einem Fall tun muss — er verwirft, was er nicht versteht.

Bei mir kam beides zusammen. Die Kopie auf der externen Platte war unbrauchbar, weil sie mitten im Schreiben entstanden war. Und die Originaldatei hatte durch das Abziehen der Platte während eines Schreibzugriffs ebenfalls etwas abbekommen. Ich hatte also weder ein Original noch eine Sicherung. Sechs Wochen Bauzeit von fünf Leuten, weg.

Warnung

Eine laufende Welt kopiert man nicht. Entweder man stoppt den Server, oder man sagt ihm vorher, dass er alles schreiben und danach nichts mehr anfassen soll:

save-all
save-off
... jetzt kopieren ...
save-on

Das ist der ganze Trick, und er kostet zwanzig Sekunden.

Der Abend danach

Ich habe erst versucht, die Datei zu retten. Es gibt Werkzeuge, die kaputte Regionsdateien reparieren, indem sie die unlesbaren Chunks entfernen — das Ergebnis ist eine Welt mit Löchern, die beim nächsten Betreten neu generiert werden. Genau das habe ich gemacht. Die Basis kam nicht zurück, aber die Welt war wieder benutzbar, und drum herum stand noch alles.

Der schwierigere Teil war der Sprachchat am Sonntag. Ich habe erklärt, was passiert ist, ohne es kleinzureden. Zwei fanden es schade, einer war sauer, einer hat angeboten, den Bahnhof gemeinsam noch mal zu bauen. Was ich dabei gelernt habe, hat mit Technik wenig zu tun: Menschen verzeihen Fehler ziemlich zuverlässig, wenn man sie ohne Ausreden erklärt. Sie verzeihen deutlich schlechter, wenn sie das Gefühl haben, dass man etwas verschweigt.

Was ich danach gebaut habe

Mein erstes Sicherungsskript war peinlich einfach, und ich habe es bis heute im Kopf:

#!/bin/bash
ZIEL=/mnt/backup/minecraft
DATUM=$(date +%Y-%m-%d-%H%M)
 
screen -S mc -X stuff "save-all\nsave-off\n"
sleep 10
tar -czf "$ZIEL/welt-$DATUM.tar.gz" /srv/minecraft/world
screen -S mc -X stuff "save-on\n"
 
find "$ZIEL" -name "welt-*.tar.gz" -mtime +7 -delete

Vier Dinge stecken darin, und alle vier habe ich an diesem Wochenende gelernt:

  1. Erst das Schreiben anhalten, dann kopieren. Sonst sichert man einen Zustand, den es nie gab.
  2. In ein Archiv packen, nicht Ordner spiegeln. Ein .tar.gz ist entweder ganz oder kaputt. Ein halb kopierter Ordner sieht aus wie ein vollständiger.
  3. Der Zeitstempel gehört in den Dateinamen. Eine Sicherung, die immer backup.tar.gz heißt, ist genau eine Sicherung — und die überschreibt man mit dem kaputten Stand, sobald man den Fehler bemerkt.
  4. Alte Stände wegräumen. Sonst läuft die Platte voll, und die Sicherung bricht ab, ohne dass es jemand merkt.

Der Punkt, an dem es wirklich klick gemacht hat

Das Skript lief zwei Monate. Dann wollte ich etwas aus einer Sicherung holen — und stellte fest, dass sämtliche Archive der letzten drei Wochen 45 Byte groß waren. Ein leeres tar.gz. Der Grund: Ich hatte den Serverordner umbenannt und den Pfad im Skript nicht angepasst. tar hat brav jede Nacht ein Archiv aus einem nicht existierenden Verzeichnis gebaut, mit einer Fehlermeldung, die niemand las, weil das Skript per Cron lief und seine Ausgabe ins Nichts ging.

Das ist der eigentliche Kern dieses Eintrags, und der Satz, den ich seitdem bei jedem System aufsage, das ich betreue:

Eine Sicherung, die nie zurückgespielt wurde, ist keine Sicherung. Sie ist eine Vermutung.

Seitdem gehört zu jeder Sicherung eine Prüfung. Bei einer Minecraft-Welt kann die simpel sein — Größe des Archivs mit dem Vortag vergleichen und Alarm schlagen, wenn sie plötzlich unter einen Schwellwert fällt:

GROESSE=$(stat -c %s "$ZIEL/welt-$DATUM.tar.gz")
if [ "$GROESSE" -lt 10000000 ]; then
  echo "Sicherung verdächtig klein: $GROESSE Byte" \
    | mail -s "Backup kaputt" ich@example.org
fi

Die drei Fragen, die eine Sicherung beantworten muss

Über die Jahre ist aus dieser Erfahrung ein fester Satz Fragen geworden, den ich an jedes System stelle, das Daten hält.

Wie alt darf der Verlust sein? Bei einer Minecraft-Welt sind vierundzwanzig Stunden ärgerlich, aber verkraftbar — man baut einen Abend nach. Bei einer Datenbank mit Bestellungen sind vierundzwanzig Stunden inakzeptabel. Diese Frage bestimmt, wie oft gesichert wird, und sie ist eine fachliche, keine technische.

Wie lange darf die Wiederherstellung dauern? Ein Archiv von zwei Gigabyte entpackt sich in Minuten. Ein Archiv von zweihundert Gigabyte nicht. Wer diese Zeit nie gemessen hat, kennt sie im Ernstfall nicht — und der Ernstfall ist der schlechteste Zeitpunkt, sie herauszufinden.

Wo liegt die Sicherung, und was passiert, wenn dieser Ort mit ausfällt? Meine erste Sicherung lag auf derselben Festplatte wie der Server. Das schützt gegen versehentliches Löschen und gegen gar nichts sonst. Heute liegt bei mir jede wichtige Sicherung zusätzlich an einem zweiten Ort.

Der Fehler, der mir Jahre später noch einmal passiert ist

Ich hätte gerne geschrieben, dass ich seitdem nie wieder eine Sicherung verloren habe. Stimmt nicht.

Jahre später hatte ich eine Sicherungskette, die technisch einwandfrei lief — und deren Zielverzeichnis vollgelaufen war. Das Skript schrieb weiter, das Dateisystem lehnte ab, die Fehlermeldung ging in eine Protokolldatei, die niemand las.

Der Unterschied zu 2019 war nur, dass ich es nach drei Tagen bemerkt habe statt nach drei Wochen — weil eine Prüfung auf das Alter der letzten Sicherung lief. Die Prüfung hat den Fehler nicht verhindert, aber sie hat ihn sichtbar gemacht, und das ist der ganze Zweck.

Seitdem prüfe ich zusätzlich den freien Platz am Sicherungsort, mit einer Hochrechnung statt eines Prozentwerts. „In elf Tagen voll" ist ein Termin. „89 % belegt" ist eine Zahl, die man wegklickt.

Was davon bis heute gilt

Ich habe seitdem Systeme betreut, die deutlich mehr Daten halten als eine Minecraft-Welt: Datenbanken, Spielerstände, Bestellungen. Die Technik ist jedes Mal anders, die drei Fragen sind immer dieselben.

  • Wann wurde die letzte Sicherung geschrieben, und woher weiß ich das, ohne nachzusehen?
  • Wie lange dauert es, sie zurückzuspielen — habe ich das jemals gemessen?
  • Was genau ist beim letzten Mal verloren gegangen, wenn ich sie brauche? Eine Stunde? Ein Tag?

Wer diese drei Fragen beantworten kann, hat eine Sicherungsstrategie. Wer sie nicht beantworten kann, hat eine Datei, die zufällig gut aussieht. Ich hatte 2019 nicht einmal die Datei.