Donnerstag Juni 09, 2005

Oracle Block Corruption

Korrupte Blöcke in einer (Oracle) Datenbank sind etwas ziemlich Unangenehmes. Vorallem wenn alles in NOLOGGING Modus läuft, also keine Archivlogs geschrieben werden und ein Offline-Backup (Cold-Backup) schon länger zurückliegt, da der Betriebsablauf nur kurze und seltene Downtimes für ein Backup vorsieht. Ich habe das bis jetzt zweimal erlebt und die Ursache dafür war immer ein Hardware-Defekt. Beim ersten Mal war es so, dass die Verbindung vom Rechner zum Storage des öfteren einfach weg war. Das hat wohl mit der der Zeit dazu geführt, dass immer mehr Blöcke kaputt gingen, da das Storage mitten unter einem Schreibvorgang in einen Block weg war. Problem ist blos, das die Datenbank sich anschließend zwar wieder starten läßt, aber das Ganze solange niemand merkt, bis tatsächlich mal dann eine Query über so einen kaputten Block drübermaschiert. Beim zweiten Vorfall war die Firmware des Controllers für das SUN 3510 Storage buggy. Der Controller hat nämlich schlicht und ergreifend nicht gemerkt, das eine Platte einen fehlerhaften Block gemeldet hat und hat diese Platte somit auch nicht aus dem RAID 5 Verbund genommen. Wie das allerdings alles so laufen konnte, ist nicht mal SUN ganz klar.

Nun ja... Es empfiehlt sich deshalb regelmäßig einen Verify mit Hilfe des Oracle-Tools dbv über die Datenfiles zu machen (und natürlich ein Backup ;-). Da die Files READ-ONLY geöffnet werden, kann man das entweder direkt auf den Live-Datenfiles tun oder besser man checkt die Datenfiles nach dem Backup. dbv erkennt zwar auch nicht alles, aber grobe Fehler in den Datenstrukturen werden auf jeden Fall sichtbar. Das sollte aber zu Traffic armer Zeit passieren, da dbv schon Einiges an I/O benötigt.

Wie so ein Fehler sich bemerkbar macht, sieht man z.B. hier:

SQL> CREATE TABLE test AS SELECT * FROM TESTTABLE;
*
FEHLER in Zeile 1:
ORA-12801: Fehler in parallelem Abfrage-Server P015 angezeigt
ORA-01578: ORACLE-Datenblock beschädigt (Datei Nr. 56, Block Nr. 357316)
ORA-01110: Datendatei 56: '/u01/data/DATENBANK/data/datenfile.dbf'

Nun in diesem Falle sollte man zuerst Oracle Metalink Note 28814.1 zu Rate ziehen und außerdem alle relevaten Logs auf der Maschine checken, den die Wahrscheinlichkeit eines Hardwaredefekts ist recht groß. Es kommt nun drauf an, welches Segment es erwischt hat. Wenn z.B. ein Objekt im Data Dictionary betroffen ist, wird man meistens um ein DB-Recovery nicht drumrumkommen. Ist ein Index betroffen, kann man oft Glück haben und ein Index Rebuild erledigt die Sache gleich wieder. Ist eine Tabelle hin, kann man zwar die "guten" Daten noch rausholen, aber ohne Backup gehen dabei fast immer Daten verloren. Ist die Tabelle partitioniert, kann man einen sog. Partitionstausch (ALTER TABLE ... EXCHANGE PARTITION ...) machen. D.h. man erstellt eine neue Tabelle und tauscht die defekte Partition durch diese neue Tabelle aus. Damit ist die Tabelle dann gewissermaßen für die Anwendungen wieder "ganz". Diese Tabelle sollte möglichst die gleichen Storagedaten der Partition haben und natürlich auch die gleichen Spalten. Das könnte man z.B. wie folgt machen:

CREATE TABLE test_save TABLESPACE tablespace STORAGE ( ... ) AS
SELECT * FROM test WHERE rownum=1;

Sollte das schon nicht mehr hinhauen, kann man das DBMS_REPAIR-Paket verwenden:

EXEC DBMS_REPAIR.SKIP_CORRUPT_BLOCKS('SCHEMANAME','test');

"test" ist hier die Tabelle, die die korrupten Blöcke enthält. Damit sollte dann der CREATE TABLE ... AS SELECT ... jetzt funken. Damit bekommt man dann z.B. auch die "guten" Daten in die neue Tabelle, wenn man die WHERE-Klausel wegläßt. Man sollte allerdings die korrupte Tabelle nicht einfach dropen, sondern am Besten mit ALTER TABLE test RENAME TO test_corrupted; umbenennen. Dann hat man die Daten noch, um sich die Daten noch genauer anschauen zu können. Man kann dann ja versuchen, die alte Tabelle neu anzulegen und die Daten rekonstruieren. Eventl. vorhandene Constraints wird man ausschalten müssen.

Die interessanten Dokumente dazu findet man im Oracle Metalink, wenn man nach der Note 28814.1 sucht. Die Not 33405.1 gibt Auskunft über die Vorgehensweise, wenn man DBMS_REPAIR.SKIP_CORRUPT_BLOCKS verwenden möchte. Wie man an die Daten mit Hilfe der ROWID oder von Index-Scans wieder ran kommt, beschreibt Note 61685.1 (für Oracle 8i+).

Nun... Die Moral von der Geschicht, betriebe keine Oracle-Datenbank ohne vernünftiges Backup nicht ;-) Wenn man noch dazu keine Archivlogs hat, ist man doppelt aufgeschmissen. Ansonsten könnte man die Datenbank sogar aus einem uralt Cold-Backup mit den Archivlogs wieder hinbiegen. Aber manchmal hat man eben auch das nicht. Dann bleibt nur das letzte Coldbackup und dann sind die Daten vom diesem Backupzeitpunkt bis zum Schluß u.U. weg. Und wenn man auch das nicht hat... Ja dann... Dann muß man damit rechnen, das Daten einfach futsch sind. DAS ist dann richtig geil ;-)

Kommentare:

Senden Sie einen Kommentar:
  • HTML Syntax: Ausgeschaltet