動手為王——利用logminer挖掘日誌恢復誤操作

kunlunzhiying發表於2017-07-31


挖掘日誌恢復誤操作

1 介紹:

LogMinerOracle資料庫提供的一個工具,它用於分析重做日誌和歸檔日誌所記載的事務操作。

Logmineroracle8i開始提供的用於分析重做日誌資訊的工具,它包括DBMS_LOGMNRDBMS_LOGMNR_D兩個package。它既能分析redo log file,也能分析歸檔後的archive log file。在分析日誌的過程中需要使用資料字典,一般先生成資料字典檔案後使用,10g版本還可以使用線上資料字典。

Logminer也可以分析其它資料庫的重做日誌檔案,但是必須使用重做日誌所在資料庫的資料字典,否則會出現無法識別的亂碼。另外被分析資料庫的作業系統平臺最好和當前Logminer所在資料庫的執行平臺一樣,且block size相同。

 

LogMiner的功能

1)確定資料庫的邏輯損壞時間

透過LogMiner可以準確定位該誤操作的執行時間和SCN值,然後透過基於時間恢復或者基於SCN恢復可以完全恢復該表資料。

 SQL> select scn_to_timestamp(2599788) from dual;

scn_to_timestamp(2599788)

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

2016-05-01 06:06:01

 

SQL>select timestamp_to_scn(to_timestamp('2016-5-1 6:06:06','yyyy-mm-dd hh24:mi:ss')) FROM dual;

TIMESTAMP_TO_SCN(TO_TIMESTAMP('2016-5-16:06:06','YYYY-MM-DDHH24:MI:SS'))

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

                                                                 2599788

2)確定事務級要執行的精細邏輯恢復操作

透過LogMiner可以取得任何使用者的DML操作及相應的UNDO操作,透過執行UNDO操作可以取消使用者的錯誤操作。

3)執行後續審計

透過LogMiner可以跟蹤Oracle資料庫的所有DMLDDLDCL操作,從而取得執行這些操作的時間順序、執行這些操作的使用者等資訊。

 

追加日誌

  重做日誌用於實現例程恢復和介質恢復,這些操作所需要的資料被自動記錄在重做日誌中。但是,重做應用可能還需要記載其他列資訊到重做日誌中,記錄其他列的日誌過程被稱為追加日誌。

  預設情況下,Oracle資料庫沒有開啟追加日誌,從而導致預設情況下LogMiner無法支援以下特徵:

  1)索引簇、鏈行和遷移行;

  2)直接路徑插入;

  3)摘取LogMiner字典到重做日誌;

  4)跟蹤DDL

  5)生成鍵列的SQL_REDOSQL_UNDO資訊;

  6LONGLOB資料型別。

 

 

----如何修改追加日誌資料模式:

SYS@test> select supplemental_log_data_min from v$database;

SUPPLEME

--------

NO

 

SYS@test> alter database add supplemental log data;

Database altered.

 

SYS@test> select supplemental_log_data_min from v$database;

SUPPLEME

--------

YES

----關閉追加日誌

SYS@test> alter database drop supplemental log data;

Database altered.

 

SYS@test> select supplemental_log_data_min from v$database;

SUPPLEME

--------

NO

2環境準備(資料誤delete後並commit)

SYS@test> create user shall identified by shall;

User created.

SYS@test> grant connect,resource to shall;

Grant succeeded.

 

SHALL@test> create table test(id number,name varchar2(20));

Table created.

SHALL@test> begin

  2  for i in 1..100000 loop

  3  insert into test values(i,'zhong');

  4  end loop;

  5  commit;

  6  end;

  7  /

PL/SQL procedure successfully completed.

 

 

SHALL@test> select count(*) from test;

  COUNT(*)

----------

    100000

 

SHALL@test> select * from test where id = 999;

        ID NAME

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

       999 zhong

 

SHALL@test> delete test;

100000 rows deleted.

 

SHALL@test> commit;

Commit complete.

 

SHALL@test> select * from test;

no rows selected

3開始資料探勘找回已提交的刪除資料

1)資料庫是關閉追加日誌狀態:

SYS@test> select supplemental_log_data_min from v$database;

SUPPLEME

--------

NO

2)查詢庫redo位置

SYS@test> select member from v$logfile;

MEMBER

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

/u01/app/oracle/oradata/orcl/redo01_1.log

/u01/app/oracle/oradata/orcl/redo02_1.log

/u01/app/oracle/oradata/orcl/redo03_1.log

3)生成日誌挖掘佇列

SYS@test> exec dbms_logmnr.add_logfile ('/u01/app/oracle/oradata/orcl/redo01_1.log');

PL/SQL procedure successfully completed.

 

SYS@test> exec dbms_logmnr.add_logfile ('/u01/app/oracle/oradata/orcl/redo02_1.log');

PL/SQL procedure successfully completed.

 

SYS@test> exec dbms_logmnr.add_logfile ('/u01/app/oracle/oradata/orcl/redo03_1.log');

PL/SQL procedure successfully completed.

 

----如果剛做了誤操作,日誌未切換,可以只新增當前redo

SYS@test> select group#,status from v$log;

    GROUP# STATUS

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

         1 INACTIVE

         2 INACTIVE

         3 CURRENT

SYS@test> col member for a50

SYS@test> select group#,member,type from v$logfile;

    GROUP# MEMBER                                             TYPE

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

         1 /u01/app/oracle/oradata/orcl/redo01_1.log          ONLINE

         2 /u01/app/oracle/oradata/orcl/redo02_1.log          ONLINE

         3 /u01/app/oracle/oradata/orcl/redo03_1.log          ONLINE

4)開始挖掘

SYS@test> exec dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);

PL/SQL procedure successfully completed.

5)從v$logmnr_contents查前滾SQL和反算回來的回滾SQL

SYS@test> select sql_redo from v$logmnr_contents where lower(sql_redo) like '%delete%' and seg_name='TEST';

 

redo資料如下:

SQL_REDO

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

delete from "SHALL"."TEST" where "ID" = '42016' and "NAME" = 'zhong' and ROWID =

 'AAAWGEAAEAAAOSfABL';

delete from "SHALL"."TEST" where "ID" = '42017' and "NAME" = 'zhong' and ROWID =

 'AAAWGEAAEAAAOSfABM';

delete from "SHALL"."TEST" where "ID" = '42018' and "NAME" = 'zhong' and ROWID =

 'AAAWGEAAEAAAOSfABN';

delete from "SHALL"."TEST" where "ID" = '42019' and "NAME" = 'zhong' and ROWID =

 

 

undo資料如下:

SYS@test> select sql_redo from v$logmnr_contents where lower(sql_undo) like '%delete%' and seg_name='TEST';

SQL_REDO

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

insert into "SHALL"."TEST"("ID","NAME") values ('5039','zhong');

insert into "SHALL"."TEST"("ID","NAME") values ('5040','zhong');

insert into "SHALL"."TEST"("ID","NAME") values ('5041','zhong');

insert into "SHALL"."TEST"("ID","NAME") values ('5042','zhong');

insert into "SHALL"."TEST"("ID","NAME") values ('5043','zhong');

insert into "SHALL"."TEST"("ID","NAME") values ('5044','zhong');

insert into "SHALL"."TEST"("ID","NAME") values ('5045','zhong');

insert into "SHALL"."TEST"("ID","NAME") values ('5046','zhong');

 

 

SYS@test> set linesize 200

SYS@test> set pagesize 10000

SYS@test> create table shall as select sql_redo from v$logmnr_contents where lower(sql_undo) like '%delete%' and seg_name='TEST';

SYS@test> select * from shall;


6)最後結束挖掘:

SYS@test> EXECUTE DBMS_LOGMNR.END_LOGMNR;

PL/SQL procedure successfully completed.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28211342/viewspace-2142828/,如需轉載,請註明出處,否則將追究法律責任。

相關文章