본문 바로가기
oracle/[Recovery] 기타

[Block Corruption and Repair] DBMS_REPAIR package

by #moonyz 2014. 11. 18.

[DBMS_REPAIR package]

- 오라클 8i 버전 부터 등장

- Block Corruption을 detecting하고 repair

- table block과 index block을 조사하여 문제가 있는 block을 수정해주는 data corruption repair 패키지를 가짐

- sys계정으로 작업

- 결과들이 저장되는 테이블에는 "DBA_" 접두어가 붙어서 생성됨

- DBMS_REPAIR 패키지는 corrup block를 repair하는것이 아님 (장애난 블록을 찾아서 내용을 고쳐주는 패키지가 아님)

- 장애난 블록을 찾아내서 해당 block을 장애로 mark하고 더이상 사용안하게 막아주고 

   해당 블록 장애때문에 진행 안되던 작업을 계속 할 수 있도록 도와주는 역할




[DBMS_REPAIR package 프로시저]   

1. ADMIN_TABLE 프로시저

block repair를 하기위해 필요한 관리작업(create, drop, purge)을 제공

이런작업을 하기 위한 테이블들은 항상 SYS schema 소유로 생성됨

이 테이블에 손상이 발생한 블록들의 리스트를 저장

2. CHECK_OBJECT 프로시저

table이나 index의 block corruption을 체크하고 문제가 있는 블록은 1번에서 만든 repair table에 기록

3. DUMP_ORPHAN_KEYS 프로시저

corrupted된 블록들이 테이블과 관련된 것이라면 admin_table에서 생성한 곳에 기록되지만

index와 관련있는 블록들이라면 이 테이블에 기록

4. FIX_CORRUPT_BLOCKS 프로시저

check_object로 발견된 corrupt된 block을 mark해줌

5. REBUILD_FREELISTS 프로시저

object의 freelists를 재생성

6. SEGMENT_FIX_STATUS 프로시저

ASSM 기능을 사용하고있는 Bitmap index가 corrupt 되었다면 이 프로시저가 fix 해줌

7. SKIP_CORRUPT_BLOCKS 프로시저

table이나 index scan할때 기존에 mark된 corrupt block들은 확인하지 않고 건너뜀




[DBMS_REPAIR 제약사항 및 한계점]

1. LOB나 Cluster Index는 지원하지 않음

2. DUMP_ORPHAN_KEYS 프로시저는 BITMAP Index, Function-Based Index는 지원하지 않음

3. 3,950 bytes이상은 지원하지 못함




[DBMS_REPAIR 시작하기]

1. Block Corruption 찾아내기

관련패키지 : . CHECK_OBJECT

  . FIX_CORRUPT_BLOCK

위 두가지 패키지를 사용하려면 먼저 ADMIN_TABLE이 실행되어야함


2. admin_tables 프로시저를 실행시켜 REPAIR_TABLE 생성하기

## sys 계정으로 접속하여 작업

SQL>conn / as sysdba;

Connected.


## admin_tables 프로시저를 실행시켜 repair_table생성

SYS>begin

  2     dbms_repair.admin_tables(

  3     table_name => 'REPAIR_TABLE',

  4     table_type => dbms_repair.repair_table,

  5     action => dbms_repair.create_action,

  6     tablespace => 'USERS');

  7  end;

  8  /


PL/SQL procedure successfully completed.


## repair_table조회

SYS>desc repair_table; --또는 dba_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



3. admin_tables 프로시저를 실행해서 Orphan-key-table 생성하기

- 장애가 발생한 테이블과 관련이 있는 다른 object를 저장하는 곳

- 테이블 검사를 하다가 관련이 있는 인덱스 등 문제가 있을수 있기 때문에 미리 생성해두어야 함.


## admin_tables 프로시저를 실행시켜 orphan_key_table 생성

SYS>begin

  2  dbms_repair.admin_tables(

  3     table_name => 'ORPHAN_KEY_TABLE',

  4     table_type => dbms_repair.orphan_table,

  5     action => dbms_repair.create_action,

  6     tablespace => 'USERS');

  7  end;

  8  /


PL/SQL procedure successfully completed.


## orphan_key_table조회

SYS>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


4. DB_Block_checking=true

- 블록에 문제가 있는지 없는지를 확인하려면 오라클 파라미터 중에서 block checking하는 파라미터를 true값으로 변경해주어야함

- DB_BLOCK_CHECKING=true  >> 오라클은 모든 블록을 체크 시작

- 어느정도의 overhead는 감수해야 함

- 이 값을 false로 하게되면 system tablespace만 체크하고 나머지는 체크하지 않음

SYS>show parameter db_block_checking;


NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

db_block_checking                    string      FALSE


SYS>alter system set db_block_checking=true;


System altered.


SYS>show parameter db_block_checking;


NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

db_block_checking                    string      TRUE



5. DBMS_REPAIR실습

## block checking parameter 값을 true로 설정

SYS>show parameter db_block_checking;

NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

db_block_checking                    string      FALSE


SYS>alter system set db_block_checking=true;

System altered.


SYS>show parameter db_block_checking;

NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

db_block_checking                    string      TRUE


## block corruption을 발생시키기 위해서 tablespace 및 table을 생성하고 데이터입력

SYS>@dd

TABLESPACE         MB FILE_NAME

---------- ---------- ---------------------------------------------

USERS              10 /app/oracle/oradata/testdb/users01.dbf

UNDOTBS1           10 /app/oracle/oradata/testdb/undotbs01.dbf

SYSAUX            600 /app/oracle/oradata/testdb/sysaux01.dbf

SYSTEM            710 /app/oracle/oradata/testdb/system01.dbf

EXAMPLE       345.625 /app/oracle/oradata/testdb/example01.dbf


SYS>create tablespace test10 datafile '/app/oracle/oradata/testdb/test01.dbf' size 256k;

Tablespace created.


SYS>@dd

TABLESPACE         MB FILE_NAME

---------- ---------- ---------------------------------------------

USERS              10 /app/oracle/oradata/testdb/users01.dbf

UNDOTBS1           10 /app/oracle/oradata/testdb/undotbs01.dbf

SYSAUX            600 /app/oracle/oradata/testdb/sysaux01.dbf

SYSTEM            710 /app/oracle/oradata/testdb/system01.dbf

EXAMPLE       345.625 /app/oracle/oradata/testdb/example01.dbf

TEST10            .25 /app/oracle/oradata/testdb/test01.dbf


6 rows selected.


SYS>create table scott.tt900 (no number, name varchar2(10)) tablespace test10;

Table created.


SYS>insert into scott.tt900 values (1, 'AA');

1 row created.


SYS>insert into scott.tt900 values (2, 'BB');

1 row created.


SYS>select * from scott.tt900;


        NO NAME

---------- ----------

         1 AA

         2 BB


SYS>alter tablespace test10 offline;
Tablespace altered.

## 해당 data file을 윈도우로 이동시켜서 Block corruption 만든후 다시 리눅스로 이동 후 작업 

SYS>recover tablespace test10;

ORA-00283: recovery session canceled due to errors

ORA-00264: no recovery required


SYS>alter tablespace test10 online;

Tablespace altered.


SYS>select * from scott.tt900;

select * from scott.tt900

                    *

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 6, block # 11)

ORA-01110: data file 6: '/app/oracle/oradata/testdb/test01.dbf' --장애발생


## DBMS_REPAIR을 사용하여 에러찾기

SYS>set serveroutput on;


SYS>declare n_corrupt int;

  2  begin

  3  n_corrupt:=0;

  4  dbms_repair.check_object(

  5     schema_name => 'SCOTT',

  6     object_name => 'TT900',

  7     repair_table_name => 'REPAIR_TABLE',

  8     corrupt_count => n_corrupt);

  9  dbms_output.put_line('장애블록수:' || to_char(n_corrupt));

 10  end;

 11  /

PL/SQL procedure successfully completed.


SYS>set line 200;

SYS>col object_name for a10

SYS>col corrupt_description for a20

SYS>col repair_description for a20


SYS>select object_name, block_id, corrupt_type, marked_corrupt,

  2        corrupt_description, repair_description

  3  from repair_table;


OBJECT_NAM   BLOCK_ID CORRUPT_TYPE MARKED_COR CORRUPT_DESCRIPTION  REPAIR_DESCRIPTION

---------- ---------- ------------ ---------- -------------------- --------------------

TT900              11         6148 TRUE                            mark block software

                                                                               corrupt

--> 11번 블록이 문제가 있다는것이 확인되며 corrupt 되었다고 mark됨


## corrupt된 블록 FIX
SYS>set serveroutput on;
SYS>declare n_fix int;
  2  begin
  3  n_fix:=0;
  4  dbms_repair.fix_corrupt_blocks(
  5     schema_name => 'SCOTT',
  6     object_name => 'TT900',
  7     object_type => dbms_repair.table_object,
  8     repair_table_name => 'REPAIR_TABLE',
  9     fix_count => n_fix);
 10  dbms_output.put_line('fix_count:' ||to_char(n_fix));
 11  end;
 12  /
fix_count:0 --fix된 블록의 갯수 (check_object 부분에서 자동으로 fix되었기 때문에 따로 하지 않아도 됨)
PL/SQL procedure successfully completed.

SYS>select * from scott.tt900; --테이블 여전히 조회안됨

select * from scott.tt900

                    *

ERROR at line 1:

ORA-01578: ORACLE data block corrupted (file # 6, block # 11)

ORA-01110: data file 6: '/app/oracle/oradata/testdb/test01.dbf'



## corrupt된 블록의 데이터를 제외한 나머지 블록만 읽어서 데이터만이라도 살려내고 싶을때
SYS>begin
  2  dbms_repair.skip_corrupt_blocks(
  3     schema_name => 'SCOTT',
  4     object_name => 'TT900',
  5     object_type => dbms_repair.table_object,
  6     flags => dbms_repair.skip_flag);
  7  end;
  8  /
PL/SQL procedure successfully completed.

SYS>select * from scott.tt900; --corrupt된 블록만 제외하고 나머지 블록을 읽어서 데이터를 살림
        NO NAME
---------- ----------
         1 AA
         2 BB

## corrupt된 블록을 skip하도록 설정되어있는지 조회
SYS>select owner, table_name, skip_corrupt
  2  from dba_tables
  3  where owner='SCOTT'
  4  and table_name='TT900';

OWNER                          TABLE_NAME                     SKIP_COR
------------------------------ ------------------------------ --------
SCOTT                          TT900                          ENABLED




[DBMS_REPAIR 패키지 활용 실습]




댓글