Also.
Der Admin stellt auf einmal fest, dass Tabelle xyz_table dank einer blockcorruption nicht komplett lesbar ist oder sich nicht mit dpexp/exp exportieren lässt. (z.B.: ORA-31693: ...ORA-02354: ...ORA-00600: internal error code, arguments: [25027], [4], [394435]...)
Ein Recovery wird verworfen, da die Koruption schon zu lange existiert und andere Daten verloren gingen.
Die Lösung ist DBMS_REPAIR:
Zunächst werden die korrupten Blöcke mit dbms_repair markiert, damit die betroffene Tabelle wieder komplett gelesen/exportiert werden kann.
DBMS_REPAIR benötigt dafür eine Repairtabelle. Diese legt man hiermit an:
SET SERVEROUTPUT ON DECLARE num_corrupt INT; BEGIN num_corrupt := 0; DBMS_REPAIR.CHECK_OBJECT ( SCHEMA_NAME => 'BEISPIEL', OBJECT_NAME => 'XYZ_TABLE', REPAIR_TABLE_NAME => 'REPAIR_TABLE', CORRUPT_COUNT => num_corrupt); DBMS_OUTPUT.PUT_LINE('number corrupt: ' || TO_CHAR (num_corrupt)); END; /
Anschließend jagt man DBMS_REPAIR über die kaputte Tabelle:
SET SERVEROUTPUT ON DECLARE num_corrupt INT; BEGIN num_corrupt := 0; DBMS_REPAIR.CHECK_OBJECT ( SCHEMA_NAME => 'BEISPIEL', OBJECT_NAME => 'XYZ_TABLE', REPAIR_TABLE_NAME => 'REPAIR_TABLE', CORRUPT_COUNT => num_corrupt); DBMS_OUTPUT.PUT_LINE('number corrupt: ' || TO_CHAR (num_corrupt)); END; /
Jetzt kann man in der Repairtabelle nachsehen, was im Argen liegt:
SELECT OBJECT_ID, TABLESPACE_ID tsid, RELATIVE_FILE_ID fileid, BLOCK_ID, CORRUPT_TYPE, CORRUPT_DESCRIPTION, REPAIR_DESCRIPTION FROM REPAIR_TABLE;
Hier die ausführliche CORRUPT_DESCRIPTION:
Block
Checking: DBA = 16780739, Block Type =
KTB-managed data block
data header at 0xf25ec07ckdbchk: row locked by non-existent transaction
table=0 slot=1
lockid=6 ktbbhitc=3
Jetzt, wo man weiß, welche Block-ID – in diesem Fall die 3523 – betroffen ist, kann man mit diesem Select sogar den Inhalt finden und anzeigen:
SELECT * FROM XYZ_TABLE WHERE DBMS_ROWID.ROWID_BLOCK_NUMBER(rowid) = 3523
Das sieht wirklich kaputt aus... aber mit ein wenig Kenntnis des Datenmodells und der Anwendung weiß man jetzt vielleicht sogar, wie man an die korrekten Daten kommt.
Anschließend kann die Tabelle korrigiert werden - z.B. mittels DBMS_REPAIR.FIX_CORRUPT_BLOCKS().
Im ersten Code-Segment sollte es wohl heißen:
AntwortenLöschenBEGIN
DBMS_REPAIR.ADMIN_TABLES (
TABLE_NAME => 'REPAIR_TABLE',
TABLE_TYPE => dbms_repair.repair_table,
ACTION => dbms_repair.create_action,
TABLESPACE => 'USER');
END;
/
*lg*
Thomas Rosenberg