IT기술/Oracle

17 Block Corruption and Repair

dobbby 2014. 1. 3. 18:37
반응형

이번  장에서는  오라클  장애  중에서  가장  난해한  부분  중  한가지  인  Block  Corruption  장애를  살펴보겠습니다.

이번  장에서  살펴볼  내용을  간단히  정리하면  아래와  같습니다. 


데이터가  저장되는  Block  들에  corruption  이  발생  할  경우에  Recovery  할 수  있는  

가장  보편적이고  일반적인  기술들에  대해서  실습을  통해서  알아봅니다. 


1. DBVerify  를  이용한  Block Recovery 

2. DBMS_REPAIR  을  이용한  Block Recovery 


그리고  마지막으로  공식적으로  문서화  되어  있지  않지만  아주  중요하고  막강한  Block  Recovery tool  인  

BBED  라는  툴을  살펴보고  BBED  툴을  이용하여  여러  가지  장애가  발생할  경우  어떻게  복구를  할  수  있는지

예를  통해서  Block Recovery  를  마무리  하겠습니다. 


3. BBED를  이용한  Block recovery 

Block  Corruption  장애를  해결하기  위해서는  데이터가  저장되어  있는  오라클  Block  의  구조를  잘 아셔야  하며

여기서  지면  관계상  언급하지  못한  오라클의  저장구조에  대한  설명은  저자의  다른 저서인  오라클  관리  실무  책을  참고하시기  바랍니다. 




1. DBVERIFY  를  이용한  Block  관리 

DBVerify  유틸리티는  오라클  7.3.2  버전부터  현재까지  제공되고  있는  Data  file  Block과  index  file block, undo block  등을  점검해  주는  유틸리티입니다.  

이  유틸리티는  Database  가  Open  되어  있는  상태에서  사용하는  유틸리티라서  DB의  중단  없이 점검할  수  있습니다.

대신  점검  중인  데이터파일은  Read-Only  가  되기  때문에  만약  점검  중일  때 DML  작업이  발생하면  잠시  작업이  중단되었다가  다시  실행됩니다. 


-  사용  문법  : dbv file= file_name [options] 


1)  주요  옵션들 

- FILE: 점검해야  할  파일명을  적습니다. 

- START : 점검을  시작할  블록  번호를  적습니다. 

          기본값은  해당  파일의  첫번째  블록입니다. 

- END : 점검을  종료할  블록  번호를  적습니다.  

        기본값은  해당  파일의  마지막  블록입니다 

- BLOCKSIZE:  점검하기를  원하는  파일의  Block  크기를  적어주면  됩니다.  

             기본값은  2048 (2k)입니다. 

- LOGFILE:  점검  결과를  저장할  파일명을  지정합니다.  기본값은  ‘NONE ‘  이며  검사  결과를  화면 

           으로  출력해서  보여줍니다. 

- FEEDBACK: 0  이상의  숫자로  설정할  수  있으며  (기본값은  0초)  검사가  진행되는  동안에  화면 

             에  .(dot)  을  찍어서  진행  과정을  표시해  줍니다. 

- PARFILE: DBV  를  실행할  때  적용하는  각종  설정들을  이  파일에  저장해두고  불러와서 

           사용할  수  있습니다. (exp  나  datapump  에서  parfile  옵션과  비슷한  역할입니다) 

- USERID: ASM  기반의  파일을  점검할  경우  ASM  인스턴스에  접속해야  하기  때문에  반드시 

           USERID  를  사용해야만  합니다. 

- SEGMENT_ID:  특정  세그먼트(TABLE, INDEX, UNDO)만  골라서  검사할  수  있습니다.  

                이  기능은  9i  이상에서만  사용할  수  있습니다 


2) DBV  의  주요  특징들 

(1) Block Level  에서의  점검만  가능하고  Analyze table … validate structure  와  같이  테이블과  인덱스간의  불일치  같은  문제는  점검하지  못합니다. 

(2)  오직  데이터  파일만  점검할  수  있습니다.  즉  Redo  log  file  이나  Control  file  은  점검할  수  없습니다. 

Redo Log File  을  점검하려고  시도하면  아래와  같은  에러가  나옵니다.. 


[ 10g  일  경우  ] 

[oracle@localhost ~]$ dbv file=/home/oracle/oradata/testdb/redo01_b.log 

DBVERIFY: Release 10.2.0.5.0 - Production on Mon Feb 21 08:00:51 2011 

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

DBV-00103: Specified BLOCKSIZE (8192) differs from actual (512) 


[ 11g  일  경우  ] 

[oracle@localhost ~]$ dbv file=/app/oracle/oradata/testdb/redod01_a.log 

DBVERIFY: Release 11.2.0.2.0 - Production on Mon Nov 25 20:19:53 2013 

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

DBV-00100: Specified FILE (/app/oracle/oradata/testdb/redod01_a.log) not accessible 


(3)  ASM  파일까지  점검할  수  있습니다.  단  ASM  인스턴스에  로그인  할  수  있는  계정  정보를  함께 입력해야  합니다. 

[oracle@localhost ~]$ dbv file=+ASM/TESTDB/datafile/system01.dbf  

userid=system/oracle 


(4)  특정  데이터  파일이  아닌  세그먼트  단위로  검사를  할  수  있습니다. 

예를  들어  크기가  무척  큰  고객  테이블만  검사한다든지  특정  인덱스만  검사하는  것을  의미합니다. 

자세한  사용법은  뒷부분에  나옵니다. 


3) DBVerify  실행하기 

(1)  특정  파일  검사하기 

[oracle@localhost ~]$ dbv file=/app/oracle/oradata/testdb/example01.dbf 


위  실행결과의  주요  항목의  의미는  아래와  같습니다. 

** Total Pages Examined :  테스트  한  총  블록의  개수 

** Total Pages Processed (Data) :  테스트  한  총  테이블  블록  개수  

** Total Pages Failing    (Data) :  문제가  있는  블록  개수 

** Total Pages Processed (Index) :  테스트  한  총  인덱스  블록  개수 

** Total Pages Failing    (Index) :  문제가  있는  블록  개수 

** Total Pages Processed (Other):  테이블이나  인덱스  외  다른  블록 개수 

** Total Pages Empty :  비어있는  블록  개수 

** Total Pages Marked Corrupt:  문제가  있어서  Corrupt Marked  된  블록  개수 

** Total Pages Influx:  다른  사용자가  먼저  데이터를  변경하고  있어서  DBV를  하기  위해 

            다시  읽은  블록  개수 


(2)  특정  세그먼트만  검사하기 

여기서는  연습용으로  tt800  이라는  테이블을  만들고  데이터를  입력해서  35  MB  크기의  테이블을 생성  한  후  

해당  테이블의  SEGMENT ID를  조회해서  검사해  보겠습니다. 

SQL> select sum(bytes)/1024/1024 as MB from dba_segments 

  2   where segment_name='TT800'; 


SQL> select t.ts#,s.header_file,s.header_block 

  2   from v$tablespace t, dba_segments s 

  3   where s.segment_name='TT800' 

  4   and t.name=s.tablespace_name; 


[oracle@localhost ~]$ dbv userid=scott/tiger segment_id=6.5.1035


이  방법을  이용하면  큰  Tablespace에  들어있는  여러  가지  테이블  중  특정  테이블만  골라서  점검할  수  있으며

시간과  비용  면에서  훨씬  효율적입니다. 

이번에는  직접  백업  받은  파일의  블록을  corruption  하겠습니다. 

테스트  할  수  있는  데이터  파일로  백업  파일  중에  /data/temp/example01.dbf  를  사용하겠습니다. 


[oracle@localhost ~]$ dd   if=/dev/zero   of=/data/temp/example01.dbf   bs=8k 

(  명령  수행  도중에  CTRL + C  로  취소합니다  ) 

52356+0 records in 

52356+0 records out 

428900352 bytes (429 MB) copied, 5.09548 seconds, 84.2 MB/s 


[ 10g  일  경우  ] 

[oracle@localhost ~]$ dbv file=/data/temp/example01.dbf 

Page 1539 is marked corrupt 

Corrupt block relative dba: 0x00000603 (file 0, block 1539) 

Completely zero block found during dbv: 

Page 1540 is marked corrupt 

Corrupt block relative dba: 0x00000604 (file 0, block 1540) 

Completely zero block found during dbv: 

Page 1541 is marked corrupt 

Corrupt block relative dba: 0x00000605 (file 0, block 1541) 

Completely zero block found during dbv: 

(이하  생략합니다) 


[ 11g  일  경우  ] 

[oracle@localhost ~]$ dbv file=/data/temp2/example01.dbf 

DBVERIFY: Release 11.2.0.2.0 - Production on Mon Nov 25 21:05:42 2013 

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

DBV-00107: Unknown header format (0) (0) 


11g  일  경우는  에러가  발생합니다. 

반면  10g  일  경우는  위와  같이  Block Corruption  이  발생한  내역이  보입니다.

이  에러들을  수정하려면  정상적으로  백업  받은  백업  파일을  가지고  와서  복구를  해야  합니다.  

이렇게  블록  장애  난  파일을  복구  시도할  경우  아래와  같이  에러가  발생합니다.  


SQL> alter tablespace example offline; 

SQL> !cp /data/temp/example01.dbf   /home/oracle/oradata/testdb/ 

SQL> recover datafile '/home/oracle/oradata/testdb/example01.dbf'; 


역시  백업파일이  에러가  있어서  복구를  해도  복구가  되지  않습니다. 

이런  Corruption  된  블록을  복구하시려면  우선  정상적인  백업파일을  복원  하신  후 

Recover  명령을  수행하시거나  아니면  RMAN에서  Recover를  하시면  됩니다. 

위의  내용으로  알  수  있듯이  직접적인  물리적  손상을  입은  블록들은  DBVerify  로   검증을  할  수  있습니다. 


(3) Database  내  전체  데이터파일을  검사하는  dbv script 

서버  내에  아주  많은  데이터파일이  있을  경우  일일이  하나씩  전부  검사하는  일은  무척  번거롭고 힘든  일입니다.

그래서  자동으로  모든  파일의  위치를  찾아내서  DBV로  검사하는  스크립트를  소개합니다.

사용하시는  OS환경에  맞게  수정하시면  아주  편리하게  사용하실  수  있을  것입니다.


SQL> !vi dbv.sql 

set feedback off 

set   head off 

set echo off 

set linesize 200 

set pagesize 3000 

spool /home/oracle/dbv.sh 

select '!dbv file='||name||'   blocksize='||block_size||' logfile=' || 

       substr(name,instr(name,'/',-1,1) +1) ||'.'|| file#||'.log' 

from v$datafile 

spool off 

@/home/oracle/dbv.sh 

:wq! 

직접  실행해  보겠습니다. 

SQL> @/home/oracle/dbv.sql 

!dbv file=/home/oracle/oradata/testdb/system01.dbf   blocksize=8192 logfile=system01.dbf.1.log 

!dbv  file=/home/oracle/oradata/testdb/undotbs01.dbf  blocksize=8192 

logfile=undotbs01.dbf.2.log 

!dbv file=/home/oracle/oradata/testdb/sysaux01.dbf   blocksize=8192 logfile=sysaux01.dbf.3.log 

!dbv file=/home/oracle/oradata/testdb/users01.dbf   blocksize=8192 logfile=users01.dbf.4.log 

!dbv  file=/home/oracle/oradata/testdb/example01.dbf  blocksize=8192 

logfile=example01.dbf.5.log 

DBVERIFY: Release 10.2.0.5.0 - Production on Mon Feb 21 17:26:22 2011 

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

(검사  결과  나오는  이  부분이  logfile  로  지정한  부분에  저장됩니다) 

 All About Oracle Backup and Recovery -  서진수  저  

DBVERIFY: Release 10.2.0.5.0 - Production on Mon Feb 21 17:26:32 2011 

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

(검사  결과  나오는  이  부분이  logfile  로  지정한  부분에  저장됩니다) 

DBVERIFY: Release 10.2.0.5.0 - Production on Mon Feb 21 17:26:31 2011 

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

(검사  결과  나오는  이  부분이  logfile  로  지정한  부분에  저장됩니다) 

DBVERIFY: Release 10.2.0.5.0 - Production on Mon Feb 21 17:26:39 2011 

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

(검사  결과  나오는  이  부분이  logfile  로  지정한  부분에  저장됩니다) 

DBVERIFY: Release 10.2.0.5.0 - Production on Mon Feb 21 17:26:40 2011 

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

이제  로그파일을  열어서  확인하시면  됩니다. 

위  스크립트는  일반  파일  시스템을  사용할  경우인데  만약  데이터파일이  Raw Device

라면  스크립트가  조금  수정되어야  합니다. 


변경  전  : 

select '!dbv file='||name||'   blocksize='||block_size||' logfile=' || 

       substr(name,instr(name,'/',-1,1) +1) ||'.'|| file#||'.log' 

from v$datafile 


변경  후  :  아래  스크립트에서  굵은  글씨의  end  부분이  추가됩니다. 

select '!dbv file='||name||'   blocksize='||block_size|| ‘ end=’|| (bytes/block_size) 

        ||' logfile=' || substr(name,instr(name,'/',-1,1) +1)||'.'||file#||'.log' 

from v$datafile 


윈도  기반에서도  스크립트  조금  변경되어야  합니다. 


변경  전  : 

select '!dbv file='||name||'   blocksize='||block_size||' logfile=' || 

       substr(name,instr(name,'/',-1,1) +1) ||'.'|| file#||'.log' 

from v$datafile 

 All About Oracle Backup and Recovery -  서진수  저  


변경  후  :   아래  쪽에  /  대신  \  로  변경해주세요 

select '!dbv file='||name||'   blocksize='||block_size||' logfile=' || 

       substr(name,instr(name,'\',-1,1) +1) ||'.'||file#||'.log' 

from v$datafile 


만약  점검하고자  하는  파일이  ASM  기반이면  아래와  같이  변경되어야  합니다. 

select '!dbv file='||name||'   blocksize='||block_size||'   userid=sys/&passwd  logfile=' || 

       substr(name,instr(name,'/',-1,1) +1) ||'.'|| file#||'.log' 

from v$datafile 


기존  스크립트에서  userid  부분이  추가되어야  합니다. 

위  스크립트를  수행하면  아래와  같이  sys  의  암호를  묻게  되는데  적당한  암호를  입력하시면  DBV가  작동합니다. 

SQL> select '!dbv file='||name||'   blocksize='||block_size||'   userid=sys/&passwd   logfile=' || 

  2   substr(name,instr(name,'/',-1,1) +1) ||'.'||file#||'.log' 

  3   from v$datafile 

  4   ; 

Enter value for passwd: oracle     <-  이렇게  암호를  입력  받는  부분이  나옵니다. 

old    1: select '!dbv file='||name||'   blocksize='||block_size||'   userid=sys/&passwd   logfile=' || 

new    1: select '!dbv file='||name||'   blocksize='||block_size||'   userid=sys/oracle   logfile=' || 

(  지면  관계상  중간  결과는  생략합니다  ) 


이상으로  DBVerify  를  사용하여  데이터  파일과  백업파일의  무결성을  체크하는  방법을  살펴보았습니다. 

다음으로  DBMS_REPAIR  패키지를  이용하여  데이터파일과  백업파일을  검증하고  관리하는  방법을  살펴보겠습니다. 





2. DBMS_REPAIR  패키지를  이용한  Block Recovery 

DBMS_REPAIR  패키지는  오라클  8i  버전부터  등장한  Block Corruption  을 Detecting  하고  Repair 하는  패키지입니다.

이  패키지는  Table Block  과  Index Block  을  조사하여 문제가  있는  Block  을 수정해주는  data corruption repair  패키지를  가지고  있으며  

sys  계정으로  작업하셔야  합니다. 

즉  아래에서  설명하는  패키지들은  각각  수행  될  수  있다는  뜻이며  결과들이  저장되는  테이블에는 “DBA_”  라는  접두어가  붙어서  생성됩니다. 

DBMS_REPAIR  패키지는  corrupt block  를  Repair  하는  것이  아닙니다.

장애  난  블록을  찾아서  그  안에  있는  내용을  고쳐주는  패키지가  아니라는  것입니다.  

다만  이  패키지는  장애  난  블록을  찾아내서  해당  block  를  장애로  mark  하고  더  이상  사용 안하게  막아주고

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

그리고  만약  장애  난  블록에  데이터가  있었다면  그  블록  안에  있던  내용은  전부  손실됩니다.

아래의  실습들은  10g  기준이며  11g  와  차이가  거의  없습니다. 


2.1 DBMS_REPAIR   패키지 

 DBMS_REPAIR  패키지는  이름처럼  여러  개의  프로시저들이  모여있습니다. 

아래에서  해당  프로시저들의  역할과  사용법을  알아보겠습니다. 

(  각  프로시저  별로  옵션은  많지만  주로  사용하는  내용만  간략하게  살펴보겠습니다.) 


1) ADMIN_TABLE  프로시저 

Block Repair  를  하기  위해  필요한  관리  작업(create, drop, pur ge)을  제공해  줍니다.  

이런  작업을  하기  위한  테이블  들은  항상  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  들은  확인하지  않고  건너  뜁니다. 



2.2 DBMS_REPAIR  의  제약  사항  및  한계점 

1) LOB  나  Cluster Index  는  지원하지  않습니다. 

2) DUMP_ORPHAN_KEYS  프로시저는  BITMAP Index, Function-Based Index  는  지원하지  않으며, 3,950 bytes  이상은  지원하지  못합니다. 


2.3 DBMS_REPAIR  시작하기 

1) Block Corruption  찾아내기 

    이  과정과  관련  있는  패키지는  아래와  같습니다. 

    (1) CHECK_OBJECT 

    (2) FIX_CORRUPT_BLOCK 

    위  두  가지의  패키지를  사용하려면  먼저  ADMIN_TABLE  이  실행되어야  합니다. 


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

SQL> conn / as sysdba; 

Connected. 

SQL> 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. 

SQL> desc repair_table;   (  또는  dba_repair_table  하셔도  됩니다) 


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

이  테이블은  장애  난  테이블과  관련  있는  다른  Object  를  저장하는  곳입니다. 

예를  들어서  관련  인덱스나  FK  등의  정보를  저장하는  곳이라고  생각하시면  됩니다.  

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


SQL> 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; 

PL/SQL procedure successfully completed. 


SQL> desc orphan_key_table; 


4) DB_Block_checking = true 

블록이  문제가  있는지  없는지를  확인하려면  오라클  파라미터  중에서  Block checking  하는  파라미터를  true  값으로  변경해주어야  합니다.

파라미터  파일에  DB_BLOCL_CHECKING = true  로  해  줄  경우  오라클은  모든  블록을  체크하기 시작합니다.

당연히  어느  정도의  Overhead  는  감수해야  할  것입니다. 

이  값을  False  로  하게  되면  SYSTEM Tablespace  만  체크하고  나머지는  체크 안  합니다. 

여기까지가  블록  장애를  검사하기  전  준비  단계이고  이제  Block Corruption  을 발생시켜  복구해  보겠습니다. 


5) DBMS_REPAIR  실습하기 

Step 1.  위  파라미터를  설정  한  후  재  시작  합니다. (또는  alter system set  으로  적용시킵니다) 


SQL> show parameter db_block_checking; 

SQL> alter system set db_block_checking=true; 

SQL> show parameter db_block_checking; 


Step 2.   Block Corruption  발생시킵니다. 

SQL> !vi dd.sql 

conn / as sysdba 

set line 200 

col tablespace_name for a10 

col file_name for a50 

col mb for 9999 

select tablespace_name , bytes/1024/1024 MB , file_name 

from dba_data_files 

:wq! 


SQL> @dd 


SQL> create tablespace test10 

  2   datafile   '/home/oracle/oradata/testdb/test01. dbf'   size   256k; 


SQL> @dd 


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

SQL> insert into scott.tt910 values (1, ’AA’); 

SQL> insert into scott.tt910 values (2, ’BB’); 

SQL> commit; 

SQL> select * from scott.tt910; 

SQL> alter tablespace test10 offline; 


여기까지  하신  후  해당  데이터  파일을  윈도로  이동시키신  후  (Winscp  등  이용)  

윈도에서 에디터를  통해서  블록을  잘  수정하셔서  Block Corruption  을  만드세요.  

이  부분을 잘  하셔야  합니다. 

Block corruption  을  만드신  후에  저장하시고  다시  리눅스로  이동  시키신 후  아래와 같이 하세요. 


SQL> recover tablespace test10; 

SQL> alter tablespace test10 online; 

Tablespace altered. <- Tablespace  는  정상적으로  recover  되었습니다. 

SQL> select   *   from   scott.tt910; 

select * from scott.tt910 

ERROR at line 1: 

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

ORA-01110: data file 6: '/home/oracle/oradata/testdb/test01.dbf' <-  장애  발생했습니다. 


Step 3. DBMS_REPAIR  을  사용하여  에러를  찾습니다. 

SQL> set serveroutput on; 

SQL> declare n_corrupt int; 

  2   begin 

  3     n_corrupt := 0; 

  4     dbms_repair.check_object ( 

  5     schema_name => 'SCOTT', 

  6     object_name => 'TT910', 

  7     repair_table_name => 'REPAIR_TABLE', 

  8     corrupt_count => n_corrupt) ; 

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

 10   end; 

 11   / 

장애블록수: 1     이렇게  장애  블록을  찾았습니다. 

PL/SQL procedure successfully completed. 


장애  블록에  대한  조금  더  자세한  정보를  알아보겠습니다. 

SQL> set line 200; 

SQL> col object_name for a10 

SQL> col corrupt_description for a20 

SQL> col repair_description for a20 

SQL> select object_name,block_id, corrupt_type,marked_corrupt, 

  2          corrupt_description,repair_description 

  3    from repair_table 


위  내용과  같이  12번  블록이  문제가  있다는  것이  확인되며  corrupt  되었다고  mark  되었다는  것도  알  수  있습니다. 


Step 4. Corrupt  된  블록을  Fix  하겠습니다.  

이  부분은  corrupt  된  블록을  찾아서  corrupt  되었다고  marking  하는  부분인데  check_object  부분에서  자동으로  해서  안  하셔도  상관없습니다. 


SQL> set serveroutput on 

SQL> declare n_fix int; 

  2   begin 

  3     n_fix := 0; 

  4     dbms_repair.fix_corrupt_blocks ( 

  5     schema_name => 'SCOTT', 

  6     object_name => 'TT910' , 

  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 <- check_object  부분에서  해서  여기서는  0으로  나옵니다.

PL/SQL procedure successfully completed. 


Fix  를  한다는  것은  해당  블록에  corruption  이  발생해서  사용  못하니까  더  이상  읽지도  쓰지도 말라는  표시를  한다는  (Mark  한다는)  뜻  입니다.  

즉  블록  안에  있는  데이터를  복구한다는 뜻이 아니라  해당  블록을  못쓴다고  표시만  해  둔다는  뜻입니다. 

Fix  를  하고  난  후에  해당  테이블에  select  를  해  보겠습니다. 


SQL> select * from scott.tt910; 

select * from scott.tt910 

ERROR at line 1: 

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

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


여전히  해당  블록에  문제가  있다고  나오고  select  가  정상적으로  수행이  안됩니다. 

예를  들어  위  데이터  파일에  수많은  블록에  데이터가  들어  있다고  가정할  경우  1개의  block  가 

corrupt  가  발생할  경우  전체  데이터를  읽어  오지  못하는  상황이  된다는  뜻입니다. 

그래서  corrupt  된  블록의  데이터는  복구  못하니까  읽지  말고  나머지  블록만  읽어서  남아 있는 

데이터만이라도  살려내고  싶을  때  아래와  같이  한가지  작업을  더  하시면  됩니다. 


Step 5. Corrupt  된  block  를  Skip  하도록  설정하겠습니다. 

SQL> begin 

  2    dbms_repair.skip_corrupt_blocks ( 

  3    schema_name => 'SCOTT', 

  4    object_name =>   'TT910', 

  5    object_type => dbms_repair.table_object, 

  6    flags => dbms_repair.skip_flag) ; 

  7   end; 

  8   / 

PL/SQL procedure successfully completed. 

이제  다시  해당  테이블에  select  해  보겠습니다. 


SQL> select * from scott.tt910; 

no rows selected 


정상적으로  select  되는  것을  알  수  있습니다. 

어떤  테이블에  corrupt  된  블록을  skip  하도록  설정이  되어  있는지는  아래의  쿼리를  수행하시면 조회  할  수  있습니다. 


SQL> select owner, table_name, skip_corrupt 

  2   from dba_tables 

  3   where owner='SCOTT'; 



2.4 DBMS_REPAIR  패키지  활용  실습 

이번  실습은  데이터가  10만  건  들어있는  scott.tt920  테이블을  생성  한  후  index  도  생성합니다. 

그  후에  data block  과  index block  에  corrupt를  발생  시켜  조회가  되지  않는  장애를  만들고 

DBMS_REPAIR을  이용하여  Fix  하고  Skip  하여  데이터가  조회  되도록  하겠습니다.


Step 1.  테스트  환경  만들기 

SQL> @dd 

SQL> alter database datafile '/home/oracle/oradata/testdb/test01.dbf' autoextend on; 

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

SQL> begin 

  2   for i in 1..100000 loop 

  3     insert into scott.tt920 

  4     values (i,dbms_random.string('A',9)); 

  5   end loop; 

  6   commit; 

  7   end; 

8   / 


SQL> select count(*) from scott.tt920; 

SQL> analyze table scott.tt920 compute statistics; 

SQL> col table_name for a10 

SQL> col owner for a10 

SQL> select table_name , owner , num_rows , blocks 

  2   from dba_tables 

  3   where table_name='TT920'; 


위  내용을  보면  scott.tt920  이란  테이블이  총  10만건의  데이터가  있고  370  개의 block를 사용하는  것을  알  수  있습니다. 

Scott.tt920  테이블의  이름  컬럼에  인덱스를  생성하겠습니다. 


SQL> create   tablespace indx 

  2   datafile '/home/oracle/oradata/testdb/indx01.d bf' size 5M 

  3   autoextend on; 


SQL> create index scott.indx_tt920_name on scott.tt920(name) tablespace indx; 

Index created. 

SQL> set line 200 

SQL> col owner for a10 

SQL> col index_name for a30 

SQL> col table_name for a10 

SQL> select owner , index_name , table_name , num_rows , leaf_blocks 

  2   from dba_indexes 

  3   where table_name='TT920'; 


위  내용을  보면  인덱스  역시  10만건의  데이터가  들어가  있고  leaf block  수가  294 개  임을  알  수 있습니다. 

Step 2. tt920 table  이  저장된  데이터파일에  block corruption  을 발생시킵니다. 

현재  tt920  테이블이  저장된  데이터  파일을  윈도로  이동시켜서  block corruption을  발생  시킨  후 다시  리눅스로  이동시킵니다. 

그리고  아래와  같은  작업을  합니다. 


SQL> alter tablespace test10 offline; 

SQL> alter tablespace test10 online; 

alter tablespace test10 online 

ERROR at line 1: 

ORA-01113: file 6 needs media recovery if it was restored from backup, or END BACKUP if it was 

not 

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

SQL> recover tablespace test10; 

Media recovery complete. 

SQL> alter tablespace test10 online; 

Tablespace altered. 


SQL> select * from scott.tt920 ; 

(중간  생략) 

NO    NAME 

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

   2671    baBvNSwET 

   2672    DUowpdecd 

   2673    faTxAykzk 

   2674    UOQhNSWGe 

   2675    GVELPvwCF 

   2676    QDSyJgthY 

   2677    MLZlPcjdR 

ERROR: 

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

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

2295 rows selected. 


Select  가  수행되다가  corrupt  난  블록에서  장애가  발생하고  이후의  데이터는  조회가 안됩니다. 



Step 3. DBMS_REPAIR  패키지로  corrupt  된  블록을  찾습니다. 

작업을  하기  전에  먼저  repair_table  을  초기화합니다. 

SQL> select count(*) from repair_table; 

  COUNT(*) 

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

         2 <-  앞에서  테스트했던  2건의  데이터가  있습니다. 

SQL> truncate table repair_table; 

Table truncated. 

SQL> select count(*) from repair_table; 

  COUNT(*) 

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

         0 

SQL> set serveroutput on ; 

SQL> declare num_corrupt int; 

  2   begin 

  3     num_corrupt := 0; 

  4     dbms_repair.check_object ( 

  5     schema_name => 'SCOTT' , 

  6     object_name => 'TT920' , 

  7     repair_table_name => 'REPAIR_TABLE' , 

  8     corrupt_count => num_corrupt ); 

  9     dbms_output.put_line('====================== ========='); 

 10     dbms_output.put_line('장애블록수: '||to_char(num_corrupt)) ; 

 11   end; 

 12  

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

장애블록수: 5 

PL/SQL procedure successfully completed. 


위  결과로  확인한  결과  5개의  블록이  장애가  났음을  알  수  있습니다. 

어떤  블록이  장애가  났는지  자세히  살펴보겠습니다. 


SQL> set pagesize 50 

SQL>   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_CORRUPTCORRUPT_DESCRIPTION    REPAIR_DESCRIPTION 

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

TT920               26                6148    TRUE                                    mark block software 

                                  corrupt 

TT920              391                6148    TRUE                                    mark block software 

                                  corrupt 

TT920              474                6148    TRUE                                    mark block software 

                                  corrupt 

TT920              484                6148    TRUE                                    mark block software 

                                   corrupt 

TT920              493               6148     TRUE                                     mark block software

                                   Corrupt 

위  내용을  살펴보니  26, 391, 474, 484, 493  번  블록에서  장애가  발생했고  fix까지  되어  있음이 확인됩니다. 



Step 4.  관련된  인덱스  블록의  상태는  어떠한지  조회해  보겠습니다. 

SQL> declare num_index int; 

  2   begin 

  3     num_index := 0; 

  4     dbms_repair.dump_orphan_keys ( 

  5     schema_name => 'SCOTT' , 

  6     object_name => 'INDX_TT920_NAME' , 

  7     object_type => dbms_repair.index_object , 

  8     repair_table_name => 'REPAIR_TABLE' , 

  9     orphan_table_name => 'ORPHAN_KEY_TABLE' , 

 10     key_count => num_index ); 

 11     dbms_output.put_line('========================================'); 

 12     dbms_output.put_line(' index key count : '||to_char(num_index)); 

 13   end; 

14   / 

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

index key count : 1834 

PL/SQL procedure successfully completed. 


위  조회  내용을  보면  1834  건의  인덱스  key  에  문제가  발생했음을  알  수  있습니다. 



Step 5. Corrupt  된  블록을  찾지  않도록  skip  설정하겠습니다. 

현재  이  테이블에  총  10만  건의  데이터가  들어  있습니다.  

그러나  지금은  5개의  블록이  장애가  나서  전체가  조회가  안되고  중지되는  일이  발생했습니다.  

그래서  위  방법으로  corrupt  된 블록을 찾은  후  지금  하는  방법으로  해당  5개의  블록은  더  이상  사용하지  않도록  skip  설정  한  후  

나머지  데이터라도  살려내겠습니다. 

현재  상태  (corrupt block  찾고  fix까지  한  상태)로  조회를  먼저  해  보겠습니다. 


SQL> select count(*) from scott.tt920; 

select count(*) from scott.tt920 

                           * 

ERROR at line 1: 

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

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


여전히  corrupt  된  block  때문에  조회가  정상적으로  안  되고  있습니다. 

Corrupt  된  block  을  skip  하도록  설정하겠습니다. 


SQL> begin 

  2     dbms_repair.skip_corrupt_blocks ( 

  3     schema_name => 'SCOTT' , 

  4     object_name => 'TT920' , 

  5     object_type => dbms_repair.table_object , 

  6     flags => dbms_repair.skip_flag); 

  7   end; 

8   / 

PL/SQL procedure successfully completed. 


SQL> select count(*) from scott.tt920; 

  COUNT(*) 

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

     98166    <-  조회가  진행  됩니다. 


위  조회  내용으로  봤을  때  전체  데이터  10만  건  중에서  현재  조회되는  98166  개  외에는 전부  장애가  발생했음을  알  수  있습니다. 

테이블이  정리되었으므로  인덱스도  rebuild  하겠습니다. 


현재  orphan key table  을  조회해보겠습니다. 


SQL> select count(*) from orphan_key_table; 

  COUNT(*) 

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

      1834 


SQL> truncate table orphan_key_table; 

Table truncated. 


SQL> select count(*) from orphan_key_table; 

  COUNT(*) 

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

         0 


SQL> declare num_index int; 

  2   begin 

  3     num_index := 0; 

  4     dbms_repair.dump_orphan_keys ( 

  5     schema_name => 'SCOTT' , 

  6     object_name => 'INDX_TT920_NAME' , 

  7     object_type => dbms_repair.index_object , 

  8     repair_table_name => 'REPAIR_TABLE' , 

  9     orphan_table_name => 'ORPHAN_KEY_TABLE' , 

 10     key_count => num_index ); 

 11     dbms_output.put_line('========================================'); 

 12     dbms_output.put_line('index key count: '||to_char(num_index)); 

 13   end ; 

14    / 

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

index key count: 0   <-  인덱스가  rebuild  되었습니다. 

PL/SQL procedure successfully completed. 


위  작업  내용  결과  tt920  테이블에서  corrupt  된  블록을  skip  하고  난  후  index  도  해당  블록을 더  이상  사용  안  하는  것을  알  수  있습니다. 

여기까지  DBMS_REPAIR  패키지를  사용해서  corrupt  된  block  가  있는  테이블을  어떻게  조치하는지를  살펴  보았습니다.  

다소  내용이  복잡  한  것  같지만  긴급한  장애가  발생했을  때  아주  요긴한  방법이  되므로  꼭  이해하시고  연습하시길  바랍니다. 




3. BBED  를  이용한  Block Recovery 

지금부터  설명  드리는  부분은  아주  위험한  방법임을  미리  알려드립니다. 

아울러  지금부터  설명  드리는  방법을  잘  못  사용할  경우  해당  데이터파일의  모든  데이터가  손상될  수  있으며  아예  복구를  하지  못할  수도  있습니다. 

그에  대한  모든  책임은  작업을  수행하신  여러분들께  있다는  것을  미리  알려드립니다. 


반드시  모든  기능을  숙지하신  후에도  실무에서  반드시  필요한  경우를  제외하고는  절대로  사용  하지  마시길  당부  드립니다.

무서운  이야기를  먼저  하는  이유는  저자  조차도  이  방법을  이용할  때 아주  조심스럽기  때문입니다.  


지금부터  오라클  블록  복구에  대한  저자만의  필살기를  전해드립니다.  

BBed  란  Block Browser and Editor  의  약자로  이름처럼  Block  을  탐색하고  수정하는  유틸리티입니다.

Oracle  버전에  따라  조금은  다르지만  기본적으로  라이브러리  파일이  설치되며  사용하기 위해서는  Linking  작업을  추가로  해  주어야  합니다.

 

여기서는  우선  BBed  의  개념과  기본적인  사용법을  익힌  후  뒷부분에서  BBed  를  어떻게  사용하는지  실제  예제를  들어서  살펴보겠습니다. 


다시  한번  더  강조하지만  이  방법은  Oracle  사에서  보증하거나  고쳐주지  않기  때문에  정말 조심하시고  주의해서  사용하시기  바랍니다.  

연습  많이  하세요!!!! 


1) BBed Link  후  실행하기  –  리눅스  버전  기반 

오라클  엔진을  설치하게  되면  BBed  의  기본적인  라이브러리들이  함께  설치가  됩니다. 

그러나  사용가능  상태가  아니기  때문에  이것을  사용하려면  link  라는  작업을  별도로  해주셔야 합니다.  

10g  까지는  아래  방법으로  하시면  됩니다. 


[oracle@localhost ~]$ cd $ORACLE_HOME/rdbms/lib 

[oracle@localhost lib]$ make -f ins_rdbms.mk $ORACLE_HOME/rdbms/lib/bbed 

(Linking  이  진행  됩니다) 

[oracle@localhost lib]$ pwd 

/home/oracle/product/10g/rdbms/lib 

[oracle@localhost lib]$ ls -l bbed 

-rwxr-xr-x   1 oracle dba 552665   2월  22 12:56 bbed    <-  파일이  생성됩니다. 

[oracle@localhost lib]$ cp bbed   $ORACLE_HOME/bin/ 

11g부터는  아래  방법으로  하시면  됩니다. 

[oracle@localhost lib]$ cd $ORACLE_HOME/rdbms/lib 

[oracle@localhost lib]$ make -f ins_rdbms.m k $ORACLE_HOME/rdbms/lib/bbed 

(위  생략) 


gcc: /app/oracle/product/11g/rdbms/lib/ssbbded.o:  그런  파일이나  디렉토리가  없음 

gcc: /app/oracle/product/11g/rdbms/lib/sbbdpt.o:  그런 파일이나  디렉토리가  없음 

make: *** [/app/oracle/product/11g/rdbms/lib/bbed]  오류  1 

에러가  발생합니다. 

그  이유는  11g  에서는  기본적인  라이브러리  파일이  없기  때문입니다. 

그래서  9i/10g  에  있는  위  라이브러리  파일을  복사해  와서  사용해야  합니다.  

경로는  9i/10g  와  11g  가  동일합니다. 

아래의  파일들을  9/10g  의  경로에서  11g  의  동일한  경로로  복사하세요. 


[ 10g  에서  복사해야  할  파일들  ] 

$ORACLE_HOME/rdbms/lib/ssbbded.o 

$ORACLE_HOME/rdbms/lib/sbbdpt.o 

$ORACLE_HOME/rdbms/mesg/bbedus.msb 

$ORACLE_HOME/rdbms/mesg/bbedus.msg 


-  아래  작업은  11g  에서  하며  10g  서버의  ip  주소가  192.168.47.133  으로 가정합니다. 

[oracle@localhost ~]$ cd $ORACLE_HOME/rdbms/lib 

[oracle@localhost lib]$ ls ssbbded.o 

ls: ssbbded.o:  그런  파일이나  디렉토리가  없음 

[oracle@localhost lib]$ ls sbbdpt.o 

ls: sbbdpt.o:  그런  파일이나  디렉토리가  없음 

[oracle@localhost lib]$ ls ../mesg/bbedus* 

ls: ../mesg/bbedus*:  그런  파일이나  디렉토리가  없음 

[oracle@localhost lib]$ pwd 

/app/oracle/product/11g/rdbms/lib 

[oracle@localhost lib]$ scp 192.168.47.133:/home/oracle/product/10g/rdbms/lib/ssbbded.o   . 

oracle@192.168.47.133's password:   oracle  암호  입력

ssbbded.o                                             100% 2 657      2.6KB/s    00:00 

[oracle@localhost lib]$ scp 192.168.47.133:/home/oracle/product/10g/rdbms/lib/sbbdpt.o   . 

oracle@192.168.47.133's password:   oracle  암호  입력

sbbdpt.o                                               100% 2979      2.9KB/s    00:00 

[oracle@localhost lib]$ pwd 

/app/oracle/product/11g/rdbms/lib 

[oracle@localhost lib]$ cd ../mesg 

[oracle@localhost mesg]$ scp 192.168.47.133:/home/oracle/product/10g/rdbms/mesg/bbedus.msb   . 

oracle@192.168.47.133's password:   oracle  암호  입력

bbedus.msb                                             100% 8 704      8.5KB/s    00:00 

[oracle@localhost mesg]$ scp 192.168.47.133:/home/oracle/product/10g/rdbms/mesg/bbedus.msg   .

oracle@192.168.47.133's password:    oracle  암호  입력

bbedus.msg                                             100%    10KB   10.0KB/s    00:00 

[oracle@localhost lib]$ make -f $ORACLE_HOME/rdbms/lib/ins_rdbms.mk BBED=$ORACLE_HOME/bin/bbed    

                     $ORACLE_HOME/bin/bbed 

(지면  관계상  Linking  이  수행되는  과정은  생략합니다) 

Linking  이  끝났으면  아래와  같이  실행합니다  (모든  버전  동일합니다) 

[oracle@localhost lib]$ bbed 

Password: blockedit   <--  기본  암호입니다. 

BBED: Release 2.0.0.0.0 - Limited Production on TueNov 26 00:49:23 2013 

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

************* !!! For Oracle Internal Use only !!! *************** 

BBED>exit 


2) BBed  주요  옵션들 

BLOCKSIZE  편집할  데이터  파일의  블록사이즈를  적어줍니다 

MODE  BBed  를  실행할  모드를  설정합니다(browser or edit) 

SILENT  작업결과를  표준  출력(모니터)로  보여주는  여부를  제어합니다(Y, N) 

SPOOL  BBed  작업  log  를  bbed.log  파일에  저장할  것인지를  제어합니다(Y, N) 

LISTFILE  작업할  파일의  목록을  적어줍니다 

CMDFILE  실행할  파일들의  목록을  적어줍니다 

BIFILE  변경  전  파일의  이미지를  저장할  파일명을  적어줍니다. (기본값-Bifile.bbd )  

LOGFILE  User log  를  저장할  파일명을  지정합니다. (  기본값-log.bbd) 

PARFILE  Bbed  를  실행할  때  사용할  파라미터등을  적어두는  파일명을  지정합니다 


위  옵션을  사용해서  bbed  구동  환경  설정하는  방법입니다. 

SYS>select file#||'   '||name||'   '||bytes   from   v$datafile ; 

FILE#||''||NAME||''||BYTES 

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

1   /app/oracle/oradata/testdb/system01.dbf   754974720 

2   /app/oracle/oradata/testdb/sysaux01.dbf   681574400 

3   /app/oracle/oradata/testdb/undotbs01.dbf   10485760 

4   /app/oracle/oradata/testdb/users01.dbf   10485760

5   /app/oracle/oradata/testdb/example01.dbf   362414080 

위  내용을  listfile  을  만들어서  거기에  등록하고  listfile  옵션을  사용해서  bbed  를  실행하겠습니다. 

즉  listfile  이란  bbed  가  작업할  대상파일들의  명단입니다.  아래와  같이  만들면  됩니다. 


SYS>! 

[oracle@localhost ~]$ vi target.log 

1   /app/oracle/oradata/testdb/system01.dbf   754974720 

2   /app/oracle/oradata/testdb/sysaux01.dbf   681574400 

3   /app/oracle/oradata/testdb/undotbs01.dbf   10485760 

4   /app/oracle/oradata/testdb/users01.dbf   10485760

5   /app/oracle/oradata/testdb/example01.dbf   362414080 

:wq! 

[oracle@localhost ~]$ vi bbed.par 

blocksize=8192 

listfile=/home/oracle/target.log 

mode=edit 

:wq! 

[oracle@localhost ~]$ bbed parfile=bbed.par 

Password: blockedit 

BBED: Release 2.0.0.0.0 - Limited Production on TueNov 26 01:07:17 2013 

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

************* !!! For Oracle Internal Use only !!! *************** 

BBED> 


3) BBed  명령어들 


(1) help all 

 BBed  관련  도움말을  보여줍니다. 

BBED> help all 

SET DBA [ dba | file#, block# ] 

SET FILENAME 'filename' 

SET FILE file# 

SET BLOCK [+/-]block# 

SET OFFSET [ [+/-]byte offset | symbol | *symbol ] 

SET BLOCKSIZE bytes 

SET LIST[FILE] 'filename' 

SET WIDTH character_count 

SET COUNT bytes_to_display 

SET IBASE [ HEX | OCT | DEC ] 

SET OBASE [ HEX | OCT | DEC ] 

SET MODE   [ BROWSE | EDIT ] 

SET SPOOL [ Y | N ] 

SHOW [ <SET parameter> | ALL ] 

INFO 

MAP[/v] [ DBA | FILENAME | FILE | BLOCK ] 

DUMP[/v] [ DBA | FILENAME | FILE | BLOCK | OFFSET |COUNT ] 

PRINT[/x|d|u|o|c] [ DBA | FILE | FILENAME | BLOCK |OFFSET | symbol | *symbol ] 

EXAMINE[/Nuf] [ DBA | FILE | FILENAME | BLOCK | OFFSET | symbol | *symbol ] 

</Nuf>: 

  N - a number which specifies a repeat count. 

  u - a letter which specifies a unit size: 

  b - b1, ub1 (byte) 

  h - b2, ub2 (half-word) 

  w - b4, ub4(word) 

  r - Oracle table/index row 

  f - a letter which specifies a display format: 

  x - hexadecimal 

  d - decimal 

  u - unsigned decimal 

  o - octal 

  c - character (native) 

  n - Oracle number 

  t - Oracle date 

  i - Oracle rowid 


FIND[/x|d|u|o|c] numeric/character string [ TOP | CURR ] 

COPY [ DBA | FILE | FILENAME | BLOCK ] TO [ DBA | FILE | FILENAME | BLOCK ] 

MODIFY[/x|d|u|o|c] numeric/character string 

      [ DBA | FILE | FILENAME | BLOCK | OFFSET | sy mbol | *symbol ] 

ASSIGN[/x|d|u|o] <target spec>=<source spec> 

<target spec> : [ DBA | FILE | FILENAME | BLOCK | OFFSET | symbol | *symbol ] 

<source spec> : [ value | <target spec options> ] 

SUM [ DBA | FILE | FILENAME | BLOCK ] [ APPLY ] 

PUSH [ DBA | FILE | FILENAME | BLOCK | OFFSET ] 

POP [ALL] 

REVERT [ DBA | FILE | FILENAME | BLOCK ] 

UNDO 

HELP [ <bbed command> | ALL ] 

VERIFY [ DBA | FILE | FILENAME | BLOCK ] 

CORRUPT [ DBA | FILE | FILENAME | BLOCK ] 


명령어들과  옵션들이  많은  것을  확인  할  수  있습니다. 


(2) set dba 

작업하고자  하는  데이터파일과  블록을  지정합니다.  여기에  지정될  데이터파일은  listfile  에  등록되어  있어야  합니다. 

BBED> set dba 2,50   

        DBA              0x00800032 (8388658 2,50) 

위  명령은  2번  파일의  50번  블록에  작업을  하겠다  라고  설정하는  것입니다. 


(3) set filename 

작업을  원하는  데이터파일을  이름으로  지정합니다. 

BBED> set   filename   '/app/oracle/oradata/testdb/example01.dbf' 

        FILENAME         /home/oracle/oradata/testdb /example01.dbf 


(4) set file 

작업을  원하는  데이터파일을  번호로  지정합니다.  

BBED> set file 3; 

        FILE#            3 


(5) set block 

현재  설정되어  있는  파일에서  작업을  원하는  block  을  지정합니다. 

BBED> set block 20 

        BLOCK#           20 


(6) set offset 

현재  작업하기  원하는  offset  번호를  지정합니다. 


(7) set blocksize 

현재  작업하는  파일의  blocksize  를  지정합니다. 

BBED> set blocksize 8192 

        BLOCKSIZE        8192 


(8) set listfile 

작업을  수행할  파일의  목록이  적혀있는  list file  을  지정합니다. 

BBED> set listfile '/home/oracle/filelist.log' 

        LISTFILE         /home/oracle/filelist.log 


(9) set width 

현재  보이는  화면의  폭을  지정합니다. 

BBED> set width 200 

        WIDTH            200 


(10) set count 

Dump  명령어  수행  시  화면에  보여줄  data block  의  byte  수를  지정합니다. 

BBED> set count 100 

        COUNT            100 


(11) set ibase 

내부적으로  사용되는  값들의  표현식을  지정합니다.  기본값은  10진수인데  16진수( Hexadecimal)나  

8진수(Octal)로  변경  가능합니다. 


(12) set mode 

Bbed  수행  mode  를  설정합니다. 


(13) show 

현재  설정되어  있는  내용들을  보여줍니다. 

BBED> show 

        FILE#              1 

        BLOCK#           1 

        OFFSET           0 

        DBA              0x00400001 (4194305 1,1) 

        FILENAME         /app/oracle/oradata/testdb/ system01.dbf 

        BIFILE             bifile.bbd 

        LISTFILE           /home/oracle/target.log 

        BLOCKSIZE        8192 

        MODE             Edit 

        EDIT              Unrecoverable 

        IBASE             Dec 

        OBASE            Dec 

        WIDTH            200 

        COUNT            100 

        LOGFILE           log.bbd 

        SPOOL            No 


(14) info 

현재  작업중인  파일  내용을  보여줍니다. 


BBED> info 

 File#   Name                                                         Size(blks) 

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

     1   /app/oracle/oradata/testdb/system01.dbf                           92160 

     2   /app/oracle/oradata/testdb/sysaux01.dbf                           83200 

     3   /app/oracle/oradata/testdb/undotbs01.dbf                           1280 

     4   /app/oracle/oradata/testdb/users01.dbf                             1280 

     5   /app/oracle/oradata/testdb/example01.dbf                          44240 


(15) map 

현재  작업중인  블록에  대한  자세한  정보를  보여줍니다. 

BBED> map /v dba 1,20 

 File: /home/oracle/oradata/testdb/system01.dbf (1)

 Block: 20                                     Dba:0x00400014 

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

 Undo Data 


 struct kcbh, 20 bytes                         @0 

    ub1 type_kcbh                            @0 

    ub1 frmt_kcbh                            @1 

    ub1 spare1_kcbh                          @2 

    ub1 spare2_kcbh                          @3 

    ub4 rdba_kcbh                            @4 

    ub4 bas_kcbh                             @8 

    ub2 wrp_kcbh                             @12 

    ub1 seq_kcbh                             @14 

    ub1 flg_kcbh                              @15 

    ub2 chkval_kcbh                           @16 

    ub2 spare3_kcbh                           @18 

ub1 freespace[212]                             @100 

 ub1 undodata[7876]                           @312 

 ub4 tailchk                                    @8188 


위에서  map  명령어로  나오는  정보들에  대해서  자세히  살펴보겠습니다. 


struct kcbh, 20 bytes  Block header  라는  뜻입니다 

ub1 type_kcbh  Block type  을  정의합니다.  아래  표  참조하세요 

ub1 frmt_kcbh  Block Format  을  지정합니다. 

ub1 spare1_kcbh  사용  안  합니다 

ub1 spare2_kcbh  사용  안  합니다 

ub4 rdba_kcbh  RDBA (Relative Data Block Address) 

ub4 bas_kcbh  Scn base 

ub2 wrp_kcbh  Scn Wrap 

ub1 seq_kcbh  Sequence Number, Block Sequence Number

ub1 flg_kcbh  Flag 

0x01 : new block 

0x02 : delayed logging change advanced SCN/seq 

0x04: check value saved – block xors’s to zero 

0x08: Temporary Block 

ub2 chkval_kcbh  Db_block_checksum=true  로  설정할  경우  checksum  값  저장 

ub2 spare3_kcbh  사용  안  합니다 

ub1 freespace[212]   freespace 

ub1 undodata[7876]  Undo data 

ub4 tailchk  아래부분에  tailcheck  내용을  참고하세요 


위에서  살펴본  부분  말고도  블록의  종류에  따라  여러  가지  내용이  더  많을  수  있습니다. 

ub1 type_kcbh  에서  언급한  블록  헤더  타입을  살펴  보겠습니다. 


항   목  설   명 

01  Undo segment header 

02  Undo data block 

03  Save undo header 

04  Save undo block 

05  Data segment header(temp, index, data  등) 

06  ITL로  관리되는  data block 

07  ITL로  관리되지  않는  Temp data block 

08  Sort key 

09  Sort run 

10  Free list block 

11  Data file header 


ub4 tailchk  에서  언급한  tailcheck  를  확인하겠습니다. 


일반적으로  블록주소는  SCN Base  값과  Block type , SCN Sequence number로  구성이  되어  있습니다. 

예를  들어  SCN Base  값이  0x00029728  이고  block type  이  06  번  이며, 

SCN Sequence Number  가  0x02  라면  tail check  부분은  0x97280602  가  되는 것입니다.  

이  값을  4 bytes  로  저장하게  됩니다. 


(16) (d)ump 

Block  의  내용을  실제  dump  해서  화면에  보여주는  명령입니다.  보다  자세한  내용을  알기  위해 /v  옵션을  함께  사용하는  경우가  많습니다.  

이  명령으로  DBA , filename, file, block, offset  등  set  명령어로  설정된  값들을  다  조회할  수  있습니다. 


아래의  예는  1번  파일의  10번  블록을  offset 1-127  번까지  dump  를  수행한  내용입니다. 


BBED> set width 100 

        WIDTH            100 

BBED> dump /v dba 1,10 offset 0 count 128 

 File: /app/oracle/oradata/testdb/system01.dbf (1) 

 Block: 10       Offsets:     0 to   127   Dba:0x0040000a 

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

 02a20000 0a004000 5a391100 00000104 l ......@.Z9...... 

 7d950000 00003f00 36000000 48001c1c l }.....?.6...H... 

 0000e81f d41ec01d ac1c981b 841a7019 l ..............p. 

 5c184817 34162015 0c14f812 e411d010 l \.H.4. ......... 

 bc0fa80e 940d800c 6c0b580a 44093008 l ........l.X.D.0. 

 1c070806 f404e003 cc02b801 00000000 l ................ 

 00000900 2f000000 a0014000 41000400 l ..../.....@.A... 

 01000000 00000000 00002a00 2f000000 l ..........*./... 

 <16 bytes per line> 


(17) (P)rint 

현재  작업중인  정보를  보여줍니다. 

BBED> p 

kcbh.type_kcbh 

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

ub1 type_kcbh                                @0         0x02 

BBED> p   kcbh 

struct kcbh, 20 bytes                          @0 

   ub1 type_kcbh                             @0         0x02 

   ub1 frmt_kcbh                             @1         0xa2 

   ub1 spare1_kcbh                           @2         0x00 

   ub1 spare2_kcbh                           @3         0x00 

   ub4 rdba_kcbh                             @4         0x00400010 

   ub4 bas_kcbh                              @8         0x0013c412 

   ub2 wrp_kcbh                              @12        0x0000 

   ub1 seq_kcbh                              @14        0x01 

   ub1 flg_kcbh                              @15        0x04 (KCBHFCKV) 

   ub2 chkval_kcbh                           @16        0x5d1a 

   ub2 spare3_kcbh                           @18        0x0000 


(18) e(x)amine 

이  명령어는  DBA, Filename, File, Block, Offfset  등의  값을  정해진  포맷형식으로  보여줍니다. 

BBED> x 

kcvfh.kcvfhbfh.type_kcbh                     @0 

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

 0x0b 

BBED> x   /b 

kcvfh.kcvfhbfh.type_kcbh                     @0 

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

 0x0b 

BBED> x   /h 

kcvfh.kcvfhbfh.type_kcbh                     @0 

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

 0xa20b 

BBED> x   /w 

kcvfh.kcvfhbfh.type_kcbh                     @0 

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

 0x0000a20b 

BBED> x   /l 

kcvfh.kcvfhbfh.type_kcbh                     @0 

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

 0x0000a20b 

BBED> x   /r 

kcvfh.kcvfhbfh.type_kcbh                     @0 

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

BBED-00402: operation only allowed for data/index blocks 


위  내용처럼  여러  가지  옵션이  있습니다. 

/b : bytes  단위로  보여줍니다. 

/h : half-word  단위로  보여줍니다. 

/w : word  단위로  보여줍니다. 

/l : long  단위로  보여줍니다. 

/r : table/index row  를  보여줍니다. 


(19) (f)ind 

원하는  데이터를  찾아내는  고마운  기능입니다. 

BBED> set file 6 

        FILE#              6 

BBED> show 

        FILE#              6 

        BLOCK#           1 

        OFFSET           0 

        DBA              0x01800001 (25165825 6,1) 

        FILENAME         /app/oracle/oradata/testdb/ test01.dbf 

        BIFILE             bifile.bbd 

        LISTFILE           /home/oracle/target.log 

        BLOCKSIZE         8192 

        MODE             Edit 

        EDIT               Unrecoverable 

        IBASE              Dec 

        OBASE             Dec 

        WIDTH             80 

        COUNT            512 

        LOGFILE            log.bbd 

        SPOOL             No 

BBED> find   /c 10 

 File: /home/oracle/oradata/testdb/test01.dbf (6) 

 Block: 1                 Offsets:   342 to   391            Dba:0x01800001 

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

 31300000 00000000 00000000 00000000 00000000 00000000 00000600 00000000 

 00000000 0000ffeb 552c0000 00000000 0000 

 <32 bytes per line> 

BBED> find   /c tt 

BBED-00212: search string not found 


위  내용은  6번  파일에서  1번  블록부터  뒤져서  10  이  들어가는  블록을  찾아달라는  명령입니다.  

수행  결과를  보면  1번  블록에서  offset 342  에서  391까지  해당  데이터를  찾았다는  뜻입니다. 

아래쪽  결과는  찾는  단어가  없을  경우  에러  메시지를  보여  줍니다. 

이렇게  결과를  찾은  후  해당  블록을  조금  더  자세히  조사해  보겠습니다. 


BBED> d   /v dba 6,1 offset 342 count 50 

 File: /home/oracle/oradata/testdb/test01.dbf (6) 

 Block: 1        Offsets:   342 to   391   Dba:0x01800001 

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

 31300000 00000000 00000000 00000000 l 10.............. 

 00000000 00000000 00000600 00000000 l ................ 

 00000000 0000ffeb   552c0000 00000000 l ........U,...... 

 0000                                   l .. 

 <16 bytes per line> 

위  결과를  보니  1번  블록을  좀더  자세히  보니  맨  윗줄에  10  이라는  글자가  보입니다. 

find  명령에서  쓸  수  있는  옵션은  아래와  같습니다. 

/x : 16진수  값을  찾습니다 

/d : 10진수  값을  찾습니다. 

/u :  부호없는  10진수  값을  찾습니다. 

/o : 8진수  값을  찾습니다. 

/c :  문자값을  찾습니다 

find  명령어는  날짜와  숫자  값  검색은  지원하지  않습니다. 


(20) copy 

이  명령어는  블록을  복사하는  명령어  입니다. 

BBED> copy dba 6,1 to dba 7,1 

 File: /home/oracle/oradata/testdb/indx01.dbf (7) 

 Block: 1                 Offsets:   342 to   391            Dba:0x01c00001 

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

 31300000 00000000 00000000 00000000 00000000 00000000 00000600 00000000 

 00000000 0000ffeb 552c0000 00000000 0000 

 <32 bytes per line> 


위  명령어는  6번  파일의  1번  블록을  7번  파일의  1번  블록으로  복사하라는  뜻입니다. 

이  명령어는  아주  위험한  명령어입니다.  

위  예제를  수행하고  나면  7번  파일의  1번  블록은  6번 파일의  1번  블록과  같은  내용이  되어서  

만약  7번  파일이  다른  데이터  파일일  경우  아래와  같이 에러가  납니다. 


ERROR at line 1: 

ORA-01122: database file 7 failed verification check 

ORA-01110: data file 7: '/home/oracle/oradata/testdb/indx01.dbf' 

ORA-01210: data file header is media corrupt 


이  명령어는  백업  파일에서  특정  블록만을  운영  파일  등으로  복사해  올  때만  조심해서  사용해야 합니다. 


(21) (m)odify 

이  명령어는  블록의  내용을  변경하는  명령어입니다. 

앞에서  6번  파일의  1번  블록에  offset 342  번에  10  이란  데이터가  들어  있었습니다. 

그  데이터를  500으로  직접  변경해  보겠습니다. 


BBED>   m /c 500 dba 6,1 offset 342 

 File: /home/oracle/oradata/testdb/test01.dbf (6) 

 Block: 1                 Offsets:   342 to   391            Dba:0x01800001 

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

 35303000 00000000 00000000 00000000 00000000 00000000 00000600 00000000 

 00000000 0000ffeb 552c0000 00000000 0000 

 <32 bytes per line> 


BBED> dump /v dba 6,1 offset 342 count 50 

 File: /home/oracle/oradata/testdb/test01.dbf (6) 

 Block: 1        Offsets:   342 to   391   Dba:0x01800001 

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

 35303000 00000000 00000000 00000000 l 500............. 

 00000000 00000000 00000600 00000000 l ................ 

 00000000 0000ffeb   552c0000 00000000 l ........U,...... 

 0000                                   l .. 

 <16 bytes per line> 


(22) sum 

이  명령어는  블록의  checksum  을  계산해  주고  틀릴  경우  올바른  값으로  저장해  주는  명령입니다. 

위  실습으로  내용이  변경된  6번  파일의  1번  블록을  사용해서  테스트  하겠습니다. 


BBED> sum dba 6,1 

Check value for File 6, Block 1: 


current = 0xfcc0, required = 0xfcf4 

원래  데이터가  10  이었는데  500  으로  변경했습니다.  그래서  checksum  값이  변경되어야  하지만 

아직  저장을  안  해서  이전  checksum  값을  가지고  있습니다.  

위  결과를  보면  current  와 required  값으로  구분되어  나옵니다. 


BBED> sum dba 6,1 apply    <-  변경된  값을  저장합니다.

Check value for File 6, Block 1: 

current = 0xfcf4, required = 0xfcf4 


BBED> sum dba 6,1 

Check value for File 6, Block 1: 

current = 0xfcf4, required = 0xfcf4 


(23) push / pop 

Bbed  명령어는  특정  파일의  블록을  메모리로  가져와서  수정하거나  조회하는  명령어입니다. 

Push  명령어는  메모리의  stack  부분에  특정  블록을  강제로  적재  시키는  명령어이고  

pop  명령어는  push  명령어로  적재시킨  메모리를  해제하는  명령어입니다. 


(24) revert 

이  명령어는  변경된  내용을  BBed  가  실행되기  전  값으로  rollback  하는  명령어입니다. 

BBED> revert dba 6,1 

All changes made to this block will be rolled back.Proceed? (Y/N) y 

Reverted file '/home/oracle/oradata/testdb/test01.dbf', block 1 


BBED> dump /v dba 6,1 offset 342 

 File: /home/oracle/oradata/testdb/test01.dbf (6) 

 Block: 1        Offsets:   342 to   391   Dba:0x01800001 

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

 31300000 00000000 00000000 00000000 l 10.............. 

 00000000 00000000 00000600 00000000 l ................ 

 00000000 0000ffeb   552c0000 00000000 l ........U,...... 

 0000                                   l .. 

 <16 bytes per line> 

위  내용을  보면  처음에  10  이었던  값을  위에서  modify  명령어  이용해서  500  으로  변경한  후  

저장했습니다.  그러나  revert  명령어로  원래  값이던  10  으로  돌렸습니다. 


(25) undo 

이  명령어는  가장  마지막에  실행했던  변경  내용을  rollback  하는  명령어입니다. 

실습으로  확인하겠습니다. 

먼저  6번  파일의  1번  블록에  offset 342  의  값이  10  인  상태에서  500  으로  변경  후  다시  600  으로  변경합니다.

그리고  undo  명령을  수행합니다.  

그러면  가장  마지막에  했던  600  으로  변경하는  작업이  취소되어  해당  값은  500  으로  되어  있습니다. 


BBED> m /c 500 dba 6,1 offset 342 

 File: /home/oracle/oradata/testdb/test01.dbf (6) 

 Block: 1                 Offsets:   342 to   391            Dba:0x01800001 

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

 35303000 00000000 00000000 00000000 00000000 00000000 00000600 00000000 

 00000000 0000ffeb 552c0000 00000000 0000 

 <32 bytes per line> 


BBED> dump /v dba 6,1 offset   342 

 File: /home/oracle/oradata/testdb/test01.dbf (6) 

 Block: 1        Offsets:   342 to   391   Dba:0x01800001 

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

 35303000 00000000 00000000 00000000 l 500............. 

 00000000 00000000 00000600 00000000 l ................ 

 00000000 0000ffeb   552c0000 00000000 l ........U,...... 

 0000                                   l .. 

 <16 bytes per line> 


BBED> m /c 600 dba 6,1 offset 342 

 File: /home/oracle/oradata/testdb/test01.dbf (6) 

 Block: 1                 Offsets:   342 to   391            Dba:0x01800001 

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

 36303000 00000000 00000000 00000000 00000000 00000000 00000600 00000000 

 00000000 0000ffeb 552c0000 00000000 0000 

 <32 bytes per line> 


BBED> dump /v dba 6,1 offset 342 

 File: /home/oracle/oradata/testdb/test01.dbf (6) 

 Block: 1        Offsets:   342 to   391   Dba:0x01800001 

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

 36303000 00000000 00000000 00000000 l 600............. 

 00000000 00000000 00000600 00000000 l ................ 

 00000000 0000ffeb   552c0000 00000000 l ........U,...... 

 0000                                   l .. 

 <16 bytes per line> 


BBED>undo

BBED> modify /x 353030 filename '/home/oracle/oradata/testdb/test01.dbf' block 1. offset 342. 

 File: /home/oracle/oradata/testdb/test01.dbf (6) 

 Block: 1                 Offsets:   342 to   391            Dba:0x01800001 

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

 35303000 00000000 00000000 00000000 00000000 00000000 00000600 00000000 

 00000000 0000ffeb 552c0000 00000000 0000 

 <32 bytes per line> 


BBED> dump /v dba 6,1 offset   342 

 File: /home/oracle/oradata/testdb/test01.dbf (6) 

 Block: 1        Offsets:   342 to   391   Dba:0x01800001 

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

 35303000 00000000 00000000 00000000 l 500............. 

 00000000 00000000 00000600 00000000 l ................ 

 00000000 0000ffeb   552c0000 00000000 l ........U,...... 

 0000                                   l .. 

 <16 bytes per line> 

Undo  와  revert  의  차이는  rollback  시점이  처음상태이냐  아니면  가장  마지막  작업만  취소냐  

하는  것입니다. 


(26) verify 

이  명령어는  특정  파일의  블록의  무결성을  검사하는  명령입니다. 


BBED> verify dba 6,1 

DBVERIFY - Verification starting 

FILE = /home/oracle/oradata/testdb/test01.dbf 

BLOCK = 1 

Block 1 is corrupt 

Corrupt block relative dba: 0x01800001 (file 0, block 1) 

Bad check value found during verification 

Data in bad block: 

 type: 11 format: 2 rdba: 0x01800001 

 last change scn: 0x0000.00000000 seq: 0x1 flg: 0x04 

 spare1: 0x0 spare2: 0x0 spare3: 0x0 

 consistency value in tail: 0x00000b01 

 check value in block header: 0xfcc0 

 computed block checksum: 0x34 

DBVERIFY - Verification complete 

Total Blocks Examined          : 1 

Total Blocks Processed (Data)    : 0 

Total Blocks Failing    (Data)     : 0 

Total Blocks Processed (Index)   : 0 

Total Blocks Failing    (Index)    : 0 

Total Blocks Empty             : 0 

Total Blocks Marked Corrupt    : 1 

Total Blocks Influx              : 0 


BBED> verify file 6 

DBVERIFY - Verification starting 

FILE = /home/oracle/oradata/testdb/test01.dbf 

Block 1 is corrupt 

Corrupt block relative dba: 0x01800001 (file 0, block 1) 

Bad check value found during verification 

Data in bad block: 

 type: 11 format: 2 rdba: 0x01800001 

 last change scn: 0x0000.00000000 seq: 0x1 flg: 0x04 

 spare1: 0x0 spare2: 0x0 spare3: 0x0 

 consistency value in tail: 0x00000b01 

 check value in block header: 0xfcc0 

 computed block checksum: 0x34 

Block 12 is corrupt 

Corrupt block relative dba: 0x0180000c (file 0, block 12) 

Bad check value found during verification 

Data in bad block: 

 type: 6 format: 2 rdba: 0x0180000c 

 last change scn: 0x0000.00177251 seq: 0x1 flg: 0x06 

 spare1: 0x0 spare2: 0x0 spare3: 0x0 

 consistency value in tail: 0x72510601 

 check value in block header: 0x5bec 

 computed block checksum: 0x3 

Block 26 is corrupt 

Corrupt block relative dba: 0x0180001a (file 0, block 26) 

Bad check value found during verification 

Data in bad block: 

 type: 6 format: 2 rdba: 0x0180001a 

 last change scn: 0x0000.00177d85 seq: 0x1 flg: 0x06 

 spare1: 0x0 spare2: 0x0 spare3: 0x0 

 consistency value in tail: 0x7d850601 

 check value in block header: 0x640e 

 computed block checksum: 0x1700 

Block 391 is corrupt 

Corrupt block relative dba: 0x01800187 (file 0, block 391) 

Bad check value found during verification 

Data in bad block: 

 type: 6 format: 2 rdba: 0x01800187 

 last change scn: 0x0000.00177d85 seq: 0x1 flg: 0x06 

 spare1: 0x0 spare2: 0x0 spare3: 0x0 

 consistency value in tail: 0x7d850601 

 check value in block header: 0xd28f 

 computed block checksum: 0x2300 

Block 474 is corrupt 

Corrupt block relative dba: 0x018001da (file 0, block 474) 

Bad check value found during verification 

Data in bad block: 

 type: 6 format: 2 rdba: 0x018001da 

 last change scn: 0x0000.00177d85 seq: 0x1 flg: 0x06 

 spare1: 0x0 spare2: 0x0 spare3: 0x0 

 consistency value in tail: 0x7d850601 

 check value in block header: 0xb2e9 

 computed block checksum: 0x34 

Block 484 is corrupt 

Corrupt block relative dba: 0x018001e4 (file 0, block 484) 

Bad check value found during verification 

Data in bad block: 

 type: 6 format: 2 rdba: 0x018001e4 

 last change scn: 0x0000.00177d85 seq: 0x1 flg: 0x06 

 spare1: 0x0 spare2: 0x0 spare3: 0x0 

 consistency value in tail: 0x7d850601 

 check value in block header: 0x8380 

 computed block checksum: 0xf00 

Block 493 is corrupt 

Corrupt block relative dba: 0x018001ed (file 0, block 493) 

Bad check value found during verification 

Data in bad block: 

 type: 6 format: 2 rdba: 0x018001ed 

 last change scn: 0x0000.00177d85 seq: 0x1 flg: 0x06 

 spare1: 0x0 spare2: 0x0 spare3: 0x0 

 consistency value in tail: 0x7d850601 

 check value in block header: 0x8594 

 computed block checksum: 0x23 

DBVERIFY - Verification complete 

Total Blocks Examined          : 528 

Total Blocks Processed (Data)    : 307 

Total Blocks Failing    (Data)     : 0 

Total Blocks Processed (Index )   : 0 

Total Blocks Failing    (Index)    : 0 

Total Blocks Empty             : 190 

Total Blocks Marked Corrupt    : 7 

Total Blocks Influx              : 0 


(27) corrupt 

이  명령어는  corrupt  된  블록을  mark  합니다. 

BBED> corrupt dba 6,1 

Block marked media corrupt. 

이상으로  Bbed  의  주요  명령어들과  사용방법을  살펴  보았습니다. 

다음  장에서는  지금까지  보셨던  명령어들을  사용해서  어떻게  장애를  직접  처리하는  지  살펴보겠습니다. 



4) Bbed  를  활용한  block recovery  예제들 


1) Delete  장애  복구하기 

이번  실습은  bbed  를  사용해서  데이터가  delete  된  block  를  찾아서  delete 이전으로  복구하는  내용입니다.


Step 1.  아래와  같이  실습용  테이블을  만듭니다. 

 [ fruit  테이블  ] 

no  name  price 

01  apple  100 

02  oranege  200 


SQL> create table fruit 

  2   (no number, 

  3    name varchar2(10), 

  4    price varchar2(10)) tablespace users ; 

SQL> insert into fruit values (1,'apple','100'); 

SQL> commit; 

SQL> insert into fruit values (2,'orange','200'); 

SQL> commit; 

SQL> select * from fruit; 

SQL> select rowid,no,name,price 

  2   from fruit; 


Step 2. Rowid  로  위  데이터가  들어  있는  블록  주소  찾기 

SQL> select dbms_rowid.rowid_block_number('AAANccAAGAAAAAUAAA') 

  2   from fruit; 


SQL> select dbms_rowid.rowid_block_number('AAANccAAGAAAAAUAAB') 

  2   from fruit; 


두  건의  데이터  모두  20  번  블록에  들어가  있다는  것이  조회됩니다. 

BBed  로  20  번  블록을  확인해  보겠습니다. 


BBED> set dba 6,20 

        DBA              0x01800014 (25165844 6,20) 


BBED> find /c apple 

 File: /home/oracle/oradata/testdb/test10.dbf (6) 

 Block: 20                Offsets: 8179 to 8191            Dba:0x01800014 

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

 6170706c 65033130 30010640 56 

 <32 bytes per line> 


BBED> dump /v dba 6,20 offset 8179 

 File: /home/oracle/oradata/testdb/test10.dbf (6) 

 Block: 20       Offsets: 8179 to 8191   Dba:0x01800014 

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

 6170706c 65033130 30010640 56        l apple.100..@V 

 <16 bytes per line> 


BBED> set offset 0 

        OFFSET           0 


BBED> set dba 6,20 

        DBA              0x01800014 (25165844 6,20) 


BBED> find /c orange 

 File: /home/oracle/oradata/testdb/test10.dbf (6) 

 Block: 20                Offsets: 8162 to 8191            Dba:0x01800014 

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

 6f72616e 67650332 30302c01 0302c102 05617070 6c650331 30300106 4056 

 <32 bytes per line> 


BBED> dump /v dba 6,20 offset 8162 

 File: /home/oracle/oradata/testdb/test10.dbf (6) 

 Block: 20       Offsets: 8162 to 8191   Dba:0x01800014 

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

 6f72616e 67650332 30302c01 0302c102 l orange.200,..... 

 05617070 6c650331 30300106 4056      l .apple.100..@V 

 <16 bytes per line> 


위  블록의  내용을  보니  offset 8162  에  orange  가  입력되어  있고  offset 8179  에  apple  이  입력되

어  있음을  알  수  있습니다. 



Step 3. Apple  을  delete  한  후  commit  을  수행한  후  block  내용  다시  조회 

--  터미널  1  작업  -- 

SQL> select * from fruit; 

     NO    NAME           PRICE 

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

       1    apple           100 

       2    orange          200 


SQL> delete from fruit where no=1; 

1 row deleted. 


SQL> commit; 

Commit complete. 


SQL> select * from fruit; 

    NO    NAME            PRICE 

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

       2   orange           200 


SQL> alter system checkpoint; 

System altered. 


--  터미널  2  작업  -- 

위  작업을  수행  한  후  다른  터미널에서  bbed  를  실행해서  블록을  살펴  보겠습니다. 


BBED> find /c apple 

 File: /home/oracle/oradata/testdb/test10.dbf (6) 

 Block: 20                Offsets: 8179 to 8191            Dba:0x01800014 

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

 6170706c 65033130 30010640 56 

 <32 bytes per line> 


BBED> dump /v dba 6,20 offset 8179 count 50 

 File: /home/oracle/oradata/testdb/test10.dbf (6) 

 Block: 20       Offsets: 8179 to 8191   Dba:0x01800014 

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

 6170706c 65033130 30010602 57        l apple.100...W 

 <16 bytes per line> 


여전히  block  내부에는  apple  이  삭제되지  않고  존재함을  알  수  있습니다. 

이  이유는  DML  을  수행하면  오라클은  해당  블록에서  직접  데이터를  지우지  않고  해당  row에  사용하지  않는다는  표시만  하게  됩니다.  

그리고  freespace  에는  빈  곳으로  표시됩니다.

이렇게  해당  데이터가  delete  되었다는  표시는  해당  row의  Header  부분에  표시됩니다. 

Row Header  는  Row Flag , Lock Byte (ITL entry), Column Count  로  구성이  되는데  제일  먼저  있는 

Row Flag  부분은  해당  row  의  상태를  표시하는  1 byte  로  구성이  됩니다. 


이곳에  표시될  수  있는  값이  아래  표에  있습니다. 

Cluster Key                     128

Cluster Table Member     64

Head of Row Piece         32

Deleted                          16

First data piece              8

Last data piece             4

1st column                     2

Last Column                   1


위  표의  값들을  계산해서  row header  정보를  분석하면  해당  row  가  어떤  상태인지  알  수  있습니다. 

위의  실습처럼  apple  를  삭제  한  후  row header  정보를  살펴보겠습니다. 

일반  테이블에서  특정  row  가  삭제된다면  deleted  부분이  set  으로  설정이  되어  32+16+8+4 = 60  이  되어  

16진수로  0x3c  값이  되고  데이터가  delete  안되었다면  deleted  부분이  not set  상태여서  32+8+4=44  로  16진수  0x2c  에  해당됩니다. 


BBED> p   *kdbr[0] 

rowdata[17] 

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

ub1 rowdata[17]                              @8172      0x3c 


BBED> p   *kdbr[1] 

rowdata[0] 

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

ub1 rowdata[0]                               @8155      0x2c 


위  결과를  보면  apple  은  offset 8179  에  있었는데  row header  는  8172  임을  알  수  있으며  row header  값이  0x3c  로  

delete  되었다는  내용을  알  수  있습니다. 


또  orange  는  offset 8162  에  입력되어  있었는데  row header  는  8155  임을  알  수  있으며  0x2c  로  데이터가  존재한다는  것도  알  수  있습니다. 


Step 4. Bbed로  복구한  후  조회하기 

복구  원리는  간단합니다. 8172  의  0x3c  값을  0x2c  값으로  변경하고  저장만  하면  바로  적용됩니다. 

아래와  같이  하시면  됩니다. 


BBED> m   /x   2c   offset   8172 

 File: /home/oracle/oradata/testdb/test10.dbf (6) 

 Block: 20                Offsets: 8172 to 8191            Dba:0x01800014 

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

 2c010302 c1020561 70706c65 03313030 01060257 

 <32 bytes per line> 


BBED> sum dba 6,20 

Check value for File 6, Block 20: 

current = 0xb8b8, required = 0xb8a8 


BBED> sum dba 6,20 apply 

Check value for File 6, Block 20: 

current = 0xb8a8, required = 0xb8a8 


BBED>   p *kdbr[0] 


rowdata[17] 

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

ub1 rowdata[17]                              @8172      0x2c

--  터미널  2 – 

다른  터미널에서  확인해  보겠습니다. 


SQL> select * from fruit; 

    NO    NAME            PRICE 

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

       2    orange          200   <-  아직  복구  전  값이  나옵니다. 


SQL> alter tablespace test10 offline; 

Tablespace altered. 


SQL> alter tablespace test10 online; 

Tablespace altered. 

SQL> select * from fruit; 

    NO    NAME                  PRICE 

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

1    apple                 100   <-  다시  살아납니다. 

      2    orange                200 

이번에는  BBed  로  2번  orange  의  row header  값을  0x3c로  변경하고  확인 해  보겠습니다. 


BBED> m /x 3c offset   8155 

 File: /home/oracle/oradata/testdb/test10.dbf (6) 

 Block: 20                Offsets: 8155 to 8191            Dba:0x01800014 

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

 3c000302 c103066f 72616e67 65033230 302c0103 02c10205 6170706c 65033130 

 30010602 57 

 <32 bytes per line> 


BBED> sum dba 6,20 apply 

Check value for File 6, Block 20: 

current = 0xa8a8, required = 0xa8a8 


BBED> p *kdbr[1] 

rowdata[0] 

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

ub1 rowdata[0]                               @8155      0x3c   <-  삭제  표시  되었습니다. 

--  터미널  2 – 

다른  터미널에서  이  내용이  반영되었는지  확인하겠습니다. 


SQL> alter tablespace test10 offline; 

Tablespace altered. 


SQL> alter tablespace test10 online; 

Tablespace altered. 


SQL> select * from fruit; 

    NO    NAME            PRICE 

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

      1    apple             100     

예상대로  orange  가  보이지  않습니다. 


2) BBED로  Block corruption  장애  복구하기 

Oracle 8i부터는  DBMS_REPAIR  이란  패키지가  나와서  Block Corrupt  장애가  나도  쉽게  해결할  수 있음을  앞에서  살펴보았습니다. 

그러나  여기서는  Bbed  를  사용하여  corrupt  된  block  를  recovery  해  보겠습니다. 

DBMS_REPAIR  과  BBed  와는  아주  중요한  차이가  있습니다. 

어떤  블록에  있는  특정  row  에서  corruption  이  발생했을  경우  DBMS_REPAIR  는  해당  블록  전체를  Corruption  처리해서  skip 하게  됩니다.  

그  말은  해당  블록  안에  있는  전체  내용이  손상된다는  뜻입니다. 

그러나  BBED  는  corruption이  발생한  row  만  corruption  처리를  하기  때문에  그 블록  안에  있는  데이터들은  살려  낼  수  있습니다.  

이  실습을  위해  테스트  테이블  tt930  을  생성하고  데이터를  5건  입력하겠습니다. 

그리고  특정  row  에  corruption  을  발생시켜  DBMS_REPAIR  과  BBED  로 복구해서  차이를  살펴보겠습니다. 


<  실습  1. DBMS_REPAIR  로  block corruption  복구하기  > 

Step 1.  실습용  테이블  tt930  테이블을  생성합니다. 

SQL> !vi dd.sql 

conn / as sysdba 

set line 200 

col tablespace_name for a10 

col file_name for a50 

col mb for 9999 

select tablespace_name , bytes/1024/1024 MB , file_name 

from dba_data_files 

:wq! 


SQL> @dd 

Connected. 

TABLESPACE       MB    FILE_NAME 

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

EXAMPLE         183    /home/oracle/oradata/testdb/example01.dbf 

USERS            20     /home/oracle/oradata/testdb/users01.dbf 

SYSAUX          340    /home/oracle/oradata/testdb/sysaux01.dbf 

UNDOTBS1        50    /home/oracle/oradata/testdb/undotbs01.dbf 

SYSTEM          460    /home/oracle/oradata/testdb/system01.dbf 

TEST10             1    /home/oracle/oradata/testdb/test10.dbf 

6 rows selected. 


SQL> create table tt930 (no number,name varchar2(10)) tablespace test10; 

Table created. 

SQL> insert into tt930 values (1,'AAAAA'); 

1 row created. 

SQL> insert into tt930 values (2,'BBBBB'); 

1 row created. 

SQL> insert into tt930 values (3,'CCCCC'); 

1 row created. 

SQL> insert into tt930 values (4,'DDDDD'); 

1 row created. 

SQL> insert into tt930 values (5,'EEEEE'); 

1 row created. 

SQL> commit; 

Commit complete. 

SQL> select * from tt930; 

    NO    NAME 

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

       1    AAAAA 

       2    BBBBB 

       3    CCCCC 

       4    DDDDD 

       5    EEEEE 


SQL> select dbms_rowid.rowid_block_number('AAANcdAAGAAAAAcAAA') from tt930; 

DBMS_ROWID.ROWID_BLOCK_NUMBER('AAANCDAAGAAAAACAAA')

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

                                                 28

                                                 28

                                                 28

                                                 28

                                                 28

위  5건의  데이터가  모두  28번  블록에  들어  있다는  것이  확인됩니다. 


Step 2.   1   AAAAA row  를  corruption  발생시킨  후  조회하겠습니다. 

윈도로  위  데이터  파일을  가져온  후  에디터에서  AAAAA  를  수정하여  block corruption  을  발생시킨  후  리눅스로  보내서  아래와  같이  작업  하겠습니다. 


SQL> alter tablespace test10 offline; 

Tablespace altered. 

SQL> alter tablespace test10 online; 

Tablespace altered. 

SQL> select * from tt930; 

select * from tt930 

              * 

ERROR at line 1: 

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

ORA-01110: data file 6: '/home/oracle/oradata/testdb/test10.dbf' 

예상대로  28번  block  에  corruption  이  발생해서  조회가  되지  않습니다. 



Step 3. DBMS_REPAIR  로  복구하겠습니다. 

 -- corruption detect – 

SQL> set serveroutput on 

SQL> 

SQL> declare num_corrupt int; 

  2   begin 

  3   num_corrupt := 0; 

  4   dbms_repair.check_object ( 

  5     schema_name => 'SYS' , 

  6     object_name => 'TT930' , 

  7     repair_table_name => 'REPAIR_TABLE', 

  8     corrupt_count => num_corrupt ); 

  9 

 10   dbms_output.put_line('==================================='); 

 11   dbms_output.put_line('  장애블록수  :'|| to_char(num_corrupt)); 

 12   end; 

 13   / 

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

장애블록수  :1 

PL/SQL procedure successfully completed. 


1  개의  블록에  장애가  발생했음을  알  수  있습니다. 

보다  자세한  내용을  살펴보겠습니다. 


SQL> col object_name for a10 

SQL> col corrupt_description for a20 

SQL> col repair_description for a30 

SQL> set line 200 

SQL> 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_CORRUPT   CORRUPT_DESCRIPTION   REPAIR_DESCRIPTION 

---------------- ------------- -------------------------------------------- ----------------------------- ------------------------TT930               28                6148    TRUE                                         mark block soft ware  

corrupt 

28번  블록이  에러  났다는  것을  알  수  있습니다. 

-- skip  설정하겠습니다. 


SQL> begin 

  2   dbms_repair.skip_corrupt_blocks ( 

  3     schema_name => 'SYS' , 

  4     object_name => 'TT930' , 

  5     object_type => dbms_repair.table_object , 

  6     flags => dbms_repair.skip_flag ); 

 All About Oracle Backup and Recovery -  서진수  저  

  7   end; 

  8   / 

PL/SQL procedure successfully completed. 


Step 4.   Tt930  테이블을  다시  조회합니다. 

SQL> select * from tt930; 

no rows selected 

한  건의  데이터도  안  나옴을  알  수  있습니다.  

즉  DBMS_REPAIR  은  블록에서  특정  row  만  장애  나도  블록  전체를  corrupt  처리해서  해당  블록 

내부에  있는  데이터를  모두  손실하게  되는  문제가  있습니다. 

반면에  Bbed  는  장애  난  row  만  corruption  처리를  하기  때문에  나머지  데이터는  전부  살려낼 

수  있습니다.  동일한  장애  발생  시킨  후  BBED  로  복구해  보겠습니다. 


<  실습  2. BBED  로  block corruption  복구하기  > 

Step 1.  실습용  테이블  tt940  을  생성합니다. 

SQL> @dd 

Connected. 

TABLESPACE      MB    FILE_NAME 

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

EXAMPLE        183    /home/oracle/oradata/testdb/example01.dbf 

USERS            20    /home/oracle/oradata/testdb/users01.dbf 

SYSAUX          340    /home/oracle/oradata/testdb/sysaux01.dbf 

UNDOTBS1        50    /home/oracle/oradata/testdb/undotbs01.dbf 

SYSTEM          460    /home/oracle/oradata/testdb/system01.dbf 

TEST10             1    /home/oracle/oradata/testdb/test10.dbf 

6 rows selected. 

SQL> create table tt940 (no number, name varchar2(10)) tablespace test10; 

Table created. 

 All About Oracle Backup and Recovery -  서진수  저  

SQL> insert into tt940 values (1,'AAAAA'); <-  이  row 에  장애를  발생시킬  예정입니다. 

1 row created. 

SQL> insert into tt940 values (2,'BBBBB'); 

1 row created. 

SQL> insert into tt940 values (3,'CCCCC'); 

1 row created. 

SQL> insert into tt940 values (4,'DDDDD'); 

1 row created. 

SQL> insert into tt940 values (5,'EEEEE'); 

1 row created. 

SQL> commit; 

Commit complete. 

SQL> select * from tt940; 

    NO    NAME 

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

       1    AAAAA 

       2    BBBBB 

       3    CCCCC 

       4    DDDDD 

       5    EEEEE 

SQL> select rowid, no , name from tt940; 

ROWID                        NO      NAME 

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

AAANceAAGAAAAAkAAA             1    AAAAA 

AAANceAAGAAAAAkAAB             2    BBBBB 

AAANceAAGAAAAAkAAC             3    CCCCC 

AAANceAAGAAAAAkAAD             4    DDDDD 

AAANceAAGAAAAAkAAE             5    EEEEE 


SQL> select dbms_rowid.rowid_block_number('AAANceAAGAAAAAkAAA') from tt940; 

DBMS_ROWID.ROWID_BLOCK_NUMBER('AAANCEAAGAAAAAKAAA')

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

                                                 36

                                                 36

                                                 36

                                                 36

                                                 36

36번  블록에  저장되어  있다는  것이  확인됩니다. 



Step 2. AAAAA row  에  장애를  발생시킵니다. 

윈도로  해당  데이터파일을  가져와서  에디터로  해당  row  를  corruption  발생  시킨  후 리눅스로  보내고  아래와  같이  진행하겠습니다. 

SQL> alter tablespace test10 offline; 

Tablespace altered. 

SQL> alter tablespace test10 online; 

alter tablespace test10 online 

ERROR at line 1: 

ORA-01113: file 6 needs media recovery if it was restored from backup, or END BACKUP if it was 

not 

ORA-01110: data file 6: '/home/oracle/oradata/testdb/test10.dbf' 

SQL> recover tablespace test10; 

Media recovery complete. 

SQL> alter tablespace test10 online; 

Tablespace altered. 

SQL> select * from tt940; 

select * from tt940 

ERROR at line 1: 

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

ORA-01110: data file 6: '/home/oracle/oradata/testdb/test10.dbf' 

36번  블록에  corruption  이  발생한  것을  알  수  있습니다. 



Step 3. BBED  를  실행시켜  해당  row  를  복구합니다. 

[oracle@localhost ~]$ vi filelist.log 

1   /home/oracle/oradata/testdb/system01.dbf   482344960 

2   /home/oracle/oradata/testdb/undotbs01.dbf   52428800 

3   /home/oracle/oradata/testdb/sysaux01.dbf   356515840 

4   /home/oracle/oradata/testdb/users01.dbf   20971520 

5   /home/oracle/oradata/testdb/example01.dbf   192020480 

6   /home/oracle/oradata/testdb/test10.dbf   4325376 

:wq! 

[oracle@localhost ~]$ vi bbed.par 

blocksize=8192 

listfile=/home/oracle/filelist.log 

mode=edit 

:wq! 

[oracle@localhost ~]$ bbed parfile=bbed.par 

Password: blockedit 

BBED: Release 2.0.0.0.0 - Limited Production on ThuFeb 24 13:19:11 2011 

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

************* !!! For Oracle Internal Use only !!! *************** 

BBED> set dba 6,36 

        DBA              0x01800024 (25165860 6,36) 

BBED> corrupt block 36    <-  장애  난  블록을  corrupt  처리  합니다.

Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) y 

Block marked media corrupt. 

BBED> p kcbh 

struct kcbh, 20 bytes                          @0 

   ub1 type_kcbh                             @0         0x06 

   ub1 frmt_kcbh                             @1         0xa2 

   ub1 spare1_kcbh                           @2         0x00 

   ub1 spare2_kcbh                           @3         0x00 

   ub4 rdba_kcbh                             @4         0x01800024 

   ub4 bas_kcbh                              @8         0x00000000 

   ub2 wrp_kcbh                              @12        0x0000 

ub1 seq_kcbh                              @14        0xff 

   ub1 flg_kcbh                               @15        0x04 (KCBHFCKV) 

   ub2 chkval_kcbh                            @16        0x4267 

   ub2 spare3_kcbh                            @18        0x0000 

오라클은  특정  블록이  corrupt  되면  해당  블록의  sequence number  를  0xff  로  설정하며  

이것은 seq_kcbh  에서  조회가  가능합니다.  위의  굵은  표시로  해  둔  곳입니다. 

이  값을  다른  사용  가능한  값  (예를  들어  0x01  등)  으로  변경하면  block corruption  이  취소됩니다. 


BBED> m /x 01 dba 6,36 offset   14 

 File: /home/oracle/oradata/testdb/test10.dbf (6) 

 Block: 36                Offsets:    14 to   525            Dba:0x01800024 

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

 01046742 00000100 00001ed7 00003274 18000000 00000200 32002100 80010600 

 1900dd01 00000509 80007401 20000080 00004873 18000000 00000000 00000000 

 00000000 00000000 00000000 00000000 00000000 00000001 0500ffff 1c005c1f 

(  지면  관계상  중간  결과  출력은  생략합니다  ) 

 <32 bytes per line> 


BBED> p   kcbh 

struct kcbh, 20 bytes                        @0 

   ub1 type_kcbh                             @0         0x06 

   ub1 frmt_kcbh                             @1         0xa2 

   ub1 spare1_kcbh                           @2         0x00 

   ub1 spare2_kcbh                           @3         0x00 

   ub4 rdba_kcbh                             @4         0x01800024 

   ub4 bas_kcbh                              @8         0x00000000 

   ub2 wrp_kcbh                              @12        0x0000 

   ub1 seq_kcbh                              @14        0x01 

   ub1 flg_kcbh                               @15        0x04 (KCBHFCKV) 

   ub2 chkval_kcbh                            @16        0x4267 

   ub2 spare3_kcbh                            @18        0x0000 

또한  sequence number  는  마지막  8 bytes  에  해당  row  의  corruption  여부를  등록해  두는데  

리는  아래와  같이  tailchk  를  이용해서  조회를  할  수  있습니다. 

해당  row  에  장애가  생기면  이  row  의  값이  0x000006ff 로  설정이  되는데  이  값  역시  새로운 SCN  으로  변경해  주어야  합니다. 


BBED> p   tailchk 

ub4 tailchk                                  @8188      0x000006ff


BBED> m /x 01060000 dba 6,36 offset 8188 

 File: /home/oracle/oradata/testdb/test10.dbf (6) 

 Block: 36                Offsets: 8188 to 8191            Dba:0x01800024 

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

 01060000   <-  원래  06ff  였던  값을  사용  가능한  0x10 (010)  으로  변경했습니다. 

 <32 bytes per line> 


BBED> sum dba 6,36 apply 

Check value for File 6, Block 36: 

current = 0x4267, required = 0x4267 


그  후에  해당  블록의  변경된  checksum  값을  저장하고  적용하는  것으로  corruption  이  발생한  블록의  수정  작업을  마쳤습니다. 

이제  다른  창에서  장애  난  테이블을  다시  조회  해  보겠습니다. 


기억해야  할  것은  위에서  DBMS_REPAIR  로는  Block Recovery  를  한  후에도 해당  블록에  있던  모든  내용이  조회가  되지  않았다는  것입니다. 


SQL> select * from tt940; 

select * from tt940 

ERROR at line 1: 

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

ORA-01110: data file 6: '/home/oracle/oradata/testdb/test10.dbf' 


SQL> alter tablespace test10 offline; 

Tablespace altered. 

SQL> alter tablespace test10 online; 

Tablespace altered. 

SQL> select * from tt940; 

    NO    NAME 

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

       1    AzAAA <-  필자가  발생시킨  Corruption  난  row  입니다. 

       2    BBBBB 

       3    CCCCC 

       4    DDDDD 

       5    EEEEE 


위에서  보듯이  해당  블록에  모든  데이터가  조회  됩니다. 

위  실습을  다시  정리합니다. 

필자는  1번  row  의  AAAAA  를  AzAAA  로  강제  수정해서  Block corruption  을  발생시켰습니다. 

위  5건의  데이터는  모두  6번  파일의  36번  블록에  들어가  있었는데  강제로  내용을  수정시켜서

Block corruption  을  발생  시킨  후  DBMS_REPAIR  로  Block Recovery  를  했으나  36번  블록  전체가 

Corruption  처리  되어서  모든  데이터가  전부  조회가  되지  않았습니다. 


그러나  BBED  로  Corruption  된  Row  만  찾아서  Recovery  한  후  조회하니까  모든  데이터가  전부 조회  되었습니다. 

BBED  를  활용한  아주  막강한  Block Recovery  기능이니  잘  숙지하셔서  요긴하게  사용하시기  바랍니다. 



실습  3. Noarchive log mode  에서  복구가  안  되는  데이터  파일  Open  하기

이번  경우는  Noarchive log mode  에서  Archive redo log file  이  없어서  복구가  안되는  데이터파일의  블록을  제어해서  open  을  시키는  과정입니다. 


Step 1.  현재  상황  확인  후  다수의   Log Switch  발생하기 

SYS>archive log list; 

Database log mode             No Archive Mode 

Automatic archival              Disabled 

Archive destination             /data/arc2 

Oldest online log sequence      17 

Current log sequence            19 

SYS>alter system switch logfile; 

System altered. 

SYS>/ 

System altered. 

(  지면  관계상  수행  과정은  생략하지만  반복해서  Log Switch  를  발생시키세요  ) 



Step 2. DB  종료  후  현재  상태를  Close Backup  수행합니다. 

SYS>shutdown immediate; 

Database closed. 

Database dismounted. 

ORACLE instance shut down. 

SYS>! 

[oracle@localhost ~]$ mkdir /data/backup/close/noarch/ 

[oracle@localhost ~]$ cp /app/oracle/oradata/testdb/* /data/backup/close/noarch/ 

[oracle@localhost ~]$ exit 

exit 



Step 3.  백업  파일의  내용과  Checkpoint SCN  정보를  다르게  만듭니다. 

SYS>startup 

ORACLE instance started. 

Total System Global Area   422670336 bytes 

Fixed Size                   1344616 bytes 

Variable Size              260049816 bytes 

Database Buffers           155189248 bytes 

Redo Buffers                 6086656 bytes 

Database mounted. 

Database opened. 

SYS>alter system checkpoint ; 

System altered. 

SYS>/ 

System altered. 

SYS>/ 

System altered. 

SYS>alter system switch logfile; 

System altered. 

SYS>/ 

System altered. 



Step 4. DB  종료  후  백업해  둔  users01.dbf  파일을  운영  경로로  복사  후  Open  시도합니다. 

SYS>shutdown immediate; 

Database closed. 

Database dismounted. 

ORACLE instance shut down. 

SYS>! 

[oracle@localhost ~]$ cp /data/backup/close/noarch/users01.dbf /app/oracle/oradata/testdb/ 

[oracle@localhost ~]$ exit 

exit 

SYS>startup 

ORACLE instance started. 

Total System Global Area   422670336 bytes 

Fixed Size                   1344616 bytes 

Variable Size              260049816 bytes 

Database Buffers           155189248 bytes 

Redo Buffers                 6086656 bytes 

Database mounted. 

ORA-01113: file 4 needs media recovery 

ORA-01110: data file 4: '/app/oracle/oradata/testdb/users01.dbf' 

SYS>recover datafile '/app/oracle/oradata/testdb/users01.dbf' ; 

ORA-00279: change 1904232 generated at 11/26/2013 04:36:04 needed for thread 1 

ORA-00289: suggestion : /data/arc2/26_1_823319766.arc 

ORA-00280: change 1904232 for thread 1 is in sequence #26 

Specify log: {<RET>=suggested | filename | AUTO | CANCEL} 

ORA-00326: log begins at change 1952656, need earlier change 1904232 

ORA-00334: archived log: '/data/arc2/26_1_823319766.arc' 

SYS>alter database open; 

alter database open 

ERROR at line 1: 

ORA-01113: file 4 needs media recovery 

ORA-01110: data file 4: '/app/oracle/oradata/testdb/users01.dbf' 


위와  같이  복구가  필요하다고  나오지만  No  Archive  Log  Mode  이므로  복구할  수  없어서  복구도 안되고  Open  도  안됩니다.

이럴  경우  기존  방법은  해당  파일만  Offline  drop  처리하고  DB를 Open  하면  되지만  

그럴  경우  Offline Drop  된  파일에  저장되어  있던  내용은  모두 손실됩니다. 

이런  경우를  BBED  를  활용해서  장애  난  파일의  블록을  직접  조작해서  OPEN  시켜  보겠습니다. 


SYS>select checkpoint_change# from v$database; 

CHECKPOINT_CHANGE# 

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

           1905030    <--  정상적인  checkpoint scn  정보 


SYS>select change# from v$recover_file ; 

   CHANGE# 

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

   1904232 <-- users01.dbf  의  문제되는  예전  scn  정보 

위에서  보는  바와  같이  정상적인  Checkpoint  SCN  은  1905030  인데  장애난  users01.dbf  는 

1904232  라서  Open  이  되지  않습니다.  

이런  경우를  해결하는  방법은  users01.dbf  의  블록을  조작해서  정보를  동일하게  세팅을  하면  됩니다. 



Step  5.  bbed  를  사용해서  system01.dbf  의  정보를  확인  한  후  users01.dbf  의  정보를 system01.dbf  의  정보로  업데이트  함. 

[oracle@localhost ~]$ vi /home/oracle/target.log 

1   /app/oracle/oradata/testdb/system01.dbf   754974720 

2   /app/oracle/oradata/testdb/sysaux01.dbf   681574400 

3   /app/oracle/oradata/testdb/undotbs01.dbf   10485760 

4   /app/oracle/oradata/testdb/users01.dbf   10485760

5   /app/oracle/oradata/testdb/example01.dbf   362414080 

:wq! 

[oracle@localhost ~]$ vi bbed.par 

blocksize=8192 

listfile=/home/oracle/target.log 

mode=edit  

:wq! 

[oracle@localhost ~]$ bbed parfile=bbed.par 

Password: blockedit 

BBED: Release 2.0.0.0.0 - Limited Production on TueNov 26 04:55:07 2013 

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

************* !!! For Oracle Internal Use only !!! *************** 

BBED> set filename '/app/oracle/oradata/testdb/system01.dbf' 

        FILENAME         /app/oracle/oradata/testdb/ system01.dbf 

BBED> p kcvfhckp 

struct kcvfhckp, 36 bytes                      @484 

   struct kcvcpscn, 8 bytes                    @484 

      ub4 kscnbas                            @484       0x001d14ed 

      ub2 kscnwrp                            @488       0x0000 

ub4 kcvcptim                              @492       0x319eb358 

   ub2 kcvcpthr                               @496       0x0001 

   union u, 12 bytes                           @500 

      struct kcvcprba, 12 bytes                  @50 0 

         ub4 kcrbaseq                         @500       0x00000021 

         ub4 kcrbabno                         @504       0x000002e4 

         ub2 kcrbabof                          @508       0x0010 

   ub1 kcvcpetb[0]                             @512       0x02 

   ub1 kcvcpetb[1]                             @513       0x00 

   ub1 kcvcpetb[2]                             @514       0x00 

   ub1 kcvcpetb[3]                             @515       0x00 

   ub1 kcvcpetb[4]                             @516       0x00 

   ub1 kcvcpetb[5]                             @517       0x00 

   ub1 kcvcpetb[6]                             @518       0x00 

   ub1 kcvcpetb[7]                             @519       0x00 

BBED> p kcvfhcpc 

ub4 kcvfhcpc                                 @140       0x0000013a 

BBED> p kcvfhccc 

ub4 kcvfhccc                                 @148       0x00000139 



 5.2   users01.dbf  로  변경  후  정보확인 

BBED> set filename '/app/oracle/oradata/testdb/users01.dbf' 

        FILENAME         /app/oracle/oradata/testdb/ users01.dbf 

BBED> p kcvfhckp 

struct kcvfhckp, 36 bytes                       @484

   struct kcvcpscn, 8 bytes                     @484

      ub4 kscnbas                            @484       0x001d0e68 

      ub2 kscnwrp                            @488       0x0000 

   ub4 kcvcptim                              @492       0x319ea534 

   ub2 kcvcpthr                               @496       0x0001 

   union u, 12 bytes                           @500 

      struct kcvcprba, 12 bytes                  @50 0 

         ub4 kcrbaseq                         @500       0x0000001a 

         ub4 kcrbabno                         @504       0x00000107 

         ub2 kcrbabof                          @508       0x0010 

   ub1 kcvcpetb[0]                              @512       0x02 

   ub1 kcvcpetb[1]                              @513       0x00 

   ub1 kcvcpetb[2]                              @514       0x00 

   ub1 kcvcpetb[3]                              @515       0x00 

   ub1 kcvcpetb[4]                              @516       0x00 

   ub1 kcvcpetb[5]                              @517       0x00 

   ub1 kcvcpetb[6]                              @518       0x00 

   ub1 kcvcpetb[7]                              @519       0x00 

BBED> p kcvfhcpc 

ub4 kcvfhcpc                                 @140       0x0000012b 

BBED> p kcvfhccc 

ub4 kcvfhccc                                 @148       0x0000012a 


5.3   users01.dbf  의  내용을  system01.dbf  와  동일하게  변경한다. 

BBED> m   /x   ed141d00   dba 4,1   offset   484 

BBED-00209: invalid number (ed141d00)   <--  에러  발생할  경우  아래와  같이  하세요 

BBED> m   /x   ed14   dba 4,1   offset   484 

BBED> set   offset   +2 

BBED> m   /x   1d00 

BBED> m   /x   58b39e31   dba 4,1   offset   492 

Warning: contents of previous BIFILE will be lost. Proceed? (Y/N) Y

 File: /app/oracle/oradata/testdb/users01.dbf (4) 

 Block: 1                 Offsets:   492 to 1003            Dba:0x01000001 

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

 58b39e31 01000000 1a000000 07010000 10000000 02000000 00000000 00000000 

 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 

 (중간  내용  생략) 

 <32 bytes per line> 


BBED> m   /x   3a010000   dba   4,1   offset   140 

 File: /app/oracle/oradata/testdb/users01.dbf (4) 

 Block: 1                 Offsets:   140 to   651            Dba:0x01000001 

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

 3a010000 85b39e31 2a010000 6b3f1a00 00000000 3da35e30 01003500 32000000 

 c24c0000 10000000 02000000 00000000 00000000 00000000 00000000 00000000 

(  중간  내용  생략  ) 

 <32 bytes per line> 


BBED> m   /x   39010000   dba   4,1   offset   148 

 File: /app/oracle/oradata/testdb/users01.dbf (4) 

 Block: 1                 Offsets:   148 to   659            Dba:0x01000001 

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

 39010000 6b3f1a00 00000000 3da35e30 01003500 32000000 c24c0000 10000000 

 02000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 

(중간  내용  생략) 

 <32 bytes per line> 


BBED> sum dba 4,1 apply 

Check value for File 4, Block 1: 

current = 0x3e95, required = 0x3e95 



Step 6. SQLPLUS  에서  recovery  해서  Open  합니다. 

SYS>recover datafile '/app/oracle/oradata/testdb/users01.dbf' ; 

Media recovery complete. 

SYS>alter database open; 

Database altered. 


정상적으로  잘  Open  되는  것이  확인됩니다. 

지면  관계상  모두  언급할  수는  없지만  여기서  살펴  본  것  외에도  일반적인  방법으로  복구를  할 수  없는  아주  다양한  경우를  해결할  수  있습니다. 

혹시라도  일반적인  방법으로  살려  낼  수  없어서  BBED  를  사용해서라도  시도를  해  보고  싶은 분 들은  저자에게  연락을  해  주세요.  

다시  한번  더  강조하지만  BBED  라는  방법은  잘  못  사용될  경우  완전히  복구가  불가  한  더 큰  문제를  만들  수  있으므로  아주  주의해야  합니다!! 

그리고  반드시  기억  하셔야  할  것은  사람도  병원이  있다고  해도  평소에  건강관리  잘해서  아프지 않는  것이  가장  최선이듯이  

평상시에  백업을  아주  철저히  하시길  당부  드립니다.


 

반응형