闪回表允许我们将数据表恢复到过去的某个时间点,而不必像以前一样采用基于时间点的恢复。
Oracle 10g的flashback table有如下特性:
- 可以在线操作;
- 恢复到指定时间点或者SCN的任何数据;
- 自动恢复相关属性,如索引、触发器、约束等;
- 满足分布式的一致性;
- 满足数据一致性,所有相关对象将自动一致。
闪回表的常用语法为:
alter table table_name enable row movement;
flashback table table_name to timestamp|scn <timestamp|scn>;
注意:如果需要flashback一个数据表,需要具有flashback any table的系统权限或者是该表的flashback对象权限,同时还需要拥有该表的SELECT、INSERT、DELETE、ALTER权限,由于flashback table技术使用DML操作去恢复数据,不能保证Rowid不变,所以在闪回之前还需要启用表的row movement特性。
可以使用flashback table命令去闪回一个或多个表到过去的某个时间点或SCN,但是需要注意,flashback table不能将表恢复到改变表结构的DDL操作之前。
以下测试说明了闪回表的基本用法:
SQL> create table test as select * from dba_users;
表已创建。
SQL> select count(*) from test;
COUNT(*)
----------
32
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
1030688
SQL> delete from test where rownum <13;
已删除12行。
SQL> commit;
提交完成。
SQL> select count(*) from test;
COUNT(*)
----------
20
SQL> alter table test enable row movement;
表已更改。
SQL> flashback table test to scn 1030688;
闪回完成。
SQL> select count(*) from test;
COUNT(*)
----------
32
实际上闪回表的功能是对闪回查询的增强,我们可以通过后台跟踪来研究一下闪回表的内部操作:
SQL> create table eygle as select * from dba_users;
表已创建。
SQL> select count(*) from eygle;
COUNT(*)
----------
32
SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
1031000
SQL> delete from eygle where rownum <13;
已删除12行。
SQL> commit;
提交完成。
SQL> select count(*) from eygle;
COUNT(*)
----------
20
SQL> alter session set events '10046 trace name context forever,level 12';
会话已更改。
SQL> alter table eygle enable row movement;
表已更改。
SQL> flashback table eygle to scn 1031000;
闪回完成。
SQL> select count(*) from eygle;
COUNT(*)
----------
32
获得跟踪文件,分析其中的主要内容,得到闪回表的主要操作步骤(以下测试在Oracle Database 11gR2中进行):
1.通过闪回查询在SYS_TEMP_FBT临时表记录闪回信息
以下查询通过as of SCN的闪回查询将指定对象、指定SCN的数据,包含ROWID插入到SYS_TEMP_FBT临时表中,注意这里面有一个重要的函数SYS_FBT_INSDEL,这个函数用于决定是通过INSERT操作还是DEL操作来还原数据:
PARSING IN CURSOR #1 len=159 dep=1 uid=86 oct=2 lid=86 tim=10946591929 hv=439595081 ad='2e25706c' sqlid='8qu8q54d37c29'
INSERT /*+ APPEND */ into SYS_TEMP_FBT SELECT /*+ FBTSCAN FULL(S) PARALLEL(S, DEFAULT) */ :1, :2, :3, rowid, SYS_FBT_INSDEL FROM "EYGLE"."EYGLE" as of SCN :4 S
END OF STMT
PARSE #1:c=0,e=48,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1028464186,tim=10946591927
BINDS #1:
Bind#0
oacdty=01 mxl=32(32) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=800000 frm=01 csi=852 siz=32 off=0
kxsbbbfp=36167438 bln=32 avl=05 flg=09
value="EYGLE"
Bind#1
oacdty=01 mxl=32(32) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=800000 frm=01 csi=852 siz=32 off=0
kxsbbbfp=36167458 bln=32 avl=05 flg=09
value="EYGLE"
Bind#2
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=800000 frm=00 csi=00 siz=24 off=0
kxsbbbfp=36167478 bln=22 avl=04 flg=09
value=73442
Bind#3
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=800000 frm=00 csi=00 siz=24 off=0
kxsbbbfp=36167490 bln=22 avl=04 flg=09
value=1031000
在SYS_TEMP_FBT这个临时表中记录了闪回表的数据操作,表中共有52条记录,先是DELETE 20条记录,然后是INSERT 32条记录,删除的是表中当前记录共20条,INSERT的是闪回目标点的32条记录:
SQL> select * from sys_temp_fbt;
SCHEMA OBJECT_NAM OBJECT# RID A
---------- ---------- ---------- -------------------- -
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAM D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAN D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAO D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAP D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAQ D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAR D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAS D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAT D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAU D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAV D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAW D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAX D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAY D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAZ D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAa D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAb D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAc D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAd D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAe D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAf D
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAA I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAB I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAC I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAD I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAE I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAF I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAG I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAH I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAI I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAJ I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAK I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAL I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAM I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAN I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAO I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAP I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAQ I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAR I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAS I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAT I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAU I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAV I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAW I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAX I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAY I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAZ I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAa I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAb I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAc I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAd I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAe I
EYGLE EYGLE 73442 AAAR7iAAEAAAACrAAf I
已选择52行。
第二个步骤在数据表中删除那些需要删除的记录:
PARSING IN CURSOR #1 len=237 dep=1 uid=86 oct=7 lid=86 tim=10946767645 hv=2296038091 ad='2e2566dc' sqlid='46df7uk4dphqb'
/* Flashback Table */ DELETE /*+ BYPASS_UJVC */ FROM (SELECT /*+ ORDERED USE_NL(S) PARALLEL(S,DEFAULT) PARALLEL(T,DEFAULT) */ S.rowid FROM SYS_TEMP_FBT T, "EYGLE"."EYGLE" S WHERE T.rid = S.rowid and T.action = 'D' and T.object# = : 1) V
END OF STMT
PARSE #1:c=0,e=66,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=4211461806,tim=10946767643
WAIT #1: nam='cursor: pin S' ela= 4 idn=2296038091 value=1 where=327680 obj#=-1 tim=10946773047
BINDS #1:
Bind#0
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=800000 frm=00 csi=00 siz=24 off=0
kxsbbbfp=361676c8 bln=22 avl=04 flg=09
value=73442
第三个步骤是执行INSERT操作,还原期望SCN点上的32条记录:
PARSING IN CURSOR #1 len=290 dep=1 uid=86 oct=2 lid=86 tim=10946853708 hv=3158191884 ad='2e25d5ec' sqlid='f8k47dfy3wbsc'
/* Flashback Table */ INSERT /*+ PARALLEL(S, DEFAULT) PARALLEL(T, DEFAULT) */ INTO "EYGLE"."EYGLE" SELECT /*+ USE_NL(S) ORDERED PARALLEL(S, DEFAULT) PARALLEL(T, DEFAULT) */ S.* FROM SYS_TEMP_FBT T , "EYGLE"."EYGLE" as of SCN :1 S WHERE T.rid = S.rowid and T.action = 'I' and T.object# = :2
END OF STMT
PARSE #1:c=0,e=62,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=890006386,tim=10946853705
BINDS #1:
Bind#0
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=800000 frm=00 csi=00 siz=24 off=0
kxsbbbfp=36167628 bln=22 avl=04 flg=09
value=1031000
Bind#1
oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00
oacflg=13 fl2=800000 frm=00 csi=00 siz=24 off=0
kxsbbbfp=36167640 bln=22 avl=04 flg=09
value=73442
这就是闪回表的内部实现机制。




