oracle資料庫災難挽救應急方案之DML誤操作恢復

龍山游龍發表於2022-10-20

1核心業務表誤delete恢復

1.1模擬delete誤操作

建立jason業務表,如下:

SQL> create table jason as select * from dba_objects;
SQL> create index idx_jason_oid on jason(object_id);

刪除jason業務表部分資料,在提交之後,發現部分資料存在誤刪,如下:

SQL> delete from jason where object_id between 3000 and 6000;
3001 rows deleted.

1.2閃回查詢恢復誤刪資料

首先,檢查當前時間和undo保留時間,如下:

SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
SQL> select sysdate from dual;
SYSDATE
-------------------
2022-05-06 23:29:07
SQL> show parameter undo_retention
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
undo_retention                       integer     900

根據時間戳執行閃回查詢,檢查資料能否被找回,如下:

SQL> select count(*) from sys.jason as of timestamp to_timestamp('2022-05-06 23:14:07','yyyy-mm-dd hh24:mi:ss') where object_id between 3000 and 6000;
  COUNT(*)
----------
      3001

如果資料確認可以被找回來,立即將undo中前映象資料插回至jason業務表,如下:

SQL> insert into jason select * from sys.jason as of timestamp to_timestamp('2022-05-06 23:14:07','yyyy-mm-dd hh24:mi:ss') where object_id between 3000 and 6000;
3001 rows created.

如果資料無法透過undo閃回查詢找到,則嘗試1.1.3節方案進行資料挽救。

SQL> select count(*) from sys.jason as of timestamp to_timestamp('2022-05-06 23:14:07','yyyy-mm-dd hh24:mi:ss') where object_id between 3000 and 6000;
ERROR at line 1:
ORA-01555: snapshot too old: rollback segment number 7 with name
"_SYSSMU7_2329891355$" too small

1.3歸檔日誌挖掘恢復誤刪資料

檢查資料庫全域性force_logging和supplemental_log_data_min特性是否開啟,如下:

SQL> select name,open_mode,log_mode,force_logging,supplemental_log_data_min from v$database;
NAME      OPEN_MODE            LOG_MODE     FORCE_LOGGING   SUPPLEMENTAL_LOG_DATA_MIN
--------- -------------------- ------------ --------------- -------------------------
TESTDB19  READ WRITE           ARCHIVELOG   NO              NO

手動切換歸檔日誌,並記錄當前時間,如下:

SQL> alter system switch logfile;
SQL> select sysdate from dual;
SYSDATE
-------------------
2022-05-06 23:58:35

檢查資料誤刪除期間產生的歸檔日誌檔案,如下:

select unique NAME, THREAD#, SEQUENCE#, COMPLETION_TIME
  from gv$archived_log
 where thread# = 1
   and COMPLETION_TIME >=
       to_date('2022-05-07 03:09:24', 'yyyy-mm-dd hh24:mi:ss')
   and COMPLETION_TIME <=
       to_date('2022-05-07 03:11:19', 'yyyy-mm-dd hh24:mi:ss')
 order by SEQUENCE#;

新增第一個要載入的歸檔日誌檔案,如下:

SQL> execute dbms_logmnr.add_logfile(logfilename=>'/oracle/app/fast_recovery_area/TESTDB19C/archivelog/2022_05_07/o1_mf_1_134_k7d6w2g6_.arc',options=>dbms_logmnr.new);

多次新增要載入的歸檔日誌檔案,如下:

SQL> execute dbms_logmnr.add_logfile(logfilename=>'/oracle/app/fast_recovery_area/TESTDB19C/archivelog/2022_05_07/o1_mf_1_135_k7d6wo28_.arc',options=>dbms_logmnr.addfile);

執行日誌挖掘分析,如下:

SQL> execute dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);

查詢v$logmnr_contents動態效能檢視,獲取歸檔日誌解析資訊,如下:

SQL> select count(*) from v$logmnr_contents;
  COUNT(*)
----------
    391721
SQL> create table sys.hzmc_logmnr_contents as select * from v$logmnr_contents;

關閉日誌挖掘分析,如下:

SQL> execute dbms_logmnr.end_logmnr;

將誤刪除操作的反向插入語句輸出至jason_insert.sql,如下:

SQL> set lines 1000 pages 0
SQL> spool jason_insert.sql
SQL> select sql_undo from sys.hzmc_logmnr_contents where OPERATION='DELETE' and sql_redo like '%JASON%';
SQL> spool off

清理jason_insert.sql文字中的首行和尾行,如下:

shell> vi jason_insert.sql

將反向解析出來的SQL語句插回至jason業務表,如下:

SQL> @jason_insert.sql

2、核心業務表誤update恢復

2.1模擬update誤操作

建立jason業務表,如下:

SQL> create table jason as select * from dba_objects;
SQL> create index idx_jason_oid on jason(object_id);

更新jason業務表部分資料,在提交之後,發現部分資料存在誤更新,如下:

SQL> update jason set object_id=1 where object_id<=70000;
69346 rows updated.
SQL> commit;

2.2閃回查詢恢復誤刪資料

首先,檢查當前時間和undo保留時間,如下:

SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
SQL> select sysdate from dual;
SYSDATE
-------------------
2022-05-07 06:13:38
SQL> show parameter undo_retention
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
undo_retention                       integer     900

根據時間戳執行閃回查詢,檢查資料能否被找回,如下:

SQL> select count(*) from sys.jason as of timestamp to_timestamp('2022-05-07 06:12:38','yyyy-mm-dd hh24:mi:ss') where object_id<=70000;
  COUNT(*)
----------
     69346

如果資料確認可以被找回來,先建立jason業務表的備份jason_old,再基於閃回資料建立新業務表jason_new,然後立即刪除jason業務表誤更新的資料,再將undo中前映象資料插回至jason表,如下:

SQL> create table jason_old as select * from jason;
SQL> create table jason_new as select * from jason where 1=2;
SQL> insert into jason_new select * from sys.jason as of timestamp to_timestamp('2022-05-07 06:12:38','yyyy-mm-dd hh24:mi:ss') where object_id<=70000;
69346 rows created.
SQL> commit;
SQL> delete from jason where object_id<=70000;
SQL> commit;
SQL> insert into jason select * from jason_new;
69346 rows created.
SQL> commit;

如果資料無法透過undo閃回查詢找到,則嘗試1.2.3節方案進行資料挽救。

SQL> select count(*) from sys.jason as of timestamp to_timestamp('2022-05-07 06:12:38','yyyy-mm-dd hh24:mi:ss') where object_id<=70000;
ERROR at line 1:
ORA-01555: snapshot too old: rollback segment number 7 with name
"_SYSSMU7_2329891355$" too small

2.3歸檔日誌挖掘恢復誤刪資料

檢查資料庫全域性force_logging和supplemental_log_data_min特性是否開啟,如下:

SQL> select name,open_mode,log_mode,force_logging,supplemental_log_data_min from v$database;
NAME      OPEN_MODE            LOG_MODE     FORCE_LOGGING   SUPPLEMENTAL_LOG_DATA_MIN
--------- -------------------- ------------ --------------- -------------------------
TESTDB19  READ WRITE           ARCHIVELOG   NO              NO

手動切換歸檔日誌,並記錄當前時間,如下:

SQL> alter system switch logfile;
SQL> select sysdate from dual;
SYSDATE
-------------------
2022-05-07 06:34:09

檢查資料誤刪除期間產生的歸檔日誌檔案,如下:

select unique NAME, THREAD#, SEQUENCE#, COMPLETION_TIME
  from gv$archived_log
 where thread# = 1
   and COMPLETION_TIME >=
       to_date('2022-05-07 06:12:38', 'yyyy-mm-dd hh24:mi:ss')
   and COMPLETION_TIME <=
       to_date('2022-05-07 06:34:09', 'yyyy-mm-dd hh24:mi:ss')
 order by SEQUENCE#;

新增第一個要載入的歸檔日誌檔案,如下:

SQL> execute dbms_logmnr.add_logfile(logfilename=>'/oracle/app/fast_recovery_area/TESTDB19C/archivelog/2022_05_07/o1_mf_1_137_k7dlrmqx_.arc',options=>dbms_logmnr.new);

多次新增要載入的歸檔日誌檔案,如下:

SQL> execute dbms_logmnr.add_logfile(logfilename=>'/oracle/app/fast_recovery_area/TESTDB19C/archivelog/2022_05_07/o1_mf_1_138_k7dlrtnr_.arc',options=>dbms_logmnr.addfile);

執行日誌挖掘分析,如下:

SQL> execute dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);

查詢v$logmnr_contents動態效能檢視,獲取歸檔日誌解析資訊,如下:

SQL> select count(*) from v$logmnr_contents;
  COUNT(*)
----------
    345231
SQL> create table sys.hzmc_logmnr_contents as select * from v$logmnr_contents;

關閉日誌挖掘分析,如下:

SQL> execute dbms_logmnr.end_logmnr;

將誤刪除操作的反向插入語句輸出至jason_insert.sql,如下:

SQL> set lines 1000 pages 0
SQL> spool jason_update.sql
select sql_undo
  from sys.hzmc_logmnr_contents
 where OPERATION = 'UPDATE'
   and sql_redo like '%JASON%'
   and TIMESTAMP >= to_date('2022-05-07 06:12:38', 'yyyy-mm-dd hh24:mi:ss')
   and TIMESTAMP <= to_date('2022-05-07 06:34:09', 'yyyy-mm-dd hh24:mi:ss');
SQL> spool off

清理jason_update.sql文字中的首行和尾行,如下:

shell> vi jason_update.sql

將反向解析出來的SQL語句插回至jason業務表,如下:

SQL> @jason_update.sql


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

相關文章