Computer >> 컴퓨터 >  >> 프로그래밍 >> 데이터베이스

Oracle 데이터베이스 블록 손상 복구 완벽 가이드: 시스템 데이터 파일까지

이 글에서는 Oracle® 데이터베이스에서 발생하는 단일 또는 다중 블록 손상(block corruption)을 진단하고 복구하는 방법을 다룹니다. 시스템(SYSTEM) 데이터 파일의 손상까지 포함하며, 실제 운영 환경에서 자주 마주치는 문제를 실무 관점에서 해결하는 절차를 소개합니다.

블록 손상은 데이터베이스 장애(downtime)의 대표적인 원인 중 하나입니다. 데이터베이스 블록의 내용이 Oracle이 기대하는 값과 다를 때 해당 블록은 손상된 것으로 간주되며, 이를 적절히 예방하거나 복구하지 않으면 데이터베이스 전체가 중단되고 핵심 비즈니스 데이터가 유실될 수 있습니다.

블록 손상 찾기 및 복구

다음은 블록 손상이 발생한 사례입니다.

이미지 출처: https://blog.toadworld.com/2017/12/01/block-corruption-in-an-oracle-database

1단계: 손상 위치 확인

손상된 블록을 확인하려면 아래 명령어를 실행합니다.

SQL> select * from V$DATABASE_BLOCK_CORRUPTION;

FILE#    BLOCK#    BLOCKS    CORRUPTION_CHANGE#  CORRUPTION
----- ---------- ----------  ------------------  ----------
 352     173191      9               0            ALL ZERO

SQL> SELECT FILE_ID,RELATIVE_FNO,FILE_NAME,TABLESPACE_NAME FROM DBA_DATA_FILES WHERE FILE_ID=352;

 FILE_ID   RELATIVE_FNO   FILE_NAME                                          TABLESPACE_NAME
---------- ------------ -------------------------------------------------- ------------------
    352        352      /u01/apps_st/samusxxxxxxxx_data2/system09.dbf              SYSTEM

SQL> SELECT owner, segment_name, segment_type FROM dba_extents WHERE RELATIVE_FNO = 352 AND Block_id BETWEEN 173191 AND 173191 + blocks - 1;

OWNER      SEGMENT_NAME    SEGMENT_TYPE
-------- ---------------  ------------------
SYS         I_COL3          INDEX
SYS         C_OBJ#          CLUSTER

참고: 이 사례에서는 SYS 오브젝트 세그먼트 I_COL3에 블록 손상이 발생했습니다. dbv 명령으로 보고된 손상 블록은 dba_free_space 뷰에서는 여유 공간(free)으로 표시됩니다.

2단계: 블록 해제 상태 확인

파일 352의 해당 블록이 여유 상태인지 확인하려면 다음 명령어를 실행합니다.

SQL> select * from V$DATABASE_BLOCK_CORRUPTION;

FILE#    BLOCK#    BLOCKS    CORRUPTION_CHANGE#  CORRUPTION
----- ---------- ----------  ------------------  ----------
 352     173191      9               0            ALL ZERO

SQL> Select * from dba_free_space where file_id =352 and 173191 between block_id and block_id + blocks -1;

TABLESPACE_NAME   FILE_ID  BLOCK_ID  BYTES    BLOCKS   RELATIVE_FNO
---------------   -------  --------  -----  ---------- ------------
   SYSTEM           352     173191   73728       9        352

3단계: 손상 블록 강제 초기화(포맷)

블록이 여유 공간으로 확인되면, 어떤 세그먼트에도 속하지 않는 손상 블록을 강제로 포맷(formatting)하여 초기화할 수 있습니다. 절차는 다음과 같습니다.

3-1. 테스트용 사용자 생성 및 권한 부여

create user Scott identified by password default tablespace SYSTEM;
grant resource, connect, create table, create trigger to Scott;

3-2. DBVERIFY로 손상 블록 식별

dbv(DBVERIFY) 유틸리티를 사용해 데이터 파일 내 손상 블록을 정확히 파악합니다.

[Thu Nov 17 11:59:19 orbdev@samusxxxxxxxx:~ ] $ dbv file='/mnt/apps_st/samusxxxxxxxx_data2/system09.dbf' userid=sys/xxxxx

DBVERIFY: Release 11.2.0.4.0 - Production on Thu Nov 17 11:59:21 2016

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

DBVERIFY - Verification starting: FILE = /mnt/apps_st/samusxxxxxxxx_data2/system09.dbf
Page 173191 is marked corrupt
Corrupt block relative dba: 0x5802a487 (file 352, block 173191)
Completely zero block found during dbv:

Page 173192 is marked corrupt
Corrupt block relative dba: 0x5802a488 (file 352, block 173192)
Completely zero block found during dbv:

... (중략: Page 173193 ~ 173199 동일하게 zero block 손상 감지) ...

DBVERIFY - Verification complete

Total Pages Examined         : 917504
Total Pages Processed (Data): 253735
Total Pages Failing   (Data) : 0
Total Pages Processed (Index): 335744
Total Pages Failing   (Index): 0
Total Pages Processed (Other): 375
Total Pages Processed (Seg)  : 17
Total Pages Failing   (Seg)  : 0
Total Pages Empty            : 327624
Total Pages Marked Corrupt   : 9
Total Pages Influx           : 0
Total Pages Encrypted        : 0
Highest block SCN            : 3412538527 (1421.3412538527)

[Thu Nov 17 12:00:13 orbdev@samusxxxxxxxx:~ ] $

3-3. 여유 공간 확인

Select * from dba_free_space where file_id= <Absolute file number> and <corrupted block number> between block_id and block_id + blocks -1;


SQL> Select * from dba_free_space where file_id=352 and 173191 between block_id and block_id + blocks -1;

TABLESPACE_NAME   FILE_ID   BLOCK_ID     BYTES    BLOCKS   RELATIVE_FNO
--------------- ---------- ---------- ---------- --------- ------------
SYSTEM              352     173196      73728        9          352

3-4. 첫 번째 손상 블록 재포맷

아래 절차를 모든 손상 블록이 재포맷될 때까지 반복합니다.

create table scott.s (n number,c varchar2(4000)) nologging tablespace SYSTEM;

select owner,table_name,tablespace_name from dba_tables where table_name='S';

SQL> CREATE OR REPLACE TRIGGER corrupt_trigger
   AFTER INSERT ON scott.s
   REFERENCING OLD AS p_old NEW AS new_p
   FOR EACH ROW
   DECLARE
   corrupt EXCEPTION;
   BEGIN
   IF (dbms_rowid.rowid_block_number(:new_p.rowid)=&blocknumber)
     and (dbms_rowid.rowid_relative_fno(:new_p.rowid)=&filenumber) THEN
     RAISE corrupt;
   END IF;
   EXCEPTION
   WHEN corrupt THEN
     RAISE_APPLICATION_ERROR(-20000, 'Corrupt block has been formatted');
   END;
 /

Enter value for blocknumber: 173191
old   8:   IF (dbms_rowid.rowid_block_number(:new_p.rowid)=&blocknumber)
new   8:   IF (dbms_rowid.rowid_block_number(:new_p.rowid)=173191)

Enter value for filenumber: 352
old   9:  and (dbms_rowid.rowid_relative_fno(:new_p.rowid)=&filenumber) THEN
new   9:  and (dbms_rowid.rowid_relative_fno(:new_p.rowid)=352) THEN

Trigger created.

Select BYTES/1024/1024 from dba_free_space where file_id=352 and 173191 between block_id and block_id + blocks -1;

72K

SQL> BEGIN
   FOR i IN 1..100000 LOOP
      EXECUTE IMMEDIATE 'alter table scott.s allocate extent (DATAFILE '||'''/mnt/apps_st/samusxxxxxxxx_data2/system09.dbf''' ||'SIZE 72K)';
   END LOOP;
END;
/

SQL> BEGIN
  FOR i IN 1..1000000 LOOP
     INSERT /*+ APPEND */ INTO scott.s select i, lpad('REFORMAT',3092, 'R') from dual;
  commit ;
  END LOOP;
END;
/

SQL> Select * from v$database_block_corruption;

no rows selected

DROP TABLE scott.s;

Alter system switch logfile;

Alter system checkpoint;

DROP trigger corrupt_trigger;

3-5. 복구 결과 검증

모든 작업이 끝나면 손상 블록이 실제로 해소되었는지 V$DATABASE_BLOCK_CORRUPTION 뷰와 dbv 유틸리티로 최종 검증합니다.

SQL> select * from V$DATABASE_BLOCK_CORRUPTION;

no rows selected

[Wed Nov 16 08:12:37 orbdev@samusxxxxxx:~ ] $ dbv file='/mnt/apps_st/samusxxxxxx_data2/system09.dbf' userid=sys/****

DBVERIFY: Release 11.2.0.4.0 - Production on Wed Nov 16 08:12:41 2016

Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.

DBVERIFY - Verification starting : FILE = /mnt/apps_st/samusxxxxxx_data2/system09.dbf

DBVERIFY - Verification complete

Total Pages Examined     : 655359
Total Pages Processed (Data) : 260868
Total Pages Failing  (Data) : 0
Total Pages Processed (Index): 340482
Total Pages Failing  (Index): 0
Total Pages Processed (Other): 278
Total Pages Processed (Seg): 15
Total Pages Failing (Seg): 0
Total Pages Empty     : 53716
Total Pages Marked Corrupt : 0
Total Pages Influx     : 0
Total Pages Encrypted   : 0
Highest block SCN     : 136830000 (1422.136830000)

[Wed Nov 16 08:14:50 orbldev2@samusxxxxxx:~ ] $

검증 결과 Total Pages Marked Corrupt : 0으로 표시되며, 손상 블록이 성공적으로 복구되었음을 확인할 수 있습니다.

결론: 블록 손상 예방을 위한 MAA 모범 사례

데이터 손상을 사전에 탐지하고 예방하기 위해, Oracle이 권장하는 최대 가용성 아키텍처(Maximum Availability Architecture, MAA) 모범 사례를 적용하는 것이 좋습니다.

  • Oracle Data Guard 활용: 대기(Standby) 데이터베이스를 통해 장애 시 신속한 전환과 데이터 보호를 실현합니다.
  • 블록 손상 탐지 파라미터 설정: DB_BLOCK_CHECKSUM, DB_LOST_WRITE_PROTECT 등 Oracle Database의 손상 탐지 파라미터를 활성화합니다.
  • RMAN 기반 백업·복구 전략 구축: Recovery Manager(RMAN)를 활용해 정기적인 백업과 블록 손상 검사(BACKUP VALIDATE, RESTORE ... VALIDATE)를 수행합니다.

이러한 고가용성 솔루션은 Oracle Database와 긴밀하게 통합되어 있으며, 데이터베이스의 내부 데이터 구조를 활용하기 때문에 기존 도구보다 한 단계 진보한 지능형 데이터 보호 및 재해 복구 기능을 제공합니다.

궁금한 점이나 의견이 있다면 피드백 탭을 통해 남겨 주세요. 데이터베이스 서비스 및 애플리케이션 서비스에 대한 자세한 내용도 함께 확인해 보시기 바랍니다.