flashback六大技术之flashback query

环境:

23:05:08 hr@ORCL (^ω^) select * from v$version where rownum=1;

BANNER
--------------------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod


1 原理介绍
原理一
多版本读一致性

flashback query依赖于undo中存储的数据的前镜像,在AUM下,我们通过undo_retention及undo表空间的大小,来设置undo数据的保留时间,只要before image没有被覆盖,那么flashback query就是可能的。

oracle通过undo来确保写不阻塞读,当一个事务在写数据时,另一个事务可以通过undo表空间中的数据的前镜像来构造所需的记录集,无需等待commit或rollback。而且undo数据占用的空间并非一次性消费,而是通过AUM动态分配和回收,这样在不同时间点,同一条记录可能被多次修改,也就可能在undo表空间存在多条对应的记录,也就是对应多个版本,flashback便是利用多版本读一致性,通过查询不同时间点的数据和前镜像,获得查询指定时间点(而不仅仅是当前)数据的能力。

flashback query这一特性,最常被应用的就是修复误操作的数据,也就是基于select的扩展:select .. as of timestamp | scn,让user拥有了“穿越”过去的能力,至于恢复,便是insert tasble ..select或create table as select。

原理二
SMON_SCN_TIME

SMON_SCN_TIME是SCN和时间的映射表,也是flashback 时间的限制。从oracle 10g开始,LGWR首先会在SGA中记录SCN与时间的映射关系,SMON则定期检查SGA是否内存中记录的映射大于磁盘上的,如果有就刷新记录到磁盘。由于LGWR至少每3秒就会被激活一次,所以现在SMON_SCN_TIME能够支持大于3秒flashback。

oracle 10g提供了两个新的函数对SCN和timestamp进行相互转换:scn_to_timestamp和timestamp_to_scn.这两个函数的时间转换正是依赖于SMON_SCN_TIME表,oracle能够转换的最小SCN,也就是这个表中记录的最小记录。即使执行flashback query时指定as of timestamp查询undo中的数据,实际获取的数据是以指定的时间对应的SCN时的数据为基准。例如,SCN:339988,339989分别匹配2009-05-30 13:52:00和2009-05-30 13:57:00,则当你通过as of timestamp查询2009-05-30 13:52:00或者2009:05-30 13:56:59这段时间点内的任何时间,oracle都会将其匹配为SCN:339988到undo表空间中查找,也就是说在这个时间内,不管你指定的时间点是什么,查询返回的都将是2009-05-30 13:52:00这个时刻对应的SCN的数据。

16:11:47 sys@ORCL (^ω^) select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER
------------------------
                 3898458

16:12:11 sys@ORCL (^ω^) alter session set nls_date_format='yyyy/mm/dd hh24:mi:ss';

会话已更改。

16:12:45 sys@ORCL (^ω^) select scn_to_timestamp(3898458)  scn from dual;

SCN
---------------------------------------------------------------------------
10-9月 -12 04.12.11.000000000 下午

16:13:13 sys@ORCL (^ω^) select timestamp_to_scn(sysdate-5/1440) scn from dual;

       SCN
----------
   3898333

16:31:22 hr@ORCL (^ω^) select scn,to_char(time_dp,'yyyy/mm/dd hh24:mi:ss') from sys.smon_scn_time;

       SCN TO_CHAR(TIME_DP,'YYYY/MM/DDHH24:MI:SS'
---------- --------------------------------------
   3361371 2012/09/03 18:23:53
   3361948 2012/09/03 18:33:52
   3362176 2012/09/03 18:38:53
   3362674 2012/09/03 18:48:52
   3363615 2012/09/03 19:03:52
   3363792 2012/09/03 19:08:53
   3364474 2012/09/03 19:18:43
   3364715 2012/09/03 19:23:47
   3365034 2012/09/03 19:28:48
   3365400 2012/09/03 19:38:45


2 实验

基于时间的查询与恢复

22:47:40 hr@ORCL (^ω^) select count(*) from t1;

  COUNT(*)
----------
        17

22:47:49 hr@ORCL (^ω^) delete t1 where rownum<5;

已删除4行。

22:49:15 hr@ORCL (^ω^) commit;

提交完成。

22:49:21 hr@ORCL (^ω^) select count(*) from t1;

  COUNT(*)
----------
        13

22:49:39 hr@ORCL (^ω^) select count(*) from t1 as of timestamp sysdate-3/1440;

  COUNT(*)
----------
        17

22:50:47 hr@ORCL (^ω^) create table t1_recov as select * from t1 as of timestamp sysdate-3/1440;

表已创建。

22:52:17 hr@ORCL (^ω^) select count(*) from t1_recov;

  COUNT(*)
----------
        17

22:52:30 hr@ORCL (^ω^) commit;

提交完成。

22:52:39 hr@ORCL (^ω^)


基于SCN的查询与恢复

22:52:39 hr@ORCL (^ω^) select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER
------------------------
                 3928361

22:56:35 hr@ORCL (^ω^) select count(*) from t1;

  COUNT(*)
----------
        13

22:56:58 hr@ORCL (^ω^) delete t1 where rownum<5;

已删除4行。

22:58:20 hr@ORCL (^ω^) commit;

提交完成。

22:58:25 hr@ORCL (^ω^) select count(*) from t1;

  COUNT(*)
----------
         9

22:58:37 hr@ORCL (^ω^) select count(*) from t1 as of scn 3928361;

  COUNT(*)
----------
        13

22:59:04 hr@ORCL (^ω^) create table t1_recov_scn as select * from t1 as of scn 3928361;

表已创建。

23:00:12 hr@ORCL (^ω^) select count(*) from t1_recov_scn;

  COUNT(*)
----------
        13

23:00:29 hr@ORCL (^ω^) commit;

提交完成。


你可能感兴趣的:(flashback)