1          개요 및 목적

  • Blcok corruption이 발생으로 인한 오류 ORA-01578 발생원인과 종류 및 확인, 처리방법에 이문서의 목적을 둔다.

1.1   Block Corruption 종류

1.1.1  Logical Corruption

  • 메모리 블록의 손상
  • ORA-600 에러중 첫번째 인수가 3398 발생

 

1.1.2  Physical Corruption

  • 물리적 블록의 손상
  • ORA-1579 에러발생
  • ORA-600 [3339]와 ORA-600[4519] 는 메모리와 디스크 손상 모두와 연관

2          BLOCK CORRUPTION 발생원인

  • Disk 손상으로 인한 문제 발생
  • 메모리상에서 이미 손상된 블록을 디스크상에 그대로 기록된 경우
  • 블록이 데이터파일상의 기록될 위치를 잘못찾아 손상된경우(write blocks out of sequence)
  • I/O controller 문제
  • 동일한 디바이스에서 다른 블록을 읽어온경우 (O/S, H/W 문제인 경우 많음)
  • Oracle이나 O/S bug

3          Block corruption 확인

  • 손상된 블록 access시에 에러발생
select * from t1;
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # x, block #xxxx)

 

  • dbv 확인
dbv file=test1_01.dbf blocksize=8192

 

  • Corruption된 블록의 object 확인
— f: 화일번호

— b: 블럭번호

select segment_name, segment_type

from dba_extents

where file_id = f and

b between block_id and block_id + blocks – 1;

 

4          RECOVERY SCENARIO

4.1   RMAN을 이용한 RECOVERY

4.1.1  환경구성

SQL> create tablespace test1 datafile ‘/u01/oradata/ORA/test1_01.dbf’ size 1M;

SQL> alter user test identified by test default tablespace test1;

SQL> insert into t1

select *

from dual

connect by level <=1000;

SQL> commit;

SQL> alter system switch logfile;

 

4.1.2  Rman backup 수행

RMAN> report schema;

Report of database schema

List of Permanent Datafiles

===========================

File Size(MB) Tablespace           RB segs Datafile Name

—- ——– ——————– ——- ————————

5    0        MGMT_TABLESPACE      ***     /u01/app/oracle/OracleHome/oms10g/oradata/mgmt.dbf

6    0        MGMT_ECM_DEPOT_TS    ***     /u01/app/oracle/OracleHome/oms10g/oradata/mgmt_ecm_depot1.dbf

7    1        TEST1                ***     /u01/oradata/ORA/test1_01.dbf

List of Temporary Files

=======================

File Size(MB) Tablespace           Maxsize(MB) Tempfile Name

—- ——– ——————– ———– ——————–

1    20       TEMP                 32767       /u01/oradata/ORA/temp01.dbf

 

RMAN> backup tablespace test1;

Starting backup at 02-APR-10

piece handle=/u01/recovery/ORA/backupset/2010_04_02/o1_mf_nnndf_TAG20100402T150042_5vc20b5t_.bkp tag=TAG20100402T150042 comment=NONE

Finished backup at 02-APR-10

RMAN> list backup

RMAN> list backupset 11;

List of Backup Sets

===================

BS Key  Type LV Size       Device Type Elapsed Time Completion Time

——- —- — ———- ———– ———— —————

11      Full    152.00K    DISK        00:00:00     02-APR-10

BP Key: 11   Status: AVAILABLE  Compressed: NO  Tag: TAG20100402T150042

Piece Name: /u01/recovery/ORA/backupset/2010_04_02/o1_mf_nnndf_TAG20100402T150042_5vc20b5t_.bkp

List of Datafiles in backup set 11

File LV Type Ckp SCN    Ckp Time  Name

—- — —- ———- ——— —-

7       Full 1621908    02-APR-10 /u01/oradata/ORA/test1_01.dbf

 

 

4.1.3  BLOCK CORRUPT 작업

l  Segment 정보확인

select owner, segment_name, segment_type, header_file, header_block, blocks,

tablespace_name from dba_segments

where owner =’TEST’ and segment_name =’T1′;

 

 

OWNER SEGMENT_NAME SEGMENT_TYPE HEADER_FILE HEADER_BLOCK BLOCKS TABLESPACE_NAME
TEST T1 TABLE 7 11 8 TEST1

l  Data file 정보

select file#, ts#, rfile#, status, enabled, name, blocks, block_size

from v$datafile where file#= 7 ;

 

FILE# TS# RFILE# STATUS ENABLED NAME BLOCKS BLOCK_SIZE
7 9 7 ONLINE READ WRITE /u01/oradata/ORA/test1_01.dbf 128 8192

 

l  Corrupt 할 block 정보 확인 (15번 block corrution 예정)

select c1, rowid, dbms_rowid.rowid_relative_fno(rowid) fno#,

dbms_rowid.rowid_block_number(rowid) blk#

from t1;

 

번호 C1 ROWID FNO# BLK#
94 X AAARr8AAHAAAAAMABd 7 12
95 X AAARr8AAHAAAAAMABe 7 12
96 X AAARr8AAHAAAAAMABf 7 12
97 1111 AAARr8AAHAAAAAPAAA 7 15
98 2222 AAARr8AAHAAAAAPAAB 7 15
99 X AAARr8AAHAAAAAPAAC 7 15
100 X AAARr8AAHAAAAAPAAD 7 15
101 X AAARr8AAHAAAAAPAAE 7 15
102 X AAARr8AAHAAAAAPAAF 7 15
562 X AAARr8AAHAAAAAQAAM 7 16

 

l  15번째 block corruption 한다

$ dd if=/dev/zero of=/u01/oradata/ORA/test1_01.dbf seek=15 count=1 bs=8192 conv=notrunc

1+0 records in

1+0 records out

$

SQL> alter system flush buffer_cache;   buffer cache를 flush 한다

System altered.

SQL> select * from t1;

select * from t1

*

ERROR at line 1:

ORA-08103: object no longer exists

SQL> select * from t1 where rowid =’AAARr8AAHAAAAAMABd’;   12번 block rowid로 확인

C1

———-

X

SQL> select * from t1 where rowid =’AAARr8AAHAAAAAPAAA’;  15번 rowid로 확인

select * from t1 where rowid =’AAARr8AAHAAAAAPAAA’

*

ERROR at line 1:

ORA-08103: object no longer exists

 

 

4.1.4  Block corruption 확인

4.1.4.1    Dbv를 이용한 확인

$ dbv file=test1_01.dbf blocksize=8192

DBVERIFY: Release 10.2.0.1.0 – Production on Fri Apr 2 16:40:08 2010

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

DBVERIFY – Verification starting : FILE = test1_01.dbf

Page 15 is marked corrupt

Corrupt block relative dba: 0x01c0000f (file 7, block 15)

Completely zero block found during dbv:

DBVERIFY – Verification complete

Highest block SCN            : 1621880 (0.1621880)

 

4.1.4.2    dbms_repair package를 활용한 확인작업

l  손상된 블록의 정보를 보관한 table, view 생성

SQL> exec dbms_repair.admin_tables(‘

REPAIR_TABLE’,   table name

DBMS_REPAIR.REPAIR_TABLE,  table type

DBMS_REPAIR.CREATE_ACTION,  작업

‘USERS’);  테이블스페이스

PL/SQL procedure successfully completed.

SQL> select * from tab where tname like ‘%REPAIR%’;

TNAME                          TABTYPE   CLUSTERID

—————————— ——- ———-

REPAIR_TABLE                    TABLE

DBA_REPAIR_TABLE         VIEW

l  손상된 블록을 가진 테이블의 index 를 위한 테이블생성

SQL> exec dbms_repair.admin_tables(

‘ORPHAN_KEY_TABLE’,

DBMS_REPAIR.ORPHAN_TABLE,

DBMS_REPAIR.CREATE_ACTION

,’USERS’);

PL/SQL procedure successfully completed.

SQL> select * from tab where tname like ‘%ORPHAN%’;

TNAME                          TABTYPE   CLUSTERID

—————————— ——- ———-

ORPHAN_KEY_TABLE         TABLE

DBA_ORPHAN_KEY_TABLE             VIEW

l  손상된 테이블

SQL> SET SERVEROUTPUT ON

SQL> VAR CORRUPT_COUNT NUMBER

SQL> BEGIN

2  DBMS_REPAIR.CHECK_OBJECT

3  (

4  ‘TEST’,’T1′,REPAIR_TABLE_NAME=>’REPAIR_TABLE’

5  ,CORRUPT_COUNT=>:CORRUPT_COUNT);

6  end;

7  /

BEGIN

*

ERROR at line 1:

ORA-00600: internal error code, arguments: [4555], [0], [], [], [], [], [], []

ORA-06512: at “SYS.DBMS_REPAIR”, line 293

ORA-06512: at line 2

l  손상되지 않은 테이블

SQL> set serveroutput on

DECLARE num_corrupt INT;

BEGIN

num_corrupt := 0;

DBMS_REPAIR.CHECK_OBJECT (

SCHEMA_NAME => ‘&schema_name’,

OBJECT_NAME => ‘&object_name’,

REPAIR_TABLE_NAME => ‘REPAIR_TABLE’,

corrupt_count => num_corrupt);

DBMS_OUTPUT.PUT_LINE(‘number corrupt: ‘ || TO_CHAR (num_corrupt));

END;

/SQL>   2    3    4    5    6    7    8    9   10   11

Enter value for schema_name: TEST

old   5: SCHEMA_NAME => ‘&schema_name’,

new   5: SCHEMA_NAME => ‘TEST’,

Enter value for object_name: T2

old   6: OBJECT_NAME => ‘&object_name’,

new   6: OBJECT_NAME => ‘T2’,

number corrupt: 0

PL/SQL procedure successfully completed.

 

4.1.4.3    RMAN을 이용한 확인

RMAN> backup validate check logical database skip offline; offline datafile skip

Starting backup at 05-APR-10

input datafile fno=00007 name=/u01/oradata/ORA/test1_01.dbf

channel ORA_DISK_1: backup set complete, elapsed time: 00:00:55

SQL> select * from v$database_block_corruption;

no rows selected   validation check(RMAN) 작업전

SQL>

SQL> validation check(RMAN) 작업 후

FILE#     BLOCK#       BLOCKS CORRUPTION_CHANGE# CORRUPTIO

———- ———- ———- —————— ———

        7        15          1         0 ALL      ZERO

 

4.1.5  RECOVERY

4.1.5.1    데이터 확인

  • 위에서 7번파일의 15번째 블록이 손상된 것을 확인할수 있다.
  • 과연 그곳에 데이터가 존재하는지는 확인해보자
select segment_name, segment_type

from dba_extents

where file_id = 7 and

15 between block_id and block_id + blocks – 1;

 

SEGMENT_NAME          SEGMENT_TYPE

——————– ——————

T1                 TABLE

 

4.1.5.2    데이터 복구

  • Corrutpion된 block이 table이란 것을 위에서 확인했다
  • Rman으로 복구작업을 진행한다.
RMAN> blockrecover datafile 7 block 15;

Starting blockrecover at 06-APR-10

using target database control file instead of recovery catalog

allocated channel: ORA_DISK_1

channel ORA_DISK_1: sid=148 devtype=DISK

channel ORA_DISK_1: restoring block(s)

channel ORA_DISK_1: specifying block(s) to restore from backup set

restoring blocks of datafile 00007

channel ORA_DISK_1: reading from backup piece /u01/recovery/ORA/backupset/2010_04_02/o1_mf_nnndf_TAG20100402T150042_5vc20b5t_.bkp

channel ORA_DISK_1: restored block(s) from backup piece 1

piece handle=/u01/recovery/ORA/backupset/2010_04_02/o1_mf_nnndf_TAG20100402T150042_5vc20b5t_.bkp tag=TAG20100402T150042

channel ORA_DISK_1: block restore complete, elapsed time: 00:00:01

starting media recovery

media recovery complete, elapsed time: 00:00:03

Finished blockrecover at 06-APR-10

 

4.1.6  Recovery data 확인

Sql> select * from t1;

X

1002 rows selected.

SQL> select * from t1 where rowid =’AAARr8AAHAAAAAPAAA’;

C1

 

4.2   Export backup을 이용한 Recovery

4.2.1  Export/import를 이용한 recovery

l  정상적인 data export 작업 수행

$ exp test/test file=test_exp.dmp log=test_exp.log

. . exporting table           SYS_EXPORT_SCHEMA_01         11 rows exported

. . exporting table                             T1       1002 rows exported

. . exporting table                             T2          0 rows exported

 

 

l  Datapump를 이용한 export

Export: Release 10.2.0.1.0 – Production on Tuesday, 06 April, 2010 12:48:43

. . exported “TEST”.”T1″                                 19.58 KB    1002 rows

. . exported “TEST”.”T2″                                     0 KB       0 rows

 

 

4.2.2  Block corruption 작업수행

  • 1.3.과 같은 방법을 이용해서 block corruption을 수행한다.
  • 1.4와 같은 방법으로 blcok corruption을 확인한다

 

4.2.3  Export 재수행

  • T1 테이블이 정상적으로 export 되지 않는다.
l  TEST_corruption.dmp로 export 작업 수행

EXP-00091: Exporting questionable statistics.

. . exporting table                             T1

EXP-00056: ORACLE error 8103 encountered

ORA-08103: object no longer exists

. . exporting table                             T2          0 rows exported

. exporting synonyms

 

4.2.4  Import를 통한 T1 테이블 Recovery

SQL> drop table test.t1;  정상적으로 backup 받아진 파일 확인후 작업

Table dropped.

l  Imp test/test file=test.dmp log=test_imp.log tables=t1

Sql> select * from t1;

X

X

1002 rows selected.

  • Export 받기전에 DATA만 복구 가능함
  • DATA가 변경이 없는경우에 사용가능

5          사용하지않는 block corruption 발생

  • 백업후 기존의 T1테이블 삭제, 새로운 T1테이블 생성후 새로운 데이터 입력
  • Block corruption을 발생시킨다..(데이터가 들어있지 않은 블록)

 

5.1.1  확인 및 수행 순서

l  새로운 데이터 입력

l  Block corrution 작업

l  Dbv 확인

$ dbv file=test1_01.dbf blocksize=8192

DBVERIFY – Verification starting : FILE = test1_01.dbf

Page 15 is marked corrupt

Corrupt block relative dba: 0x01c0000f (file 7, block 15)

 

l  Table인지 index인지 확인한다

select segment_name, segment_type

from dba_extents

where file_id = 7 and

15 between block_id and block_id + blocks – 1;

l  Index시 Rebuild 작업수행

l  Table시 복구작업수행

l  데이터가 없을시 exp -> imp로 수행

 

6          Event(10210, 10211, 10231) 사용

  • 8i 이전버전에서 block skip할 때 사용한다.
  • Block corrupt으로 인해 table 전체를 읽지 못할 때
  • Corruption 된 블록의 데이터가 필요치 않을경우

 

7          dbms_repair (8i 이후버전)

7.1   rapair table 생성

BEGIN

DBMS_REPAIR.ADMIN_TABLES (

TABLE_NAME => ‘REPAIR_TABLE’,

TABLE_TYPE => dbms_repair.repair_table,

ACTION => dbms_repair.create_action,

TABLESPACE => ‘&tablespace_name’);

END;

/

7.2   block cuttuption schema, objcet 입력 (정보수집)

set serveroutput on

DECLARE num_corrupt INT;

BEGIN

num_corrupt := 0;

DBMS_REPAIR.CHECK_OBJECT (

SCHEMA_NAME => ‘&schema_name’,

OBJECT_NAME => ‘&object_name’,

REPAIR_TABLE_NAME => ‘REPAIR_TABLE’,

corrupt_count => num_corrupt);

DBMS_OUTPUT.PUT_LINE(‘number corrupt: ‘ || TO_CHAR (num_corrupt));

END;

/

 

  • 수집된 정보 확인
select BLOCK_ID, CORRUPT_TYPE, CORRUPT_DESCRIPTION

from REPAIR_TABLE;

 

 

7.3   Block fixed

  • Table block fix
DECLARE num_fix INT;

BEGIN

num_fix := 0;

DBMS_REPAIR.FIX_CORRUPT_BLOCKS (

SCHEMA_NAME => ‘&schema_name’,

OBJECT_NAME=> ‘&object_name’,

OBJECT_TYPE => dbms_repair.table_object,

REPAIR_TABLE_NAME => ‘REPAIR_TABLE’,

FIX_COUNT=> num_fix);

DBMS_OUTPUT.PUT_LINE(‘num fix: ‘ || to_char(num_fix));

END;

/

 

  • table repair후 full scan 에러 지속시 인덱스 정보 확인
Select index_name from dba_indexes

where table_name in (select distinct object_name from repair_table);

 

  • curruption data index 정보수집
var key_count number
SQL> begin
2  dbms_repair.dump_orphan_keys(
3  schema_name=>”,
4  object_name=>”,
5  object_type=>DBMS_REPAIR.INDEX_OBJECT,
6  repair_table_name=>’REPAIR_TABLE’,
7  orphan_table_name=>’ORPHAN_KEY_TABLE’,
8  key_count=>:key_count);
9  end;
10  /

 

  • curruption data index 정보확인
select SCHEMA_NAME, INDEX_NAME, INDEX_ID, TABLE_NAME, KEYROWID from orphan_key_table;

—- 추출된 index를 rebuild 해준다

 

8          ORACLE BUG 로 인한 block corruption

n  Bug 4655520 Block corrupted during write not noticed 에서보면 아래 버젼에서 block corruption 이 발생

–    9.2.0.6

–    9.2.0.7

–    10.1.0.5

–    10.2.0.2

l  이것은 아래버전에서 fix되었습니다.

–    9.2.0.8 (Server Patch Set)

–    10.1.0.6 (Server Patch Set)

–    10.2.0.3 (Server Patch Set)11g (Future version)

n  Bug 4411228 – Block corruption with mixture of file system and RAW files 발생가능한 버전

–    9.2.0.5

–    9.2.0.7

–    10.1.0.5

–    10.2.0.2

l  fix된 버전

–    9.2.0.8 (Server Patch Set)

–    10.1.0.6 (Server Patch Set)

–    10.2.0.3 (Server Patch Set)

–    11g (Future version)

n  Bug 5061091 Block recovery corrupts undo header when log_parallelism > 1 발생가능 버전

–    9.2.0.6

–    10.1.0.5

–    10.2.0.2

l  fix된 버전

–    10.1.0.6 (Server Patch Set)

–    10.2.0.3 (Server Patch Set)

–    11g (Future version

 

 

 

By haisins

오라클 DBA 박용석 입니다. haisins@gmail.com 으로 문의 주세요.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다