您的位置:首页 > 其它

数据误删后如何使用Flashback恢复数据

2014-05-05 15:00 555 查看
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

    

  

  

  

  

          
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: