1. Einleitung
Block Corruption ist eines der schlimmsten Dinge, die passieren können. Es gibt verschiedene Ursache für das Auftreten eines Block-Corruption:
- Hardware-Fehler
- Betriebssystemfehler
- Oraclefehler
Oracle-Block-Fehler werden in der Alert-Log aufgezeichnet:Oracle-Blockfehler werden üblicherweise erst deutlich nachdem Auftreten reportet. Das kommt daher, dass Oracle meistens nicht beim Schreiben den Fehler reportet, sondern beim Lesen.
Beispiel:
Corrupt block relative dba: 0x060079fd (file 24, block 31229) |
Bemerkung: Die FILE-ID ist die absolute File-Nummert: AFN bezeichnet. Die Block-Nummer wird mit BL bezeichet
In dem Beispiel oben wird die File-ID aufgeführt: 24 Wenn die Datenbank noch geöffnet ist, dann folgende Abfrage absetzen:
SELECT name FROM v$datafile WHERE file#=24; |
Falls kein Treffer gefunden wird, handelt es sich nicht um ein Datenfile, sondernum ein Tempfile. Die File-Nummer, die oben in der Fehlermeldung angezeigt wird,ist die relative:
SELECT t.name FROM v$tempfile t CROSS JOIN v$parameter v WHERE v.name = 'db_files' and file#= <WERT aus Meldung> + valu |
Oder einfacher vielleicht:
SELECT tablespace_name, file_id+value "AFN", relative_fno "RFN" FROM dba_temp_files cross join v$parameter WHERE name='db_files'; |
dann mit der Relativen File-Nummer in der v$tempfile suchen
select name from v$tempfile where file#= <RFN>; |
Überprüfung der Hardware. Hier schaut man z.B. in die Ereignisanzeige bei Windows.Wenn eine Festplatte unbrauchbar ist.
ALTER DATABASE RENAME FILE '/oldlocation/myfile.dbf' TO '/newlocation/myfile.dbf'; |
6. Datenbank öffnen
SELECT tablespace_name, segment_type, owner, segment_name |
Beispiel mit oben der Fehlermeldung:
SELECT tablespace_name, segment_type, owner, segment_name |
TABLESPACE_NAME SEGMENT_TYPE OWNER SEGMENT_NAME |
5. Behebung des Fehlers
Die Behebung ist abhängig von dem Segmenttyp: Es gibt folgende Möglichkeiten:
a) CACHE
b) CLUSTER
c) INDEX PARTITION
d) INDEX
e) ROLLBACK
f) TABLE PARTITION
g) TABLE
h) TEMPORARY
i) SONSTWAS
a) CACHE Bitte Statement überprüfen, File-Id AFN und Block-Id BL Wenn erneut CACHE als Typ erscheint Oracle-Support kontaktieren
b) CLUSTER Wenn es ein CLUSTER ist, muss rausgefunden werden, welche Tabelle betroffen ist.
SELECT owner, table_name FROM dba_tables WHERE owner='<SEGMENT-OWNER>' AND cluster_name='<SEGMENT-NAME>'; |
Wenn es sich um eine Dictionary-Tabelle handelt (OWNER = SYS) Media Recovery
durchführen, siehe unten.
c) INDEX PARTITION Zur Doku die Partition ermitteln:
SELECT partition_name FROM dba_extents WHERE file_id = <AFN> AND <BL> BETWEEN block_id AND block_id + blocks - 1; |
Ansonten verfahren wie unter d)
d) INDEX
Wenn der OWNER SYS ist, Oracle Support kontaktieren
Ansonsten: Tabelle ermitteln.
SELECT table_owner, table_name FROM dba_indexes WHERE owner='<SEGMENT-OWNER>' AND index_name='<SEGMENT-NAME>'; |
Beispiel:
SQL> SELECT table_owner, table_name FROM dba_indexes WHERE owner='SAP' and index_name ='IDX_BEGRU'; |
Ermitteln, ob der Index Grundlage eines Constraintes ist.
SELECT owner, constraint_name, constraint_type, table_name FROM dba_constraints WHERE owner='<TABLE-OWNER>' AND constraint_name='<INDEX-NAME>' |
Beispiel:
SELECT owner, constraint_name, constraint_type, table_name FROM dba_constraints WHERE owner='INFO' AND constraint_name='IDX_RECHNER_USERLOG' |
Mögliche Werte für einen Constraint sind:
P: Primary Key
U: Unique Key
Wenn es sich um einen Primary Key handelt, dann prüfen, ob der Primary Key
von einem Foreign Key referenziert wird.
SELECT owner, constraint_name, constraint_type, table_name FROM dba_constraints WHERE r_owner='<TABLE-OWNER>' AND r_constraint_name='<INDEX-NAME>'; |
Wenn der OWNER SYS ist. Media Recovery durchführen.
Ansonsten: Den Index neu anlegen:
Zuerst das DDL ermitteln.
Dazu mit OWNER anmelden und folgendes Select absetzen:
SELECT DBMS_METADATA.GET_DDL('INDEX',<INDEX_NAME>) from dual; |
Beispiel:
Die Rückgabe der Funktion ist vom Typ long, also den Output entsprechend groß machen.
set long 5000 |
Hat der Index einen oder mehrere Foreign Key, dann diesen oder diese ausschalten.
ALTER TABLE <child_table> DISABLE CONSTRAINT <fk_constraint>; |
Handelt es sich um einen Primary Key, so muss der Constraint ausgeschaltet werden.
ALTER TABLE <table> DISABLE CONSTRAINT <pk_constraint>; |
Dann den Index löschen;
drop index <index_name>; |
Index neu anlegen:
create index .... |
Evtl Primary Key Constraint wieder anlegen:
ALTER TABLE <table> ENABLE CONSTRAINT <pk_constraint>; |
Evtl. Foreign Key Constraints aktivieren:
ALTER TABLE <child_table> ENABLE CONSTRAINT <fk_constraint>; |
Bei einem INDEX PARTITION mit dem Befehl
ALTER INDEX ... REBUILD PARTITION ...; |
den index neu anlegen.
Bem.: Auf keinem Fall den Index mit ALTER INDEX ... REBUILD neu anlegen, da hier
existierende Segmente wieder benutzt werden.
ALTER INDEX ... REBUILD ONLINE bzw, ALTER INDEX ... REBUILD PARTITION ...;
machen dies nicht.
Beheben des Fehlers mit folgendem Befehl:
ALTER INDEX xxx REBUILD PARTITION ppp; |
e) ROLLBACK
Media Revovery.
f) TABLE PARTITION
Bestimmen der Partition und weiter verfahren wie unter g) TABLE
SELECT partition_name FROM dba_extents WHERE file_id = <AFN> AND <BL> BETWEEN block_id AND block_id + blocks - 1; |
g) TABLE
Wenn der OWNER SYS ist, es sich also um eine Dictionary-Tabelle handelt, ist Media Recovery notwendig
Kann die Tabelle gedroppt und neu angelegt werden, ohne dass Daten aus der Tabelle selbst entnommen werden müssen?
->
Ermitteln aller Indizes:
SELECT owner, index_name, index_type FROM dba_indexes WHERE table_owner='<SEGMENT-OWNER>' AND table_name='<TABLE-NAME>'; |
Ermitteln ob ein Primary Key vorliegt:
SELECT owner, constraint_name, constraint_type, table_name FROM dba_constraints WHERE owner='<TABLE-OWNER>' AND table_name='<SEGMENT-NAME>' AND constraint_type='P'; |
Wenn es sich um einen Primary Key handelt, dann prüfen, ob der Primary Key
von einem Foreign Key referenziert wird.
SELECT owner, constraint_name, constraint_type, table_name FROM dba_constraints WHERE r_owner='<TABLE-OWNER>' AND r_constraint_name='<CONSTRAINT-NAME>'; |
Wenn der OWNER SYS ist, ist Media Recovery notwendig.
-> Abfolge analog Indizes
Foreign -Key-Constraints ausschalten
Indizes-DDL-erzeugen.
Tabelle-DDL-erzeugen.
set long 5000 |
Tabelle droppen (falls Kunde nicht 100% sicher, ob alle Daten wieder hergestellt werden
, Tabelle umbenennen
rename <TABLE_NAME> to <TABLE_NAME>_bak; )drop table <table_name>; |
Tabelle neu anlegen.
Indizes neu anlegen.
Foreign Key-Constraints aktivieren.
Wenn die Tabelle nicht gedroppt werden kann, dann Media Recovery
h) TEMPORARY
Handelt es sich um ein Temporary Tablespace, so ist nachzuschauen, welche User davon
betroffen sind.
select username from dba_users where TEMPORARY_TABLESPACE =<TABLESPACE_NAME>; |
Anschliessend ist ein neues temporaeres Tablespace anzulegen, dieses
als default Tablespace zu bestimmen und die user diesem Tablespace zuzuweisen.
Beispiel:
CREATE TEMPORARY TABLESPACE temp_neu TEMPFILE 'oracle/oradata/xxxsidxxx/temp1.dbf' SIZE 512064K REUSE; |
Wenn das alte Tablespace 4 GB groß ist dann natürlich das neue auch so gross anlegen.