Flashback Version Query是用来查看表中行的修改历史,在undo保留期限内能够了解到哪些transaction对哪些行进行了修改,结合flashback transaction可以对误操作进行准确定位与及时回退。这里我们利用Flashback Version Query的特性观察一下Flashback table的工作过程。
1、先对常见DML操作后用flashback version query查询到的结果进行一下解读
###创建测试表
drop table t0513_2;
create table t0513_2 (id number,c2 varchar2(2),dmltime date);
commit;
insert into t0513_2 values(1,'A',sysdate);
commit;
set numwidth 16
col versions_starttime format a28
col versions_endtime format a28
set linesize 160
select versions_startscn,versions_starttime,versions_endtime,versions_operation,id,c2,dmltime from t0513_2 versions between scn minvalue and maxvalue;
select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
12723373810786
//////////////////// insert 操作 ////////////////////
#####再插入两行
insert into t0513_2 values(2,'B',sysdate);
insert into t0513_2 values(3,'C',sysdate);
commit;
---对于当前存在的记录versions_endtime和versions_endscn均为空
select versions_startscn,versions_starttime,versions_endtime,versions_operation,id,c2,dmltime from t0513_2 versions between scn minvalue and maxvalue;
//////////////////// delete 操作 ////////////////////
#####删除掉C2=’A’的记录
delete t0513_2 where C2='A';
commit;
----删除掉C2='A'的记录后原先A插入的记录有了versions_endscn、versions_endtime有值了,表示A插入的记录已经无效了,新增了一条operation=’D’且versions_endscn为空的记录,表示C2=’A’被删除的操作至今为止都有效,即表示当前表里已经没有C2=’A’的记录
select
versions_startscn,versions_starttime, versions_endscn,versions_endtime,versions_operation,id,c2,dmltime
from t0513_2 versions between scn minvalue and maxvalue;
//////////////////// update 操作 ////////////////////
#####更新C2=’B’的记录
update t0513_2 set C2='BB' where C2='B';
commit;
---原先C2=’B’ insert的记录在versions_endscn被赋予了值,代表在这个versions_endscn上B记录不复存在,注意新增operation=’U’的记录的version_startscn和C2=’B’记录的version_endscn相同
select versions_startscn,versions_starttime, versions_endscn,versions_endtime,versions_operation,id,c2,dmltime from t0513_2 versions between scn minvalue and maxvalue;
#####新建t0513_3表,测试merge into
t0513_2操作
create table t0513_3 ( id number,c2
varchar2(2),dmltime);
insert into t0513_3 values(4,'D',sysdate);
insert into t0513_3 values(3,'CC',sysdate);
commit;
merge into t0513_2 using t0513_3 on
(t0513_2.id=t0513_3.id)
when matched then update set
t0513_2.C2=t0513_3.C2,t0513_2.dmltime=t0513_3.dmltime
when not matched then insert
(t0513_2.id,t0513_2.c2,t0513_2.dmltime)
values(t0513_3.id,t0513_3.c2,t0513_3.dmltime);
select * from t0513_2;
----merge操作以后相当于一条insert,一条delete的效果
select
versions_startscn,versions_starttime, versions_endscn,versions_endtime,versions_operation,id,c2,dmltime
from t0513_2 versions between scn minvalue and maxvalue;
#####flashback table t0513_2 to scn 12723373810786;
alter table t0513_2 enable row movement;
flashback table t0513_2 to scn
12723373810786;
----闪回后t0513_2表的内容
select * from t0513_2
select
versions_startscn,versions_starttime, versions_endscn,versions_endtime,versions_operation,id,c2,dmltime
from t0513_2 versions between scn minvalue and maxvalue;
通过flashback version query发现flashback table的操作时按照如下顺序进行的:
删除BB、CC、D三条记录->插入A记录,即是把表先回退到刚创建完里边尚无数据的状态,再插入A记录
#####再看一个复杂一点flashback
table的例子
有的时候并不会像上面的例子那样把表里的数据回退到无数据的状态,特别是对于数据量较大的表这样做效率有点低,oracle会把表flashback到尽量接近目标scn的状态再前滚
---数据准备
create table t0513_9 tablespace ts0422_1 as
select * from dba_objects where 1=2;
SCOTT@tstdb1-SQL> insert into t0513_9
select * from dba_objects; <---第一次插入
20143 rows created.
SCOTT@tstdb1-SQL> commit;
Commit complete.
SCOTT@tstdb1-SQL> insert into t0513_9
select * from t0513_9; <---第二次插入
20143 rows created.
SCOTT@tstdb1-SQL> commit;
Commit complete.
SCOTT@tstdb1-SQL> select
dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
12723373926488 <---要flashback的目标scn
SCOTT@tstdb1-SQL> insert into t0513_9
select * from t0513_9; <---第三次插入
40286 rows created.
SCOTT@tstdb1-SQL> commit;
Commit complete.
SCOTT@tstdb1-SQL> select count(*) from
t0513_9;
COUNT(*)
----------------
80572
SCOTT@tstdb1-SQL> flashback table t0513_9 to scn
12723373926488; ?执行flashback
table,仅保留第一、第二次插入的记录
Flashback complete.
SCOTT@tstdb1-SQL> select count(*) from
t0513_9;
COUNT(*)
----------------
40286
--- 观察一下object_name='CON$'这条记录的version 变化情况
select
versions_startscn,versions_xid,versions_starttime,versions_operation,versions_endtime,versions_operation,object_name
from t0513_9 versions between scn minvalue and maxvalue where
object_name='CON$';
其中红色框圈出的是Flashback table的操作,把这6行操作之间的关系按照时间先后归纳如下
操作语句类型
Transaction ID
操作时间
操作说明
第一次插入
insert into
t0513_9 select * from dba_objects;
0008001900001A58
14-MAY-15
01.41.49 PM
第二次插入
insert into
t0513_9 select * from t0513_9
000A000F00014049
14-MAY-15
01.42.25 PM
第三次插入
insert into
t0513_9 select * from t0513_9
0002001000001981
14-MAY-15 01.42.49
PM
这一次插入对应了versions_startscn=12723373926537的两行记录
由Flashback table操作引发的delete操作
flashback
table t0513_9 to scn 12723373926488;
0002001000001962
14-MAY-15
01.45.04 PM
Flashback
table过程中把第三次插入的两行记录(versions_startscn=12723373926537对应的两行记录)删除了。结果是只留下了第一、二次插入的记录。
可以看出,上面flashback table的过程中没有对我们要保留的第一、第二次插入的记录进行任何DML操作,对于object_name='CON$'这条记录来讲,可以说是恰好flashback到我们所需要恢复到的点上,没有任何多余的操作
---再观察一下object_name='SYS_C0013006'这条记录的version 变化情况,就不一样了
select
versions_startscn,versions_xid,versions_starttime,versions_operation,versions_endtime,versions_operation,object_name
from t0513_9 versions between scn minvalue and maxvalue where object_name='SYS_C0013006';
以上红色框圈出的是Flashback table的操作
操作语句类型
Transaction ID
操作时间
操作说明
第一次插入
insert into
t0513_9 select * from dba_objects;
0008001900001A58
14-MAY-15
01.41.49 PM
第二次插入
insert into
t0513_9 select * from t0513_9
000A000F00014049
14-MAY-15
01.42.25 PM
第三次插入
insert into
t0513_9 select * from t0513_9
0002001000001981
14-MAY-15
01.42.49 PM
这一次插入对应了versions_startscn=12723373926537的两行记录
由Flashback table操作引发的delete和insert操作
flashback
table t0513_9 to scn 12723373926488;
0002001000001962
14-MAY-15
01.45.04 PM
Flashback
table过程中对应的操作,描述如下:
删除第三次插入的两行记录(第三次插入的是versions_startscn=12723373926537对应的两条记录);
删除第二次插入的一条记录(第二次插入的是versions_startscn= 12723373926472对应的那条记录);
因为第二次插入的那条记录是我们最终需要保留的,所以在最后又重新插入了这条记录
可以看出,对于object_name='SYS_C0013006'这条记录来讲,flashback的过程略微复杂,先把第三次插入的两条记录删除,接着删除了我们所需要保留的第二次插入的记录,最后再重新插入这条记录,对于第二次插入的记录经历了先删除再重新插入的过程,比起object_name='CON$'这条记录多出了前滚的操作。
---当前t0513_2表的内容如下:
select * from t0513_2;
//////////////////// merge 操作 ////////////////////
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/53956/viewspace-1655162/,如需转载,请注明出处,否则将追究法律责任。