Oracle/백업&복구

2012.02.09 백업&복구 7번째 (Log Miner, Redo log 장애복구) ; redo log장애복구 시나리오 1개

에몽이ㅋ 2012. 2. 12. 22:03
Log Miner란? (8i 이상에서만)
Redo log file과 Archive log file들은 binary file이라서 어떤 작업을 해줬는지 알 수 없습니다. 이러한 불편함때문에 생긴 기능이 log miner인데,
log miner를 사용하게 되면, view가 생성이 되어서 어떤 작업을 했는지 알 수가 있게 됩니다.
한마디로, Redo log 및 Archive log file들을 분석해주는 기능입니다.

Log miner 사용하기 전에
1. parameter에 utl_file_dir 추가하기
mkdir /home/oracle/logmnr
vi $ORACLE_HOME/dbs/inittestdb.ora
  utl_file_dir=/home/oracle/logmnr/  << 라인추가


2. DB가 supplemental logging이 ENABLE되지 않은 상태로 운영하게 되면,
redo에 일부 필수적인 내용들만 기록하기 때문에 log miner를 사용하기가 힘듭니다.


supplemental logging 활성화하기
SQL> select SUPPLEMENTAL_LOG_DATA_MIN from v$database;

SUPPLEME
--------
NO

SQL> alter database add supplemental log data;
(비활성화는 add대신에 drop입니다)

Database altered.

SQL> select SUPPLEMENTAL_LOG_DATA_MIN from v$database;

SUPPLEME
--------
YES

** ORACLE기본값이 DISABLE이므로, 항상 DB를 설치한 후 ENABLE해주세요.
기본값이 disable인 이유는, enable일때보다 log가 좀 더 많이 생성이 되는데, 성능에는 많이 차이가 없습니다.
enable하시고 운영하세요.



LOG MINER사용하기
1. parameter에 utl_file_dir 추가하기
SQL> show parameter utl

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
create_stored_outlines               string
utl_file_dir                         string      /backup/logmnr  << param. file에 utl_file_dir 라인 추가한 후 DB껏다키셔야 합니다.
(해당 파라미터는 ISSYS_MODIFIABLE=FALSE이므로 alter system set으로 dynamic하게 적용이 안됩니다.)

2. supplemental log 활성화하기
SQL> alter database add supplemental log data;

3. log miner가 사용하는 dictionary file 생성하기
SQL> exec dbms_logmnr_d.build('filename.dat', '/directory');

4. 분석하기를 원하는 log file 등록하기
( 대량의 파일을 등록할 때 
http://gyh214.tistory.com/97 참고 )

SQL> exec dbms_logmnr.add_logfile('/filename.log', 1);

* Archive log file도 등록이 가능합니다.
** 마지막 숫자 의미
1 : 신규등록
2 : 등록했던 파일 삭제
3 : 추가등록 


5. 등록한 logfile 분석하기
SQL> exec dbms_logmnr.start_logmnr(dictfilename=> '/directory/filename.dat');

*분석시 옵션
dictfilename
starttime, endtime
options
startscn, endscn


(예제 :
exec dbms_logmnr.start_logmnr(dictfilename=> '/directory/filename.dat', startscn=>880000, endscn=>890000, 
exec dbms_logmnr.start_logmnr(dictfilename=> '/directory/filename.dat', options=> dbms_logmnr.committed_data_only);


6. 원하는 자료 뽑아서 보기 
6-1. 어떤 파일이 등록되었나 살펴보기

SQL> select filename from v$logmnr_logs;

6-2. 로그파일안에 들어있는, 내가 예전에 어떤 작업을 했나 살펴보기 (v$logmnr_contents 이용하세요)
(timestamp 조회 시 
alter session set nls_date_format='RRRR-MM-DD:HH24:MI:SS';
를 먼저 실행 하신 후 조회하시면 좀더 편합니다.)
SQL> desc v$logmnr_contents;
 Name                    Null?    Type
 ----------------------- -------- ----------------
 SCN                              NUMBER
 CSCN                             NUMBER
 TIMESTAMP                        DATE    << SQL명령 쳤을당시 시간
 COMMIT_TIMESTAMP                 DATE
 THREAD#                          NUMBER
 LOG_ID                           NUMBER
 XIDUSN                           NUMBER
 XIDSLT                           NUMBER
 XIDSQN                           NUMBER
 PXIDUSN                          NUMBER
 PXIDSLT                          NUMBER
 PXIDSQN                          NUMBER
 RBASQN                           NUMBER
 RBABLK                           NUMBER
 RBABYTE                          NUMBER
 UBAFIL                           NUMBER
 UBABLK                           NUMBER
 UBAREC                           NUMBER
 UBASQN                           NUMBER
 ABS_FILE#                        NUMBER
 REL_FILE#                        NUMBER
 DATA_BLK#                        NUMBER
 DATA_OBJ#                        NUMBER
 DATA_OBJD#                       NUMBER
 SEG_OWNER                        VARCHAR2(32)      << username과 유사
 SEG_NAME                         VARCHAR2(256)
 TABLE_NAME                       VARCHAR2(32)      << SQL이 적용된 table name
 SEG_TYPE                         NUMBER
 SEG_TYPE_NAME                    VARCHAR2(32)
 TABLE_SPACE                      VARCHAR2(32)
 ROW_ID                           VARCHAR2(18)
 SESSION#                         NUMBER
 SERIAL#                          NUMBER
 USERNAME                         VARCHAR2(30)      << 명령을 쳤을당시 username
 SESSION_INFO                     VARCHAR2(4000)
 TX_NAME                          VARCHAR2(256)
 ROLLBACK                         NUMBER
 OPERATION                        VARCHAR2(32)      << 어떤 DML,DDL인지 출력합니다.
 OPERATION_CODE                   NUMBER
 SQL_REDO                         VARCHAR2(4000)      << 내가 정확하게 어떤 명령을 쳤는지 출력합니다.
 SQL_UNDO                         VARCHAR2(4000)
 RS_ID                            VARCHAR2(32)
 SEQUENCE#                        NUMBER
 SSN                              NUMBER
 CSF                              NUMBER
 INFO                             VARCHAR2(32)
 STATUS                           NUMBER
 REDO_VALUE                       NUMBER
 UNDO_VALUE                       NUMBER
 SQL_COLUMN_TYPE                  VARCHAR2(30)
 SQL_COLUMN_NAME                  VARCHAR2(30)
 REDO_LENGTH                      NUMBER
 REDO_OFFSET                      NUMBER
 UNDO_LENGTH                      NUMBER
 UNDO_OFFSET                      NUMBER
 DATA_OBJV#                       NUMBER
 SAFE_RESUME_SCN                  NUMBER
 XID                              RAW(8)
 PXID                             RAW(8)
 AUDIT_SESSIONID                  NUMBER

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

Redo log file 관련 장애복구하기

(그림출처 : http://dinggur.tistory.com/160 ) 




(그림출처 : 
 http://jigi.net/4241 ) 

-------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------- 
------------------------------------------------------------------------------------------------------------------- 
-------------------------------------------------------------------------------------------------------------------  
전체 redolog가 삭제된 경우, DB가 shutdown abort종료 & 백업이 존재하지 않음

고찰 : 
1. DB가 shutdown abort되었으므로, datafile들간의 SCN이 맞지 않을 것이다.
(최후의 방법으로 _allow_resetlogs_corruption 사용)
2. 백업이 존재하지 않으므로, 현재 datafile들을 최대한 살려야 한다.
3. 만약에 No archivelog mode이면, Active, Current인 redo안에 있던 내용들은 어쩔 수 없이 날라갈 수 밖에 없다.
4. shutdown abort인지 immediate인지는 alert log에서 맨 밑에서 위쪽으로 찾아서 보면
(vi에서 G누른 후 ?Shutting 으로 검색) Shutting down instance (abort) 인지 아닌지 나와있습니다.


1. 현재상태확인
SQL> @log

    GROUP# MEMBER                                         SEQUENCE# ARC STATUS
---------- --------------------------------------------- ---------- --- ----------------
         1 /home/oracle/oradata/testdb/redo01.log                 1 NO  CURRENT
         1 /home/oracle/oradata/testdb/redo01_b.log               1 NO  CURRENT
         2 /home/oracle/oradata/testdb/redo02.log                 0 YES UNUSED
         2 /home/oracle/oradata/testdb/redo02_b.log               0 YES UNUSED
         3 /home/oracle/oradata/testdb/redo03.log                 0 YES UNUSED
         3 /home/oracle/oradata/testdb/redo03_b.log               0 YES UNUSED

6 rows selected.


SQL> create table scott.redotest01 (no number);

Table created.

SQL> insert into scott.redotest01 values(1);

1 row created.

SQL> commit;

Commit complete.

SQL> @log

    GROUP# MEMBER                                         SEQUENCE# ARC STATUS
---------- --------------------------------------------- ---------- --- ----------------
         1 /home/oracle/oradata/testdb/redo01.log                 1 NO  CURRENT
         1 /home/oracle/oradata/testdb/redo01_b.log               1 NO  CURRENT
         2 /home/oracle/oradata/testdb/redo02.log                 0 YES UNUSED
         2 /home/oracle/oradata/testdb/redo02_b.log               0 YES UNUSED
         3 /home/oracle/oradata/testdb/redo03.log                 0 YES UNUSED
         3 /home/oracle/oradata/testdb/redo03_b.log               0 YES UNUSED

6 rows selected.

SQL> alter system switch logfile;

System altered.

SQL> insert into scott.redotest01 values(2);

1 row created.

SQL> commit;

Commit complete.

SQL> @log

    GROUP# MEMBER                                         SEQUENCE# ARC STATUS
---------- --------------------------------------------- ---------- --- ----------------
         1 /home/oracle/oradata/testdb/redo01.log                 1 YES ACTIVE
         1 /home/oracle/oradata/testdb/redo01_b.log               1 YES ACTIVE
         2 /home/oracle/oradata/testdb/redo02.log                 2 NO  CURRENT
         2 /home/oracle/oradata/testdb/redo02_b.log               2 NO  CURRENT
         3 /home/oracle/oradata/testdb/redo03.log                 0 YES UNUSED
         3 /home/oracle/oradata/testdb/redo03_b.log               0 YES UNUSED

6 rows selected.


2. 장애발생
SQL> !rm -v /home/oracle/oradata/testdb/redo*
removed `/home/oracle/oradata/testdb/redo01.log'
removed `/home/oracle/oradata/testdb/redo01_b.log'
removed `/home/oracle/oradata/testdb/redo02.log'
removed `/home/oracle/oradata/testdb/redo02_b.log'
removed `/home/oracle/oradata/testdb/redo03.log'
removed `/home/oracle/oradata/testdb/redo03_b.log'

SQL> alter system switch logfile;

System altered.

SQL> alter system switch logfile;

System altered.

SQL> alter system switch logfile;
alter system switch logfile
*
ERROR at line 1:
ORA-01013: user requested cancel of current operation



SQL> @log

    GROUP# MEMBER                                         SEQUENCE# ARC STATUS
---------- --------------------------------------------- ---------- --- ----------------
         1 /home/oracle/oradata/testdb/redo01.log                 4 NO  CURRENT
         1 /home/oracle/oradata/testdb/redo01_b.log               4 NO  CURRENT
         2 /home/oracle/oradata/testdb/redo02.log                 2 NO  INACTIVE
         2 /home/oracle/oradata/testdb/redo02_b.log               2 NO  INACTIVE
         3 /home/oracle/oradata/testdb/redo03.log                 3 NO  INACTIVE
         3 /home/oracle/oradata/testdb/redo03_b.log               3 NO  INACTIVE

6 rows selected.

SQL> shutdown abort
ORACLE instance shut down.


3. 해결하기
안전을 위해 임시DB로 전환후 

SQL> recover database until cancel;
ORA-00279: change 872468 generated at 02/12/2012 22:36:47 needed for thread 1
ORA-00289: suggestion : /backup/arc/1_4_775078606.dbf
ORA-00280: change 872468 for thread 1 is in sequence #4


Specify log: {=suggested | filename | AUTO | CANCEL}
cancel
ORA-01547: warning: RECOVER succeeded but OPEN RESETLOGS would get error below
ORA-01194: file 1 needs more recovery to be consistent
ORA-01110: data file 1: '/home/oracle/temp/system01.dbf'


ORA-01112: media recovery not started


SQL> alter database open resetlogs;
alter database open resetlogs
*
ERROR at line 1:
ORA-01194: file 1 needs more recovery to be consistent
ORA-01110: data file 1: '/home/oracle/temp/system01.dbf'
(shutdown abort로 꺼졌기 때문에 datafile들간의 일관성이 없음)
해결 : _allow_resetlogs_corruption=TRUE를 파라미터에 추가해줘서 강제로 SCN를 통일
SQL> shutdown
ORA-01109: database not open


Database dismounted.
ORACLE instance shut down.
SQL> !vi $ORACLE_HOME/dbs/inittestdb.ora
_allow_resetlogs_corruption=TRUE  << 라인추가

SQL> startup
ORACLE instance started.

Total System Global Area  167772160 bytes
Fixed Size                  1272600 bytes
Variable Size              96470248 bytes
Database Buffers           67108864 bytes
Redo Buffers                2920448 bytes
Database mounted.
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open


SQL> alter database open resetlogs;

Database opened.

SQL> @log

    GROUP# MEMBER                                         SEQUENCE# ARC STATUS
---------- --------------------------------------------- ---------- --- ----------------
         1 /home/oracle/temp/redo01.log                           1 NO  CURRENT
         1 /home/oracle/temp/redo01_b.log                         1 NO  CURRENT
         2 /home/oracle/temp/redo02.log                           0 YES UNUSED
         2 /home/oracle/temp/redo02_b.log                         0 YES UNUSED
         3 /home/oracle/temp/redo03.log                           0 YES UNUSED
         3 /home/oracle/temp/redo03_b.log                         0 YES UNUSED

6 rows selected.

SQL> select * from scott.redotest01;

        NO
----------
         1
         2