MySQL InnoDB reparieren für Fortgeschrittene
Es war wieder einmal so weit – ich hatte etwas zerstört und war auf der Suche nach einer Lösung im Netz. Und das Netz konnte mir nicht helfen….
Aber fangen wir doch einfach von vorne an.
Das Warum und das Wie lassen wir jetzt mal beiseite. In jedem Fall stand ich vor einigen Tagen mit einem laufenden Datenbankserver da, der auf der einen Seite keine Downtime haben darf, auf der anderen Seite aber eine wichtige Datenbank mit InnoDB Tabellen enthielt, deren „tablespace id“ nicht mehr stimmt.
Kleiner Ausflug in die MySQL Theorie. Wenn man InnoDB nutzt hat man generell zwei Möglichkeiten:
1. Alle Tabellendaten werden in die Zentralle Datei ibdata geschrieben. Diese bläht sich dadurch gigantisch auf und wird für schnelle Aktionen teilweise unhandlebar.
2. Man entscheidet sich für die Option „innodb_file_per_table“, wodurch die Daten in separaten Dateien je Tabelle geschrieben werden und nur die Keys etc. in der Datei ibdata verbleiben. Die Dateien stellen den Tablespace der Tabelle dar und sind über die Tablespace id mit den Daten (Keys etc.) in der Datei ibdata verknüpft.
Durch unglückliche manuelle Operationen inklusive Backup und Restore stimmen mit einem mal diese ids nicht mehr überein oder es gibt sogar zwei Tabellen mit der selben id. In der Regel ist das System an dieser Stelle fubar – fucked up beyond all repair. So sagen selbst die größten MySQL Gurus. An einer Lösung wird in Versionen größer 5.1 gearbeitet. Ende der Fahnenstange.
Nun gut, ich habe es verbockt und gebe mich daher nicht geschlagen. Wenn mir Google und die Welt nicht helfen will, suche ich halt selbst nach Lösungen.
Hier nun die Lösung, die Funktioniert:
– Setze eine frische, leere MySQL Installation auf einer separaten Maschine auf
– erstelle eine Dummy-Datenbank
– lese aus dem error-log der kaputten DB die Tablespace id der ersten zu reparierenden Tabelle aus (in meinem Fall 589) => n
– erstelle in der Dummy-Datenbank n-1 InnoDB Tabellen, in meinem Fall 588
– lege eine zweite Datenbank mit dem gleichen Namen an, in dem Deine kaputte Tabelle liegt.
– Erstelle dort mit Create Table die exakte Struktur der kaputten Tabelle
– führe ein „ALTER TABLE tabellenname DROP TABLESPACE“ in dieser Datenbank aus
– kopiere die als kaputt markierte .ibd Datei in diese neue Datenbank – achte auf die Benutzerrechte!
– führe ein „ALTER TABLE tabellenname IMPORT TABLESPACE“ aus
– führe ein „OPTIMIZE TABLE tabellenname“ aus
– nutze mysqldump um die Tabelle zu sichern
– um weitere Tabellen zu reparieren, fange ganz von vorne an! Und das ist wichtig, denn für den nächsten Anlauf muss wieder die MySQL ganz jungfräulich sein, sonst habt ihr auch in der neuen Installation wieder die tablespace ids zerstört. Also: MySQL stoppen, die ibdata, die ib_logfiles, das gesamte Verzeichnis der Dummy-Datenbank und die neu angelegte Datenbank physikalisch löschen! MySQL neu starten und los gehts für Tabelle 2
– versucht NIE, die Reihenfolge der Schritte zu ändern oder mehrere Tabellen gleichzeitig zu reparieren. Das herauszufinden kostete mich Stunden!
Anschließend die Backup-Tabellen einspielen und alles sollte gut sein!
Viel Glück!
Respekt! Die Lösung hört sich ziemlich … äh … hemdsärmelig an, aber wenn sie funktioniert 😉
Interessant finde ich, dass eine komplett neue Installation nach der „Behandlung“ quasi den gleichen „Stand“ (die ID) liefert, wie die alte Datenbank. Dann dürfte es doch eigentlich nicht so kompliziert sein, das ganze automatisiert in einem bestehenden System hinzubekommen, oder? Ja, ich weiss, ich lehne nicht mehr, ich halte mich nur noch mit den Zehen am Fensterbrett fest.
Ich habe allerdings das dringende Bedürftnis, NIEMALS herausfinden zu wollen, welche Datenbank du da repariert hast. 🙂
Also: die IDs werden einfach immer fortlaufend vergeben, daher diese Klimmzüge. Es gibt keinen (mir oder im Internet) bekannten Weg, die ID zu faken oder zu ändern – soll aber kommen. Abwarten.
Die Automatisierung hat den „Fehler“, dass du immer eine komplett zweite MySQL Installation brauchst. Das würde ich nie auf nem Produktionssystem wagen, da kann zuviel schief gehen.
Zu Deinem letzten Satz: Glaube mir, die DB ist Dir näher als Du Dir wünschst. Beinahe täglich… 😀