Oracle Flashback之Flashback versions Query

Flashback versions Query


相对于Flashback Query 只能看到某一点的对象状态, Oracle 10g引入的Flashback Version Query可以看到过去某个时间段内,记录是如何发生变化的。 根据这个历史,DBA就可以快速的判断数据是在什么时点发生了错误,进而恢复到之前的状态。我们来了解下伪列 .  所谓的伪列,就是假的,不存在的数据列,用户创建表时虽然没有指定,但是Oracle为了维护而添加的一些内部字段,这些字段可以像普通文件那样的使用。最熟悉的伪列就是 ROWID, 它相当于一个指针,指向记录在磁盘上的位置。ORA_ROWSCN 是Oracle 10g 新增的,暂且把它看作是记录最后一次被修改时的SCN。 Flashback Version Query 就是通过这个伪列来跟踪出记录的变化历史。
Flashback Versions between版本查询功能很强大,通过versions between能够查看指定时间段内undo表空间中记录的不同版本(注意,只包括被提交的记录)。
版本查询的用法并不比as of复杂,与其类似,你只需要在标准查询后面附加versions between timestamp[/scn] t1 and t2即可。记录在版本查询中可能会是一对多的关系,比如某些记录如果被修改过多次,并分别提交,那么你在查询的时候,如果修改的操作是在你指定的时间段(或scn),则记录每次修改的结果都会被选择出来,这比较有利于我们做数据的对比,比如看看数据究竟是怎么变化的。


Flashback versions Query具体的实验:
SQL> create table T(id int,name varchar2(30));

Table created.

SQL> select count(*) from T;

  COUNT(*)
----------
         0

下面做些DML,得到一些不同的数据信息
SQL>  insert into T values(1,'Jack');

1 row created.

SQL>  insert into T values(2,'John');

1 row created.

SQL> commit;

Commit complete.

SQL>  insert into T values(3,'Watson');

1 row created.

SQL> commit;

Commit complete.

SQL>  insert into T values(4,'Sam');

1 row created.

SQL> commit;

Commit complete.

SQL> update T set name='Samnor' where id=4;

1 row updated.

SQL> commit;

Commit complete.

SQL>  insert into T values(5,'XXX');

1 row created.

SQL> commit;

Commit complete.

SQL> delete from T where id=5;

1 row deleted.

SQL> commit;

Commit complete.

查询T的信息
SQL> set linesize 180
SQL> select ora_rowscn, id,NAME from T;

ORA_ROWSCN         ID NAME
---------- ---------- ------------------------------------------------------------
    671761          1 Jack
    671761          2 John
    671761          3 Watson
    671761          4 Samnor

 


查看更多的历史信息
SQL> Select versions_xid,versions_startscn,versions_endscn,DECODE(versions_operation,'I','Insert','U','Update','D','Delete', 'Original') "Operation",
id,name from T versions between scn minvalue and maxvalue;

VERSIONS_XID     VERSIONS_STARTSCN VERSIONS_ENDSCN Operation                ID NAME
---------------- ----------------- --------------- ---------------- ---------- ------------------------------------------------------------
07002E00EA000000            671761                 Delete                    5 XXX
0800250026010000            671755          671761 Insert                    5 XXX
0600130013010000            671748                 Update                    4 Samnor
03001E0018010000            671733          671748 Insert                    4 Sam
0500170029010000            671726                 Insert                    3 Watson
0A000900DB000000            671660                 Insert                    2 John
0A000900DB000000            671660                 Insert                    1 Jack

7 rows selected.


 Flashback Version Query 技术其实有很多伪列,但是ORA_ROWSCN是最重要。它记录的是最后一次被修改时的SCN, 注意是被提交的修改。如果没有提交,这个伪列不会发生变化。ORA_ROWSCN 缺省是数据块级别的,也就是一个数据块内的所有记录都是一个ORA_ROWSCN,数据块内任意一条记录被修改,这个数据库块内的所有记录的ORA_ROWSCN都会同时改变。上例的查询结果以证明。他们的ORA_ROWSCN都是671761。因为他们是同一个块的。不过我们可以在建表时使用关键字rowdependencies, 可以改变这种缺省行为,使用这个关键字后,每条记录都有自己的ORA_ROWSCN。


Example:
SQL> create table T2(id int,name varchar2(30)) rowdependencies;

Table created.

SQL> insert into T2 values(1,'test1');

1 row created.

SQL> insert into T2 values(2,'test2');

1 row created.

SQL> insert into T2 values(3,'test3');

1 row created.

SQL> commit;

Commit complete.

SQL> select ora_rowscn, id,NAME from T2;

ORA_ROWSCN         ID NAME
---------- ---------- ------------------------------------------------------------
    673805          1 test1
    673805          2 test2
    673805          3 test3

此处SCN一样,因为他们是一起提交的,所以是SCN号一样,如果没有提交,是不会变的,我们重做一下DML--update,每条记录的SCN就不一样了。

SQL> update t2 set name='test11' where id=1;

1 row updated.

SQL> commit;

Commit complete.

SQL> select ora_rowscn, id,NAME from T2;

ORA_ROWSCN         ID NAME
---------- ---------- ------------------------------------------------------------
    673868          1 test11
    673805          2 test2
    673805          3 test3

SQL> update t2 set name='test22' where id=2;

1 row updated.

SQL> commit;

Commit complete.

SQL> select ora_rowscn, id,NAME from T2;

ORA_ROWSCN         ID NAME
---------- ---------- ------------------------------------------------------------
    673868          1 test11
    673877          2 test22
    673805          3 test3

SQL> update t2 set name='test33' where id=3;

1 row updated.

SQL> commit;

Commit complete.

SQL> select ora_rowscn, id,NAME from T2;

ORA_ROWSCN         ID NAME
---------- ---------- ------------------------------------------------------------
    673868          1 test11
    673877          2 test22
    673883          3 test33

结论:如果创建表时指定了rowdependencies,则ora_rowscn是以行为单位变化,而不是块


版本查询过程中提供了多个伪列如下:

VERSIONS_STARTSCN
VERSIONS_STARTTIME
 该记录操作时的scn或时间,如果为空,表示该行记录是在查询范围外创建的。
 
VERSIONS_ENDSCN
VERSIONS_ENDTIME
 该记录失效时的scn或时间,如果为空,说明记录当前时间在当前表内存在,或者已经被删除了,可以配合着VERSIONS_OPERATION列来看,如果VERSIONS_OPERATION列值为D,说明该列已被删除,如果该列为空,则说明记录在这段时间无操作。
 
VERSIONS_XID
该操作的事务ID
 
VERSIONS_OPERATION
对该行执行的操作:I表示insert,D表示delete,U表示update。
提示:对于索引键的update操作,版本查询可能会将其识别成两个操作:DELETE和INSERT。
 

在上述查询中,列 versions_starttime、versions_endtime、versions_xid、versions_operation 是伪列,与 ROWNUM、LEVEL 等其他熟悉的伪列相类似。其他伪列 如 VERSIONS_STARTSCN 和 VERSIONS_ENDSCN 显示了该时刻的系统更改号。列 versions_xid 显示了更改该行的事务标识符。有关该事务的更多详细信息可在视图 FLASHBACK_TRANSACTION_QUERY 中找到,其中列 XID 显示事务 id


Flashback versions query的几点注意:
 
1,表不能使用别名:如果在表名后面加上别名,则会报错。
SQL> select * from employees versions e between scn minvalue and maxvalue;
select * from employees versions e between scn minvalue and maxvalue
                                 *
ERROR at line 1:
ORA-00933: SQL command not properly ended


2,伪列:如果使用伪列,则不能使用*来统配表中所有的字段,而应该用table_name.*:
SQL> select *,versions_xid from T versions between scn minvalue and maxvalue;
select *,versions_xid from T versions between scn minvalue and maxvalue
        *
ERROR at line 1:
ORA-00923: FROM keyword not found where expected


3,如果要使用*来统配表中所有的字段,则必须在*前加上表名:
SQL> select T.*,versions_xid from T versions between scn minvalue and maxvalue;

        ID NAME                                                         VERSIONS_XID
---------- ------------------------------------------------------------ ----------------
         1 Jack11                                                       0200270010010000
         1 Jack1                                                        01001B00DC000000
         1 Jack
         2 John
         3 Watson
         4 Samnor

6 rows selected.

你可能感兴趣的:(Oracle10g,Flashback)