ITPub博客

首页 > 数据库 > Oracle > 通过Flashback Version Query了解Flashback Table的行为过程

通过Flashback Version Query了解Flashback Table的行为过程

原创 Oracle 作者:oliseh 时间:2015-05-14 20:16:14 0 删除 编辑

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_endtimeversions_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_endscnversions_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_endscnB记录不复存在,注意新增operation=’U’的记录的version_startscnC2=’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_2表的内容如下:

select * from t0513_2;


//////////////////// merge 操作 ////////////////////

#####新建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;

 

2、Flashback table

#####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的操作时按照如下顺序进行的:

删除BBCCD三条记录->插入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操作引发的deleteinsert操作

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$'这条记录多出了前滚的操作。

































来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/53956/viewspace-1655162/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
不仅仅专注Oracle database技术, member of SHOUG

注册时间:2014-04-06

  • 博文量
    128
  • 访问量
    1617117