실수로 데이터를 삭제한 것을, 오라클에서는 user error라고 하여 에러종류중 하나로 취급한다.
밑에서 언급되는 삭제된 데이터는 user error에 인한 것으로 묵시적으로 취급할 것이다.
로그마이너는 대충 다음과 같은 기능을 수행할 수 있다.
테이블 데이터를 delete한 사용자 파악
삭제한 데이터를 검출하여 복구
DML문장을 수행한 사용자와 실행된 순서 파악
활동이 많은 테이블(디스크 액세스 분석정보) 파악
[예제]
아래의 파라메터를 확인하여 비어있는경우 지정해준다
utl_file_dir=C:oracleoradatawork
alter system set utl_file_dir='C:oracleoradatawork' deferred scope=spfile;
이와같이 한 후 오라클을 다시기동시키면 적용됨
SQL> connect sys
연결되었습니다.
SQL> @?/rdbms/admin/dbmslm.sql
패키지가 생성되었습니다.
권한이 부여되었습니다.
dbmslmd.sql파일의 varchar2(513)인 컬럼을 varchar2(1000)으로 변경한 다음, 실행
SQL> @?/rdbms/admin/dbmslmd.sql
패키지가 생성되었습니다.
패키지 본체가 생성되었습니다.
오류가 없음.
권한이 부여되었습니다.
[일반유저에서 테스트할 DML을 수행]
SQL> create table test ( id varchar(10), name varchar(10));
테이블이 생성되었습니다.
SQL> insert into test values('maddog', '강명규');
1 개의 행이 만들어졌습니다.
SQL> insert into test values('superman', '슈퍼맨');
1 개의 행이 만들어졌습니다.
SQL> commit;
커밋이 완료되었습니다.
SQL>
[다시 sys유저에서]
이미 logmnr_dic.ora파일이 존재한다면 EOF에러가 발생하므로, 먼저 삭제한 다음 해야한다.
그리고, 분석할 객체(테이블,.. 여기서는 kang의 test테이블이 될 것이다.)를 먼저 생성한 후 실행해주는 것이 좋다.
아니면, v_logmnr_contents의 seg_name, seg_type컬럼값이 표시되지 않는다.
SQL> exec dbms_logmnr_d.build('logmnr_dic.ora', 'C:oracleoradatawork');
SQL> select member from v$logfile;
MEMBER
--------------------------------------------------------------------------------
C:ORACLEORADATAMADDOGREDO01.LOG
C:ORACLEORADATAMADDOGREDO02.LOG
C:ORACLEORADATAMADDOGREDO03.LOG
SQL> exec dbms_logmnr.add_logfile('C:ORACLEORADATAMADDOGREDO01.LOG', dbms_logmnr.NEW);
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL> exec dbms_logmnr.add_logfile('C:ORACLEORADATAMADDOGREDO02.log', dbms_logmnr.ADDFILE);
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL> exec dbms_logmnr.add_logfile('C:ORACLEORADATAMADDOGREDO03.log', dbms_logmnr.ADDFILE);
PL/SQL 처리가 정상적으로 완료되었습니다.
SQL> exec dbms_logmnr.start_logmnr(dictfilename=> 'C:oracleoradataworklogmnr_dic.ora');
PL/SQL 처리가 정상적으로 완료되었습니다.
이제, kang에서 insert한 작업에 대한 것을 v$logmnr_contents뷰를 통해 알아보자.
SQL> set linesize 200
SQL> col operation format a10
SQL> col sql_redo format a40
SQL> col sql_undo format a40
SQL> select operation, sql_redo, sql_undo
2 from v$logmnr_contents
3 where
4 seg_owner='KANG' and seg_name='TEST' and
5 operation='INSERT' and username='KANG';
OPERATION SQL_REDO SQL_UNDO
---------- ---------------------------------------- ----------------------------------------
INSERT insert into "KANG"."TEST"("ID","NAME") v delete from "KANG"."TEST" where "ID" = '
alues ('maddog','강명규'); maddog' and "NAME" = '강명규' and ROWID
= 'AAAAxnAADAAAAADAAA';
INSERT insert into "KANG"."TEST"("ID","NAME") v delete from "KANG"."TEST" where "ID" = '
alues ('superman','슈퍼맨'); superman' and "NAME" = '슈퍼맨' and ROWI
D = 'AAAAxnAADAAAAADAAB';
테이블 소유자가 KANG이고, 테이블명이 TEST, KANG이란 유저가 INSERT한 레코드를 찾는 것이다.
SQL_REDO에서는 작업한 내용이 표시되고, SQL_UNDO에는 취소할 수 있는 SQL문이 표시된다.
즉, SQL_REDO와 대응되는 SQL_UNDO는 실행한 작업을 되돌릴 수 있게 한다.
위에서는 ROWID가 ROW를 식별하기 위한 조건으로 표시되고 있는데, 실제 ROWID를 확인해 보자.
[KANG유저에서 실행]
SQL> SELECT ROWID, TEST.* FROM TEST;
ROWID ID NAME
------------------ ---------- ----------
AAAAxnAADAAAAADAAA maddog 강명규
AAAAxnAADAAAAADAAB superman 슈퍼맨
그럼, 실수로 테이블데이터를 삭제했을때의 시나리오를 생각해 보자.
[KANG유저에서 실행]
SQL> delete from test;
2 행이 삭제되었습니다.
SQL> commit;
커밋이 완료되었습니다.
위에서 test에 있는 모든 데이터를 삭제했고, commit까지 했다.
어떻게 복구할 것인가?
v_logmnr_contents뷰에서 delete operation을 검색하여 나온 row의 sql_undo컬럼값으로 실행하면 될 것이다.
SQL> select operation, sql_redo, sql_undo
2 from v$logmnr_contents
3 where
4 seg_owner='KANG' and seg_name='TEST' and
5 operation='DELETE' and username='KANG';
OPERATION SQL_REDO SQL_UNDO
---------- ---------------------------------------- ----------------------------------------
DELETE delete from "KANG"."TEST" where "ID" = ' insert into "KANG"."TEST"("ID","NAME") v
maddog' and "NAME" = '강명규' and ROWID alues ('maddog','강명규');
= 'AAAAxnAADAAAAADAAA';
DELETE delete from "KANG"."TEST" where "ID" = ' insert into "KANG"."TEST"("ID","NAME") v
superman' and "NAME" = '슈퍼맨' and ROWI alues ('superman','슈퍼맨');
D = 'AAAAxnAADAAAAADAAB';
sql_undo컬럼값을 수행해 주자.
복구끝.
SQL> insert into "KANG"."TEST"("ID","NAME") values ('maddog','강명규');
1 개의 행이 만들어졌습니다.
SQL> insert into "KANG"."TEST"("ID","NAME") values ('superman','슈퍼맨');
1 개의 행이 만들어졌습니다.
SQL> commit;
커밋이 완료되었습니다.
SQL> select * from kang.test;
ID NAME
---------- ----------
superman 슈퍼맨
maddog 강명규
SQL>
|