TECH
QUESTION
자주하는 질문답변 입니다.
Oracle
작성자 | 유건데이타 | 등록일 | 2015-06-22 |
제목 | ORA-01578 DBMS_REPAIR | ||
---|---|---|---|
BLOCK CORRUPTION (ORA-1578) 처리 (ORACLE 8I NEW FEATURE)
======================================================== PURPOSE ------- Block Corruption의 처리 방안에 대해 알아본다. Problem Description ------------------- block corruption 시 10210, 10211,10231 의 event 를 사용해서 해당 block 을 skip 할 수도 있지만 V8.1 이상에서는 dbms_repair.fix_corrupt_blocks , dbms_repair.skip_corrupt_block 를 이용하여 corrupt가 발생한 block을 detect하고 skip, 또는 repair해주는 방안이 제시되고 있다. Workaround ---------- Solution Description -------------------- - 먼저 detecting 을 위해 db_block_checking =true 를 init.ora 에 set - dbms_repair 의 package 를 사용하는데 이 package 는 dbmsrpr.sql, prvtrpr.plb를 수행한다 . - sys 로 접속하여 package 를 실행한다. 다음의 예제를 살펴보자 T1 테이블에 corrupt 된 block 이 있다고 가정한다. SQL> desc t1 Name Null? Type ----------------------------------------- -------- --------- COL1 NOT NULL NUMBER(38) COL2 CHAR(512) SQL> analyze table t1 validate structure; analyze table t1 validate structure * ERROR at line 1: ORA-01498: block check failure - see trace file 이때 ANALYZE로 부터 발생된 trace file 에 corrupt 된 block 에 3 row 의 (nrows = 3) data 가 있음을 알수 있다고 가정하자. DBMS_REPAIR.ADMIN_TABLES (repair and orphan key) ================================================ ADMIN_TABLES 은 table 을 위한 repair table과,인덱스를 위한 orphan key tables을 제공한다. SQL> @adminCreate SQL> connect sys/change_on_install Connected. SQL> SQL> -- Repair Table SQL> SQL> declare 2 begin 3 -- Create repair table 4 dbms_repair.admin_tables ( 5 -- table_name => 'REPAIR_TABLE', 6 table_type => dbms_repair.repair_table, 7 action => dbms_repair.create_action, 8 tablespace => 'USERS'); -- default TS of SYS if not specified 9 end; 10 / PL/SQL procedure successfully completed. SQL> select owner, object_name, object_type 2 from dba_objects 3 where object_name like '%REPAIR_TABLE'; OWNER OBJECT_NAME OBJECT_TYPE ------------------------------------------------------------------ SYS DBA_REPAIR_TABLE VIEW SYS REPAIR_TABLE TABLE SQL> SQL> -- Orphan Key Table SQL> SQL> declare 2 begin 3 -- Create orphan key table 4 dbms_repair.admin_tables ( 5 table_type => dbms_repair.orphan_table, 6 action => dbms_repair.create_action, 7 tablespace => 'USERS'); -- default TS of SYS if not specified 8 end; 9 / PL/SQL procedure successfully completed. SQL> select owner, object_name, object_type 2 from dba_objects 3 where object_name like '%ORPHAN_KEY_TABLE'; OWNER OBJECT_NAME OBJECT_TYPE ------------------------------------------------------------------ SYS DBA_ORPHAN_KEY_TABLE VIEW SYS ORPHAN_KEY_TABLE TABLE DBMS_REPAIR.CHECK_OBJECT ========================= CHECK_OBJECT procedure 는 기술된 object를 check 하고, repair 를 위한 정보를 수집하기 위함이다. SQL> @checkObject SQL> set serveroutput on SQL> SQL> declare 2 rpr_count int; 3 begin 4 rpr_count := 0; 5 dbms_repair.check_object ( 6 schema_name => 'SYSTEM', 7 object_name => 'T1', 8 repair_table_name => 'REPAIR_TABLE', 9 corrupt_count => rpr_count); 10 dbms_output.put_line('repair count: ' || to_char(rpr_count)); 11 end; 12 / repair count: 1 PL/SQL procedure successfully completed. SQL> desc repair_table Name Null? Type ----------------------------------------- -------- ---------------------------- OBJECT_ID NOT NULL NUMBER TABLESPACE_ID NOT NULL NUMBER RELATIVE_FILE_ID NOT NULL NUMBER BLOCK_ID NOT NULL NUMBER CORRUPT_TYPE NOT NULL NUMBER SCHEMA_NAME NOT NULL VARCHAR2(30) OBJECT_NAME NOT NULL VARCHAR2(30) BASEOBJECT_NAME VARCHAR2(30) PARTITION_NAME VARCHAR2(30) CORRUPT_DESCRIPTION VARCHAR2(2000) REPAIR_DESCRIPTION VARCHAR2(200) MARKED_CORRUPT NOT NULL VARCHAR2(10) CHECK_TIMESTAMP NOT NULL DATE FIX_TIMESTAMP DATE REFORMAT_TIMESTAMP DATE SQL> select object_name, block_id, corrupt_type, marked_corrupt, 2 corrupt_description, repair_description 3 from repair_table; OBJECT_NAME BLOCK_ID CORRUPT_TYPE MARKED_COR ------------------------------ ---------- ------------ ---------- CORRUPT_DESCRIPTION -------------------------------------------------------------------------------- REPAIR_DESCRIPTION -------------------------------------------------------------------------------- T1 3 1 FALSE kdbchk: row locked by non-existent transaction table=0 slot=0 lockid=32 ktbbhitc=1 mark block software corrupt Data Extraction =============== repair table에 의하면 file 6 ,block 3 에 corrupt 이 났음을 알수 있다 그러나 아직 이 block 은 corrupt 로 mark 되어 있지 않으므로 필요 data 를 추출하여야 한다. 1. ALTER SYSTEM DUMP (nrows = 3) 에 의해 block안에 있는 row수를 결정한다. 2. corrupt object를 select 하여 가능한 정보를 추출한다. SQL> -- The following query can be used to salvage data from a corrupt block. SQL> -- Creating a temporary table facilitates data insertion. SQL> create table temp_t1 as 2 select * from system.t1 3 where dbms_rowid.rowid_block_number(rowid) = 3 4 and dbms_rowid.rowid_to_absolute_fno (rowid, 'SYSTEM','T1') = 6; Table created. SQL> select col1 from temp_t1; COL1 ---------- 2 3 DBMS_REPAIR.FIX_CORRUPT_BLOCKS (ORA-1578) ============================================ FIX_CORRUPT_BLOCKS procedure는 repair table 의 정보를 이용하여 corrupt blocks 을 fix 한다 그러나 아직 full table scan 시 여전히 error 가 발생한다 SQL> declare 2 fix_count int; 3 begin 4 fix_count := 0; 5 dbms_repair.fix_corrupt_blocks ( 6 schema_name => 'SYSTEM', 7 object_name => 'T1', 8 object_type => dbms_repair.table_object, 9 repair_table_name => 'REPAIR_TABLE', 10 fix_count => fix_count); 11 dbms_output.put_line('fix count: ' || to_char(fix_count)); 12 end; 13 / fix count: 1 PL/SQL procedure successfully completed. SQL> select object_name, block_id, marked_corrupt 2 from repair_table; OBJECT_NAME BLOCK_ID MARKED_COR ------------------------------ ---------- ---------- T1 3 TRUE SQL> select * from system.t1; select * from system.t1 * ERROR at line 1: ORA-01578: ORACLE data block corrupted (file # 6, block # 3) ORA-01110: data file 6: '/tmp/ts_corrupt.dbf' DBMS_REPAIR.DUMP_ORPHAN_KEYS ============================== DUMP_ORPHAN_KEYS는 corrupt data 에 해당하는 index 를 나타내 준다 SQL> select index_name from dba_indexes 2 where table_name in (select distinct object_name from repair_table); INDEX_NAME ------------------------------ T1_PK SQL> @dumpOrphanKeys SQL> set serveroutput on SQL> SQL> declare 2 key_count int; 3 begin 4 key_count := 0; 5 dbms_repair.dump_orphan_keys ( 6 schema_name => 'SYSTEM', 7 object_name => 'T1_PK', 8 object_type => dbms_repair.index_object, 9 repair_table_name => 'REPAIR_TABLE', 10 orphan_table_name => 'ORPHAN_KEY_TABLE', 11 key_count => key_count); 12 dbms_output.put_line('orphan key count: ' || to_char(key_count)); 13 end; 14 / orphan key count: 3 PL/SQL procedure successfully completed. SQL> desc orphan_key_table Name Null? Type ----------------------------------------- -------- ---------------------------- SCHEMA_NAME NOT NULL VARCHAR2(30) INDEX_NAME NOT NULL VARCHAR2(30) IPART_NAME VARCHAR2(30) INDEX_ID NOT NULL NUMBER TABLE_NAME NOT NULL VARCHAR2(30) PART_NAME VARCHAR2(30) TABLE_ID NOT NULL NUMBER KEYROWID NOT NULL ROWID KEY NOT NULL ROWID DUMP_TIMESTAMP NOT NULL DATE SQL> select index_name, count(*) from orphan_key_table 2 group by index_name; INDEX_NAME COUNT(*) ------------------------------ ---------- T1_PK 3 Note: orphan key table의 index 는 다시 rebuild 되어야 한다. DBMS_REPAIR.SKIP_CORRUPT_BLOCKS =============================== SKIP_CORRUPT_BLOCKS 은 table 과 index 의 corrupt block 을 skip 하는 것을 enable/disable 을 실시한다. Suggestion: SKIP_CORRUPT_BLOCKS 가 enabled되면 orphan key table의 모든 index 는 모두 rebuild 되어야 한다. ( all index associated with object if DUMP_ORPHAN_KEYS was omitted). SQL> @skipCorruptBlocks SQL> declare 2 begin 3 dbms_repair.skip_corrupt_blocks ( 4 schema_name => 'SYSTEM', 5 object_name => 'T1', 6 object_type => dbms_repair.table_object, 7 flags => dbms_repair.skip_flag); 8 end; 9 / PL/SQL procedure successfully completed. SQL> select table_name, skip_corrupt from dba_tables 2 where table_name = 'T1'; TABLE_NAME SKIP_COR ------------------------------ -------- T1 ENABLED SQL> -- rows in corrupt block skipped, no errors on full table scan SQL> select * from system.t1; COL1 COL2 -------------------------------------------------------------------------------- 4 dddd 5 eeee --> Notice the pk index has not yet been corrected. SQL> insert into system.t1 values (1,'aaaa'); insert into system.t1 values (1,'aaaa') * SQL> select * from system.t1 where col1 = 1; no rows selected DBMS_REPAIR.REBUILD_FREELISTS =============================== REBUILD_FREELISTS rebuilds freelists for the specified object. SQL> declare 2 begin 3 dbms_repair.rebuild_freelists ( 4 schema_name => 'SYSTEM', 5 object_name => 'T1', 6 object_type => dbms_repair.table_object); 7 end; 8 / PL/SQL procedure successfully completed. Rebuild Index ============= Note: Every index identified in the orphan key table should be rebuilt to ensure consistent results. SQL> alter index system.t1_pk rebuild online; Index altered. SQL> insert into system.t1 values (1, 'aaaa'); 1 row created. SQL> select * from system.t1; COL1 COL2 -------------------------------------------------------------------------------- 4 dddd 5 eeee 1 aaaa |
Comment | |||
---|---|---|---|
등록된 코멘트가 없습니다. |