10g:ora_rowscn伪列介绍和使用

10g里为表新增加了一个伪列ora_rowscn
下面一段英文是官方SQL Reference里的说明:

 

For each row,ORA_ROWSCNreturns the conservative upper bound system change number (SCN) of the most recent change to the row. This pseudocolumn is useful for determining approximately when a row was last updated. It is not absolutely precise, because Oracle tracks SCNs by transaction committed for the block in which the row resides. You can obtain a more fine-grained approximation of the SCN by creating your tables with row-level dependency tracking.

Please refer toCREATE TABLE ... NOROWDEPENDENCIES | ROWDEPENDENCIESfor more information on row-level dependency tracking.

You cannot use this pseudocolumn in a query to a view. However, you can use it to refer to the underlying table when creating a view. You can also use this pseudocolumn in the WHERE clause of anUPDATE or DELETEstatement.

ORA_ROWSCNis not supported for Flashback Query. Instead, use the version query pseudocolumns,
which are provided explicitly for Flashback Query.
Please refer to the SELECT ... flashback_query_clause for information on Flashback Query and
"Version Query Pseudocolumns" for additional information on those pseudocolumns.

 

主要是这么几点:
1.默认情况,ora_rowscn记录的scn并不准确,记录的是block的scn。
2.创建表的时候ROWDEPENDENCIES可以来使ora_rowscn真正记录行一级的scn。
3.不能用在查询view时。
4.不能用于flashback query。

可以用来:
1.确认行所在块最后一次修改的scn
2.确认行所在块最后一次修改的大概时间
3.大部分的时候可以确定出两行记录创建的先后顺序(没在同一个块上)
4.如果CREATE TABLE ... ROWDEPENDENCIES 可以精确到行


下面的实验涉及:
1.验证缺省情况Ora_rowscn只记录block级
2.通过scn_to_timestamp 来查询update/insert时间
3.CREATE TABLE ... ROWDEPENDENCIES让ora_rowscn精确到行一级

1.验证缺省情况Ora_rowscn只记录block级
1.1 创建表
SQL> create table emptt as select empno,ename from emp where empno>7700;

表已创建。

1.2 查询ora_rowscn:
SQL> select ora_rowscn,empno,ename from emptt;

ORA_ROWSCN      EMPNO ENAME
---------------------- ---------- ----------
    794054              7782      CLARK
    794054               7788       SCOTT
    794054              7839      KING
    794054              7844       TURNER
    794054              7876       ADAMS
    794054              7900       JAMES
    794054             7902       FORD
    794054              7934       MILLER

已选择8行。

1.3 修改一行:
SQL> update emptt set ename='CLARKCLARK' where empno=7782;

已更新 1 行。

1.4 发现所有行的ora_rowscn都相同,并且rowid显示这些行都在同一个块:
SQL> select rowid,ora_rowscn,empno,ename from emptt;

ROWID                               ORA_ROWSCN EMPNO ENAME
--------------------------------- ----------              ---------- ----------
AAAM2dAAEAAAAG8AAA     794099            7782     CLARKCLARK
AAAM2dAAEAAAAG8AAB     794099            7788     SCOTT
AAAM2dAAEAAAAG8AAC     794099            7839     KING
AAAM2dAAEAAAAG8AAD     794099            7844    TURNER
AAAM2dAAEAAAAG8AAE     794099           7876      ADAMS
AAAM2dAAEAAAAG8AAF     794099            7900     JAMES
AAAM2dAAEAAAAG8AAG     794099          7902      FORD
AAAM2dAAEAAAAG8AAH     794099           7934      MILLER

已选择8行。


1.5 再向表里插入一些数据:
SQL> insert into emptt
2 select empno,ename from emp;

已创建14行。

SQL> commit;

提交完成。

1.6 现在表在两个块上,不同块上的行ora_rowscn分别不同:
SQL> select rowid,ora_rowscn,empno,ename from emptt;

ROWID                                ORA_ROWSCN EMPNO ENAME
--------------------------------- ---------------        ---------- ----------
AAAM2dAAEAAAAG8AAA     794099            7782     CLARKCLARK
AAAM2dAAEAAAAG8AAB     794099            7788     SCOTT
AAAM2dAAEAAAAG8AAC     794099           7839     KING
AAAM2dAAEAAAAG8AAD     794099           7844     TURNER
AAAM2dAAEAAAAG8AAE     794099           7876     ADAMS
AAAM2dAAEAAAAG8AAF     794099           7900     JAMES
AAAM2dAAEAAAAG8AAG     794099           7902     FORD
AAAM2dAAEAAAAG8AAH     794099           7934     MILLER
AAAM2dAAEAAAAG9AAA     794170           7369     SMITH
AAAM2dAAEAAAAG9AAB     794170           7499     ALLEN
AAAM2dAAEAAAAG9AAC     794170           7521     WARD
AAAM2dAAEAAAAG9AAD     794170           7566    JONES
AAAM2dAAEAAAAG9AAE     794170           7654    MARTIN
AAAM2dAAEAAAAG9AAF     794170           7698    BLAKE
AAAM2dAAEAAAAG9AAG     794170           7782    CLARK
AAAM2dAAEAAAAG9AAH     794170           7788    SCOTT
AAAM2dAAEAAAAG9AAI       794170           7839    KING
AAAM2dAAEAAAAG9AAJ     794170            7844    TURNER
AAAM2dAAEAAAAG9AAK     794170           7876    ADAMS
AAAM2dAAEAAAAG9AAL     794170           7900    JAMES
AAAM2dAAEAAAAG9AAM     794170           7902    FORD
AAAM2dAAEAAAAG9AAN     794170           7934    MILLER

已选择22行。

1.7 更新一行再次验证:
SQL> update emptt set ename='CLARKtt' where ename='CLARKCLARK';

已更新 1 行。

SQL> commit;

提交完成。

SQL> select rowid,ora_rowscn,empno,ename from emptt;

ROWID                                ORA_ROWSCN   EMPNO ENAME
----------------------------------   ----------            ---------- ----------
AAAM2dAAEAAAAG8AAA     794199           7782        CLARKtt
AAAM2dAAEAAAAG8AAB     794199           7788        SCOTT
AAAM2dAAEAAAAG8AAC     794199           7839        KING
AAAM2dAAEAAAAG8AAD     794199           7844        TURNER
AAAM2dAAEAAAAG8AAE     794199            7876        ADAMS
AAAM2dAAEAAAAG8AAF     794199           7900        JAMES
AAAM2dAAEAAAAG8AAG     794199          7902         FORD
AAAM2dAAEAAAAG8AAH     794199           7934        MILLER
AAAM2dAAEAAAAG9AAA     794170           7369        SMITH
AAAM2dAAEAAAAG9AAB     794170           7499        ALLEN
AAAM2dAAEAAAAG9AAC     794170           7521        WARD
AAAM2dAAEAAAAG9AAD     794170          7566           JONES
AAAM2dAAEAAAAG9AAE     794170          7654           MARTIN
AAAM2dAAEAAAAG9AAF     794170          7698           BLAKE
AAAM2dAAEAAAAG9AAG     794170          7782          CLARK
AAAM2dAAEAAAAG9AAH     794170          7788          SCOTT
AAAM2dAAEAAAAG9AAI      794170           7839          KING
AAAM2dAAEAAAAG9AAJ     794170           7844          TURNER
AAAM2dAAEAAAAG9AAK     794170          7876          ADAMS
AAAM2dAAEAAAAG9AAL     794170          7900          JAMES
AAAM2dAAEAAAAG9AAM     794170         7902          FORD
AAAM2dAAEAAAAG9AAN     794170         7934          MILLER

已选择22行。


2. 通过scn_to_timestamp 来查询update/insert时间

此功能很有用。
SQL> col update_time format a40
SQL> select scn_to_timestamp(ora_rowscn) update_time,empno,ename from emptt;

UPDATE_TIME                                            EMPNO    ENAME
------------------------------------------------       ----------    ----------
08-5月 -08 10.45.12.000000000 上午             7782   CLARKtt
08-5月 -08 10.45.12.000000000 上午             7788   SCOTT
08-5月 -08 10.45.12.000000000 上午             7839   KING
08-5月 -08 10.45.12.000000000 上午             7844   TURNER
08-5月 -08 10.45.12.000000000 上午             7876   ADAMS
08-5月 -08 10.45.12.000000000 上午             7900   JAMES
08-5月 -08 10.45.12.000000000 上午             7902   FORD
08-5月 -08 10.45.12.000000000 上午             7934 MILLER
08-5月 -08 10.44.09.000000000 上午             7369   SMITH
08-5月 -08 10.44.09.000000000 上午             7499   ALLEN
08-5月 -08 10.44.09.000000000 上午             7521   WARD
08-5月 -08 10.44.09.000000000 上午             7566   JONES
08-5月 -08 10.44.09.000000000 上午             7654   MARTIN
08-5月 -08 10.44.09.000000000 上午             7698   BLAKE
08-5月 -08 10.44.09.000000000 上午             7782 CLARK
08-5月 -08 10.44.09.000000000 上午             7788   SCOTT
08-5月 -08 10.44.09.000000000 上午             7839   KING
08-5月 -08 10.44.09.000000000 上午             7844   TURNER
08-5月 -08 10.44.09.000000000 上午             7876   ADAMS
08-5月 -08 10.44.09.000000000 上午             7900   JAMES
08-5月 -08 10.44.09.000000000 上午             7902 FORD
08-5月 -08 10.44.09.000000000 上午             7934   MILLER

已选择22行。

 

3.CREATE TABLE ... ROWDEPENDENCIES让ora_rowscn精确到行一级

3.1 创建表
SQL> create table empaa rowdependencies as select empno,ename from emp where empno>7700;

表已创建。

3.2 查询
SQL> select rowid,ora_rowscn,empno,ename from empaa;

ROWID                      ORA_ROWSCN      EMPNO ENAME
------------------------------     ----------      ----------    ----------
AAAM3qAAEAAAAJFAAA     799250       7782       CLARK
AAAM3qAAEAAAAJFAAB     799250       7788       SCOTT
AAAM3qAAEAAAAJFAAC     799250       7839       KING
AAAM3qAAEAAAAJFAAD     799250       7844       TURNER
AAAM3qAAEAAAAJFAAE     799250       7876       ADAMS
AAAM3qAAEAAAAJFAAF     799250       7900       JAMES
AAAM3qAAEAAAAJFAAG     799250       7902       FORD
AAAM3qAAEAAAAJFAAH     799250       7934       MILLER

已选择8行。

3.3更新一行并查看结果
SQL> update empaa set ename='CLARKCLARK' where empno=7782;

已更新 1 行。

没有commit的时候ora_rowscn为空
SQL> select rowid,ora_rowscn,empno,ename from empaa;

ROWID                                  ORA_ROWSCN   EMPNO ENAME
-------------------------------      ----------             ---------- ----------
AAAM3qAAEAAAAJFAAA                               7782       CLARKCLARK
AAAM3qAAEAAAAJFAAB     799250             7788       SCOTT
AAAM3qAAEAAAAJFAAC     799250             7839       KING
AAAM3qAAEAAAAJFAAD     799250             7844       TURNER
AAAM3qAAEAAAAJFAAE     799250             7876       ADAMS
AAAM3qAAEAAAAJFAAF     799250             7900       JAMES
AAAM3qAAEAAAAJFAAG     799250             7902       FORD
AAAM3qAAEAAAAJFAAH     799250             7934       MILLER

已选择8行。

SQL> commit;

提交完成。

Commit之后同一块上的ora_rowscn也能对应到独立行:

SQL> select rowid,ora_rowscn,empno,ename from empaa;

ROWID                                  ORA_ROWSCN      EMPNO ENAME
---------------------------------   ----------             ---------- ----------
AAAM3qAAEAAAAJFAAA     799302             7782        CLARKCLARK
AAAM3qAAEAAAAJFAAB     799250             7788        SCOTT
AAAM3qAAEAAAAJFAAC     799250             7839       KING
AAAM3qAAEAAAAJFAAD     799250             7844        TURNER
AAAM3qAAEAAAAJFAAE     799250             7876        ADAMS
AAAM3qAAEAAAAJFAAF     799250             7900        JAMES
AAAM3qAAEAAAAJFAAG     799250             7902        FORD
AAAM3qAAEAAAAJFAAH     799250             7934        MILLER

已选择8行。

 

 

附:一个使用ora_rowscn辅助闪回的例子

--创建测试表
create table test (id int,name varchar2(20)) rowdependencies;
--插入测试数据
insert into test values(1,'a');
insert into test values(2,'b');
insert into test values(3,'c');
insert into test values(4,'d');
insert into test values(5,'e');
insert into test values(6,'f');
insert into test values(7,'g');
insert into test values(8,'h');

commit;
--查看数据
select * from test;

/*ID  NAME
-- -------
1   a
2   b
3   c
4   d
5   e
6   f
7   g
8   h*/

--查看当前ora_rowscn
select id,name,ora_rowscn,dbms_rowid.rowid_block_number(rowid) blockno from test;

/*ID NAME ORA_ROWSCN BLOCKNO
1 a 8249759 288
2 b 8249759 288
3 c 8249759 288
4 d 8249759 288
5 e 8249759 288
6 f 8249759 288
7 g 8249759 288
8 h 8249759 288*/

--执行更新
update test set name='8' where id=8;

commit

--查看更新后的数据
select * from test;

/*ID  NAME
-- -------
1   a
2   b
3   c
4   d
5   e
6   f
7   g
8   8*/

--查看更新后的ora_rowscn
select id,name,ora_rowscn,dbms_rowid.rowid_block_number(rowid) blockno from test;

/*ID NAME ORA_ROWSCN BLOCKNO
1 a 8249759 288
2 b 8249759 288
3 c 8249759 288
4 d 8249759 288
5 e 8249759 288
6 f 8249759 288
7 g 8249759 288
8 8 8249896 288*/

--现在可以通过闪回查询恢复这条记录
select id,name,ora_rowscn,to_char(scn_to_timestamp(ora_rowscn),'yyyy-mm-dd hh24:mi:ss') time,dbms_rowid.rowid_block_number(rowid) blockno from test;
/*ID NAME ORA_ROWSCN TIME BLOCKNO
1 a 8249759 2008-08-01 10:04:19 288
2 b 8249759 2008-08-01 10:04:19 288
3 c 8249759 2008-08-01 10:04:19 288
4 d 8249759 2008-08-01 10:04:19 288
5 e 8249759 2008-08-01 10:04:19 288
6 f 8249759 2008-08-01 10:04:19 288
7 g 8249759 2008-08-01 10:04:19 288
8 8 8249896 2008-08-01 10:08:22 288
*/
select * from test as of timestamp to_date('2008-08-01 10:08:22','yyyy-mm-dd hh24:mi:ss')

--然后删除这条错误记录
delete from test where id=8
--将闪回查询的数据插入原表
insert into test select * from test as of timestamp to_date('2008-08-01 10:08:22','yyyy-mm-dd hh24:mi:ss') where id=8
--查看数据
select * from test

--至此借助ora_rowscn恢复完毕

--如果这个这个表包含LONG数据类型,就采用EXP/IMP方式进行恢复

C:\>exp test/test@acf file=test.dmp tables=test flashback_scn=8249896 query=\"where id=8\"

--然后删除这条错误记录
delete from test where id=8;

--最后倒入这条记录完成恢复
C:\>imp test/test@acf file=test.dmp ignore=y

 

你可能感兴趣的:(oracle,sql,C++,c,C#)