數據誤刪後如何使用Flashback恢復數據



Flashback Query

Flashback 是ORACLE 自9i 就開始提供的一項特性,在9i 中利用oracle 查詢多版本一致的特點,
實現從回滾段中讀取表一定時間內操作過的數據,可用來進行數據比對,或者修正意外提交造成的錯誤數據,該項特性也被稱爲Flashback Query。

一、Flashback Query
正如前言中所提,Flashback Query 是利用多版本讀一致性的特性從UNDO 表空間讀取操作前的記錄數據!


--什麼是多版本讀一致性:

Oracle 採用了一種非常優秀的設計,通過undo 數據來確保寫不堵塞讀,簡單的講,不同的事務在寫數據時,會將數據的前映像寫入undo 表空間,
這樣如果同時有其它事務查詢該表數據,則可以通過undo 表空間中數據的前映像來構造所需的完整記錄集,而不需要等待寫入的事務提交或回滾。

flashback query 有多種方式構建查詢記錄集,記錄集的選擇範圍可以基於時間或基於scn,甚至可以同時查詢出記錄在undo 表空間中不同事務時的前映象。
用法與標準查詢非常類似,要通過flashback query 查詢undo 中的撤銷數據,最簡單的方式只需要在標準查詢語句的表名後面跟上as of timestamp(基於時間)
或as of scn(基於scn)即可。as of timestamp|scn 的語法是自9iR2 後纔開始提供支持。


----實例測試:


1.as of timestamp 的示例
 
  17:05:08 scott@ORCL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
  
  Session altered.
  
  17:08:00 scott@ORCL> select sysdate from dual;
  
  SYSDATE
  -------------------
  2012-12-02 17:08:09
  
   
  17:08:09 scott@ORCL>  select * from test_ext;
  
  EMPLOYEE_ID FIRST_NAME LAST_NAME      JOB_ID     MANAGER_ID HIRE_DATE               SALARY COMMISSION_PCT DEPARTMENT_ID EMAIL
  ----------- ------------------------- ---------- ---------- ------------------- ---------- -------------- ------------- -------------------------
          360 Jane       Janus          ST_CLERK          121 2001-05-17 00:00:00       3000              0            50 jjanus
          361 Mark       Jasper         SA_REP            145 2001-05-17 00:00:00       8000             .1            80 mjasper
          362 Brenda     Starr          AD_ASST           200 2001-05-17 00:00:00       5500              0            10 bstarr
          363 Alex       Alda           AC_MGR            145 2001-05-17 00:00:00       9000            .15            80 aalda
          401 Jesse      Cromwell       HR_REP            203 2001-05-17 00:00:00       7000              0            40 jcromwel
          402 Abby       Applegate      IT_PROG           103 2001-05-17 00:00:00       9000             .2            60 aapplega
          403 Carol      Cousins        AD_VP             100 2001-05-17 00:00:00      27000             .3            90 ccousins
          404 John       Richardson     AC_ACCOUNT        205 2001-05-17 00:00:00       5000              0           110 jrichard
   
  ---模擬刪除數據
 
  17:08:23 scott@ORCL>  delete from test_ext;
  
  8 rows deleted.
  
  17:08:52 scott@ORCL> commit;
  
  Commit complete.                                         
  
  17:08:55 scott@ORCL>   select * from test_ext;
  
  no rows selected
     

  ---查看刪除之前的狀態

  --假設當前舉例刪除數據已經有5分鐘左右的時間(從實際測試的時間來看過了不到一分鐘)

   
  17:11:10 scott@ORCL> select * from test_ext as of timestamp sysdate-3/1440;

  EMPLOYEE_ID FIRST_NAME   LAST_NAME    JOB_ID     MANAGER_ID HIRE_DATE               SALARY COMMISSION_PCT DEPARTMENT_ID EMAIL
  ----------- ------------ ------------ ---------- ---------- ------------------- ---------- -------------- ------------- -------------------------
          360 Jane         Janus        ST_CLERK          121 2001-05-17 00:00:00       3000              0            50 jjanus
          361 Mark         Jasper       SA_REP            145 2001-05-17 00:00:00       8000             .1            80 mjasper
          362 Brenda       Starr        AD_ASST           200 2001-05-17 00:00:00       5500              0            10 bstarr
          363 Alex         Alda         AC_MGR            145 2001-05-17 00:00:00       9000            .15            80 aalda
          401 Jesse        Cromwell     HR_REP            203 2001-05-17 00:00:00       7000              0            40 jcromwel
          402 Abby         Applegate    IT_PROG           103 2001-05-17 00:00:00       9000             .2            60 aapplega
          403 Carol        Cousins      AD_VP             100 2001-05-17 00:00:00      27000             .3            90 ccousins
          404 John         Richardson   AC_ACCOUNT        205 2001-05-17 00:00:00       5000              0           110 jrichard
  
  8 rows selected.
   
  ----或者如下:
  17:13:35 scott@ORCL> select * from test_ext as of timestamp to_timestamp('2012-12-02 17:07:00','yyyy-mm-dd hh24:mi:ss');                                                                                                                                                                                                                                                                                                                  
  EMPLOYEE_ID FIRST_NAME LAST_NAME     JOB_ID     MANAGER_ID HIRE_DATE               SALARY COMMISSION_PCT DEPARTMENT_ID EMAIL                    
  ----------- ------------------------ ---------- ---------- ------------------- ---------- -------------- ------------- -------------------------
          360 Jane       Janus         ST_CLERK          121 2001-05-17 00:00:00       3000              0            50 jjanus                   
          361 Mark       Jasper        SA_REP            145 2001-05-17 00:00:00       8000             .1            80 mjasper                  
          362 Brenda     Starr         AD_ASST           200 2001-05-17 00:00:00       5500              0            10 bstarr                   
          363 Alex       Alda          AC_MGR            145 2001-05-17 00:00:00       9000            .15            80 aalda                    
          401 Jesse      Cromwell      HR_REP            203 2001-05-17 00:00:00       7000              0            40 jcromwel                 
          402 Abby       Applegate     IT_PROG           103 2001-05-17 00:00:00       9000             .2            60 aapplega                 
          403 Carol      Cousins       AD_VP             100 2001-05-17 00:00:00      27000             .3            90 ccousins                 
          404 John       Richardson    AC_ACCOUNT        205 2001-05-17 00:00:00       5000              0           110 jrichard                 
          
  
  ---使用flashback query恢復delete數據
  
  17:14:00 scott@ORCL> insert into test_ext select * from test_ext as of timestamp sysdate-10/1440; 
                ---或者insert into test_ext select * from test_ext as of timestamp to_timestamp('2012-12-02 17:07:00','yyyy-mm-dd hh24:mi:ss'); 
                                                                                                 
  8 rows created.                                                                                  
                                                                                                 
  17:15:45 scott@ORCL> commit;                                                                     
                                                                                                 
  Commit complete.    
  
  如上述示例中所表示的,as of timestamp 的確非常易用,但是在某些情況下,我們建議使用as of scn 的方式執行flashback query,
  比如需要對多個相互有主外鍵約束的表進行恢復時,如果使用as of timestamp 的方式,可能會由於時間點不統一的緣故造成數據選擇或插入失敗,
  通過scn 方式則能夠確保記錄的約束一致性。
  
2.as of scn 示例
 
 --查看SCN:
  17:15:48 scott@ORCL> select current_scn from v$database;
  
  CURRENT_SCN
  -----------
       788923
  
  17:18:52 scott@ORCL> select dbms_flashback.get_system_change_number from dual;
  
  GET_SYSTEM_CHANGE_NUMBER
  ------------------------
                    788936

                                              
  17:19:16 scott@ORCL> delete from test_ext;    
                                                
  8 rows deleted.                                                                                                           
                                                
  17:20:29 scott@ORCL> commit;   
  
                 
  ---查看刪除之前的狀態:

  17:21:04 scott@ORCL>  select * from test_ext as of scn 788936;                                                                                                        
                                                                                                                                                                      
  EMPLOYEE_ID FIRST_NAME    LAST_NAME     JOB_ID     MANAGER_ID HIRE_DATE               SALARY COMMISSION_PCT DEPARTMENT_ID EMAIL                    
  ----------- ------------- ------------- ---------- ---------- ------------------- ---------- -------------- ------------- -------------------------
          360 Jane          Janus         ST_CLERK          121 2001-05-17 00:00:00       3000              0            50 jjanus                   
          361 Mark          Jasper        SA_REP            145 2001-05-17 00:00:00       8000             .1            80 mjasper                  
          362 Brenda        Starr         AD_ASST           200 2001-05-17 00:00:00       5500              0            10 bstarr                   
          363 Alex          Alda          AC_MGR            145 2001-05-17 00:00:00       9000            .15            80 aalda                    
          401 Jesse         Cromwell      HR_REP            203 2001-05-17 00:00:00       7000              0            40 jcromwel                 
          402 Abby          Applegate     IT_PROG           103 2001-05-17 00:00:00       9000             .2            60 aapplega                 
          403 Carol         Cousins       AD_VP             100 2001-05-17 00:00:00      27000             .3            90 ccousins                 
          404 John          Richardson    AC_ACCOUNT        205 2001-05-17 00:00:00       5000              0           110 jrichard                 
                                                                                                                                                               
  ------使用flashback query恢復delete數據
  
  17:21:29 scott@ORCL> insert into test_ext select * from test_ext as of scn 788936;

  8 rows created. 
    
 事實上,Oracle 在內部都是使用scn,即使你指定的是as of timestamp,oracle 也會將其轉換成scn,
 系統時間標記與scn 之間存在一張表,即SYS 下的smon_scn_time
 
 
  17:24:26 scott@ORCL> desc  sys.smon_scn_time
  
  Name                    Null?    Type
  ----------------------- -------- ----------------
  thread                           number
  time_mp                          number
  time_dp                          date
  scn_wrp                          number
  scn_bas                          number
  num_mappings                     number
  tim_scn_map                      raw(1200)
  scn                              number
  orig_thread                      number


  select * from (
   select num_mappings,orig_thread,scn,scn_bas,scn_wrp,thread,time_dp,time_mp
   from sys.smon_scn_time
   order by time_dp desc
  )where rownum<11;
  
  NUM_MAPPINGS ORIG_THREAD        SCN    SCN_BAS    SCN_WRP     THREAD TIME_DP                TIME_MP
------------ ----------- ---------- ---------- ---------- ---------- ------------------- ----------
          85           0     789025     789025          0          0 2012-12-02 17:22:44  800990564
         100           0     788860     788860          0          0 2012-12-02 17:17:20  800990240
          83           0     788746     788746          0          0 2012-12-02 17:12:50  800989970
         100           0     788091     788091          0          0 2012-12-02 17:07:19  800989639
          97           0     787894     787894          0          0 2012-12-02 17:01:58  800989318
          79           0     787650     787650          0          0 2012-12-02 16:57:25  800989045
         100           0     787379     787379          0          0 2012-12-02 16:51:58  800988718
          89           0     787257     787257          0          0 2012-12-02 16:47:16  800988436
         100           0     787092     787092          0          0 2012-12-02 16:41:58  800988118
          82           0     786980     786980          0          0 2012-12-02 16:37:30  800987850
          
          
  每隔5 分鐘,系統產生一次系統時間標記與scn 的匹配並存入sys.smon_scn_time 表,該表中記錄了最近1440個系統時間標記與scn 的匹配記錄,
  由於該表只維護了最近的1440 條記錄,因此如果使用as of timestamp 的方式則只能flashback 最近5 天內的數據(假設系統是在持續不斷運行並無中斷或關機重啓之類操作的話)。
  注意理解系統時間標記與scn 的每5 分鐘匹配一次這句話,舉個例子,比如scn:339988,339989 分別匹配2008-05-30 13:52:00 和2008-05-30 13:57:00,
  則當你通過as of timestamp 查詢08-05-30 13:52:00 或08-05-30 13:56:59 這段時間點內的時間時,
  oracle 都會將其匹配爲scn:339988 到undo 表空間中查找,也就說在這個時間內,不管你指定的時間點是什麼,查詢返回的都將是08-05-30 13:52:00 這個時刻的數據。
  

  ----查看SCN 和 timestamp 之間的對應關係:


  17:36:37 scott@ORCL> select scn,to_char(time_dp,'yyyy-mm-dd hh24:mi:ss')from sys.smon_scn_time
  17:40:00   2  where rownum<11;
  
         SCN TO_CHAR(TIME_DP,'YY
  ---------- -------------------
           4 2005-06-30 19:09:55
       10569 2005-06-30 19:10:41
      104863 2005-06-30 19:15:57
      142704 2005-06-30 19:20:13
      187891 2005-06-30 19:25:24
      232400 2005-06-30 19:28:00
      306630 2005-06-30 19:33:33
      322553 2005-06-30 19:35:45
      360021 2005-06-30 19:40:57
      361506 2005-06-30 19:41:10
    
  
  
  
  
          
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章