„Cannot commit index“ oder wie man Daten aus einer teilweise wiederhergestellten (inkonsistenten) Datenbank pumpt
Alexey Kovyazin, letzte Aktualisierung 30-März-2014
Nach der Behebung von Korruptionen tritt beim Wiederherstellungsschritt häufig der Fehler “Cannot commit index” auf. In Firebird 2.0 und später erscheint dies als Warnung und die Datenbank wird nicht online gebracht; in Firebird 1.0-1.5 und InterBase tritt dies als ein sehr unangenehmer Fehler auf, der den Wiederherstellungsprozess stoppt (es ist beeindruckend, diesen Fehler am Ende einer 200-GB-Datenbankwiederherstellung zu sehen).
Der Grund für den Fehler “Cannot commit index..” ist offensichtlich: Korruption beeinträchtigt die referenzielle Integrität der Datenbank, und Datensätze verschwinden auf magische Weise (aus Sicht des Servers).
Zum Beispiel haben Sie eine Tabelle “Customers” und eine zugehörige Tabelle “Orders”, die durch einen Fremdschlüssel referenziert wird. Ohne Korruption ist es nicht möglich, den Fremdschlüssel zu verletzen und einen Datensatz aus Customers zu löschen, ohne vorher alle Bestellungen zu löschen, die sich auf einen bestimmten Kunden beziehen. Korruption beeinträchtigt die Datenbankdatei auf niedriger Ebene und löscht Datensätze direkt. Was für eine nette Überraschung für den Server, unaufgelöste Verweise auf Master-Datensätze von Fremdschlüsseldatensätzen zu sehen.
Hier muss ich einen Tipp zum Wiederherstellungsprozess hinzufügen: Die Engine stellt alle Tabellen mit nicht aktivierten Indizes wieder her (das macht das Befüllen von Tabellen mit Datensätzen viel schneller) und beginnt danach, die Indizes nacheinander zu aktivieren (d.h. aufzubauen). Das bedeutet, dass sich alle Daten bereits in der Datenbank befinden, wenn der Wiederherstellungsprozess den Schritt zur Indexerstellung beginnt, und Sie sehen den Fehler “Cannot commit index..”.
Nun, der erste Wunsch, wenn Sie den Fehler “Cannot commit index” sehen, ist, die entsprechende Fremdschlüssel-Constraint zu entfernen, um die Wiederherstellung abzuschließen. Die Frage ist, was wir mit der inkonsistenten, aber erfolgreich wiederhergestellten Datenbank tun wollen: Ein entfernter Fremdschlüssel kann ein wichtiger Teil der Geschäftslogik sein.
Es gibt hier 2 Ansätze: fehlende Daten neu erstellen oder inkonsistente Daten entfernen. Sehen wir uns an, was das im obigen Customers-Orders-Beispiel bedeutet.
Neuerstellung fehlender Daten
Sie haben also entschieden, dass Sie fehlende Customers für inkonsistente Orders neu erstellen müssen. Auf diese Weise müssen Sie verlorene IDs ermitteln. Normalerweise verwende ich eine SQL-Abfrage wie diese (ich denke, es wird einfach sein, sie entsprechend anzupassen):
SELECT O.Customer_ID FROM ORDERS O WHERE NOT EXISTS ( SELECT C.Customer_ID FROM CUSTOMERS C WHERE O.Customer_ID=C.Customer_ID)
Danach können Sie manuell Datensätze mit der Liste der fehlenden Primärschlüssel einfügen und erneut eine Sicherung/Wiederherstellung durchführen.
Übertragung konsistenter Daten
Wenn Sie denken, dass es akzeptabel ist, inkonsistente Datensätze zu verlieren, können Sie alle Daten aus der teilweise wiederhergestellten Datenbank in eine leere Datenbank übertragen und einfach inkonsistente Datensätze überspringen, indem Sie den folgenden Ansatz verwenden:
-
Laden Sie das kostenlose Tool IBDataPump herunter: http://www.clevercomponents.com/demo/datapump/IBPump.zip
-
Erstellen Sie nur eine Metadaten-Datenbank aus der Sicherung der reparierten Datenbank (nach IBFirstAID) mit dem Befehl
gbak -c -m -user SYSDBA -pass masterkey Disk:\Pfad\backup.fbk Disk:\Pfad\fresh.fdb
-
Führen Sie IBDataPump aus und setzen Sie die teilweise reparierte Datenbank als Quelle und die frische leere Datenbank als Ziel
-
Klicken Sie auf die nächsten Registerkarten, klicken Sie auf die entsprechenden Schaltflächen und auf der 3. Registerkarte klicken Sie auf “Pump”. Warten Sie auf den Abschluss (es kann ein langer Prozess sein; um eine Vorstellung zu bekommen, können Sie die Wachstumsdynamik der Zieldatenbankgröße überprüfen).
-
Als Ergebnis erhalten Sie eine fresh.fdb-Datenbank mit konsistenten Fremdschlüsselbeziehungen - das ist vollkommen in Ordnung.
Wenn die Datenbank eine Schleife mit Fremdschlüsseln hat, wird IBDataPump Sie warnen und eine Liste solcher Constraints anzeigen - eine oder mehrere davon sollten entfernt werden, bevor das Pumpen verfügbar ist.
Natürlich gab es einige Fälle, in denen das Pumpen einen speziellen Ansatz erforderte, und wenn Sie auf eine solche Situation stoßen, kontaktieren Sie bitte unseren Support.