flashback ora_rowscn 记录 插入的先后 是否提交等

For each row, ORA_ROWSCN returns 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. In this note we will try to see how ORA_ROWSCN works with Rowdependencies and Norowdependecies with examples:

SOLUTION

  • For rows to have unique ora_rowscn ( when using row dependencies), there should be commit after every single dml. If there are multiple row manipulated in one transaction , then all these rows will have same ORA_ROWSCN. See the test case below.

select ename, ora_rowscn from temp;

ENAME ORA_ROWSCN


SMITH 1472829

ALLEN 1472832

WARD 1472835

JONES 1472838

MARTIN 1472841

BLAKE 1472850

CLARK 1472853

SCOTT 1472698

KING 1472856

TURNER 1472859

ADAMS 1472862

ENAME ORA_ROWSCN


JAMES 1472865

FORD 1472868

MILLER 1472871

SQL> insert into temp select * from emp where empno = 7788;

SQL> select ename, ora_rowscn from temp;

ENAME ORA_ROWSCN


SMITH 1472829

ALLEN 1472832

WARD 1472835

JONES 1472838

MARTIN 1472841

BLAKE 1472850

CLARK 1472853

SCOTT 1472698

KING 1472856

TURNER 1472859

ADAMS 1472862

ENAME ORA_ROWSCN


JAMES 1472865

FORD 1472868

MILLER 1472871

SCOTT 1473294 <<< new ora_rowscn

SQL> insert into temp select * from emp where empno = 7788;

1 row created.

SQL> insert into temp select * from emp where empno = 7788;

1 row created.

SQL> insert into temp select * from emp where empno = 7788;

1 row created.

SQL> commit;

Commit complete.

SQL> select ename, ora_rowscn from temp;

ENAME ORA_ROWSCN


SMITH 1472829

ALLEN 1472832

WARD 1472835

JONES 1472838

MARTIN 1472841

BLAKE 1472850

CLARK 1472853

SCOTT 1472698

KING 1472856

TURNER 1472859

ADAMS 1472862

ENAME ORA_ROWSCN


JAMES 1472865

FORD 1472868

MILLER 1472871

SCOTT 1473294

SCOTT 1473314 <<

SCOTT 1473314 << same ora_rowscn for three rows

SCOTT 1473314 <<

*** So the only reason of having rows with duplicate ORA_ROWSCN is that a single transaction is commiting/changing number of rows together.

  • When using NOROWDEPENDENCIES all the rows in a BLOCK will have the same ORA_ROWSCN.

SQL> select ename, ora_rowscn,rowid from test;

ENAME ORA_ROWSCN ROWID


SMITH 17445533 AAASMWAAEAAAAA8AAA

ALLEN 17445533 AAASMWAAEAAAAA8AAB

WARD 17445533 AAASMWAAEAAAAA8AAC

JONES 17445533 AAASMWAAEAAAAA8AAD

MARTIN 17445533 AAASMWAAEAAAAA8AAE

BLAKE 17445533 AAASMWAAEAAAAA8AAF

CLARK 17445533 AAASMWAAEAAAAA8AAG

SCOTT 17445533 AAASMWAAEAAAAA8AAH

KING 17445533 AAASMWAAEAAAAA8AAI

TURNER 17445533 AAASMWAAEAAAAA8AAJ

ADAMS 17445533 AAASMWAAEAAAAA8AAK

JAMES 17445533 AAASMWAAEAAAAA8AAL

FORD 17445533 AAASMWAAEAAAAA8AAM

MILLER 17445533 AAASMWAAEAAAAA8AAN

SCOTT 17445627 AAASMWAAEAAAAA+AAA

SCOTT 17445627 AAASMWAAEAAAAA+AAB

SCOTT 17445627 AAASMWAAEAAAAA+AAC

SCOTT 17445627 AAASMWAAEAAAAA+AAD

SCOTT 17445627 AAASMWAAEAAAAA+AAE

19 rows selected.

SQL> update test set sal=5000 where ename='WARD';

1 row updated.

SQL> select ename, ora_rowscn,rowid from test;

ENAME ORA_ROWSCN ROWID


SMITH 17445533 AAASMWAAEAAAAA8AAA

ALLEN 17445533 AAASMWAAEAAAAA8AAB

WARD 17445533 AAASMWAAEAAAAA8AAC

JONES 17445533 AAASMWAAEAAAAA8AAD

MARTIN 17445533 AAASMWAAEAAAAA8AAE

BLAKE 17445533 AAASMWAAEAAAAA8AAF

CLARK 17445533 AAASMWAAEAAAAA8AAG

SCOTT 17445533 AAASMWAAEAAAAA8AAH

KING 17445533 AAASMWAAEAAAAA8AAI

TURNER 17445533 AAASMWAAEAAAAA8AAJ

ADAMS 17445533 AAASMWAAEAAAAA8AAK

ENAME ORA_ROWSCN ROWID


JAMES 17445533 AAASMWAAEAAAAA8AAL

FORD 17445533 AAASMWAAEAAAAA8AAM

MILLER 17445533 AAASMWAAEAAAAA8AAN

SCOTT 17445627 AAASMWAAEAAAAA+AAA

SCOTT 17445627 AAASMWAAEAAAAA+AAB

SCOTT 17445627 AAASMWAAEAAAAA+AAC

SCOTT 17445627 AAASMWAAEAAAAA+AAD

SCOTT 17445627 AAASMWAAEAAAAA+AAE

19 rows selected.

SQL> commit;

Commit complete.

SQL> select ename, ora_rowscn,rowid from test;

ENAME ORA_ROWSCN ROWID


SMITH 17445699 AAASMWAAEAAAAA8AAA

ALLEN 17445699 AAASMWAAEAAAAA8AAB

WARD 17445699 AAASMWAAEAAAAA8AAC

JONES 17445699 AAASMWAAEAAAAA8AAD

MARTIN 17445699 AAASMWAAEAAAAA8AAE

BLAKE 17445699 AAASMWAAEAAAAA8AAF

CLARK 17445699 AAASMWAAEAAAAA8AAG

SCOTT 17445699 AAASMWAAEAAAAA8AAH

KING 17445699 AAASMWAAEAAAAA8AAI

TURNER 17445699 AAASMWAAEAAAAA8AAJ

ADAMS 17445699 AAASMWAAEAAAAA8AAK

JAMES 17445699 AAASMWAAEAAAAA8AAL

FORD 17445699 AAASMWAAEAAAAA8AAM

MILLER 17445699 AAASMWAAEAAAAA8AAN

SCOTT 17445627 AAASMWAAEAAAAA+AAA }

SCOTT 17445627 AAASMWAAEAAAAA+AAB }

SCOTT 17445627 AAASMWAAEAAAAA+AAC } second block

SCOTT 17445627 AAASMWAAEAAAAA+AAD }

SCOTT 17445627 AAASMWAAEAAAAA+AAE }

19 rows selected.

ORA_ROWSCN for all rows in first block got updated.

-----------------还能检查是否提交-----------

How to determine in a transaction (TX) if a row has already been committed or not?

SOLUTION

The pseudo column ORA_ROWSCN will show if the row has been committed, a thing to keep in mind is that ORA_ROWSCN will only provide correct information if the SCN is stored inline with the row (ROWDEPENDENCIES) otherwise it will return the SCN of the block the row is located in (NOROWDEPENDENCIES).

The following examples will show the difference:

NOROWDEPENDENCIES

SQL> set numwidth 20

SQL> drop table test

SQL> create table test (c varchar2(10));

SQL> insert into test values ('one');

SQL> commit;

SQL> insert into test values ('two');

SQL> select ora_rowscn,c from test;

ORA_ROWSCN C


2238860 one

2238860 two <<no commit yet so SCN should be NULL but SCN not stored in row

<<thus SCN of block returned

ROWDEPENDENCIES

SQL> set numwidth 20

SQL> drop table test;

SQL> create table test (c varchar2(10)) rowdependencies;

SQL> insert into test values ('one');

SQL> commit;

SQL> insert into test values ('two');

SQL> select ora_rowscn,c from test;

ORA_ROWSCN C


2238937 one

two << no commit yet SCN as stored with row is NULL

SQL> rollback;

Same is of course true in case of update:

SQL> update test set c='three' where c='one';

ORA_ROWSCN C


three


Is there a method to extract the changes from a table, for example all the entries inserted starting from a certain date to now?

SOLUTION

ORA_ROWSCN pseudo-column that reflects the system change-number (SCN) of the most recent change to a row and the query parameter can be used to unload the last changes from a table with DataPump.

The example below shows how to use ORA_ROWSCN in a query to generate a dump file with the last changes from a table:

1. Create a table and populate it

create table test (c varchar2(10));

begin

for i in 1..10000 loop

insert into test select rownum from dual connect by level <=10;

end loop;

commit;

end;

/

  1. Query the table as follows

select scn_to_timestamp (ora_rowscn), ora_rowscn, count(*) from test group by ora_rowscn order by scn_to_timestamp (ora_rowscn);

SCN_TO_TIMESTAMP(ORA_ROWSCN) ORA_ROWSCN COUNT(*)


10-FEB-15 12.14.05.000000000 PM 1222415 100000

3. Insert a new set of rows

begin

for i in 1..10000 loop

insert into test select rownum from dual connect by level <= 10;

end loop;

commit;

end;

/

4. Query the table to group the records by the system change-number (SCN) of the changes

select scn_to_timestamp(ora_rowscn),ora_rowscn, count(*) from test group by ora_rowscn order by scn_to_timestamp(ora_rowscn);

SCN_TO_TIMESTAMP(ORA_ROWSCN) ORA_ROWSCN COUNT(*)


10-FEB-15 12.14.05.000000000 PM 1222415 99999

10-FEB-15 12.15.04.000000000 PM 1222807 100001

5. Run the DataPump export with the parameter file below to unload the last changes from the table

exp_rowscn.parfile


tables=test

directory=data_pump_dir

dumpfile=orascn_test.dmp

logfile=orascn_test.log

query="where scn_to_timestamp(ora_rowscn)>cast('10-FEB-15 12:15:00' as timestamp)"

#> expdp user/<PASSWORD> parfile=exp_rowscn.parfile

Export: Release 11.2.0.4.0 - Production on Tue Feb 10 12:16:36 2015

Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

Starting "TEST"."SYS_EXPORT_TABLE_02": test/******** parfile=exp_rowscn.parfile

Estimate in progress using BLOCKS method...

Processing object type TABLE_EXPORT/TABLE/TABLE_DATA

Total estimation using BLOCKS method: 3.441 GB

(...)

Processing object type TABLE_EXPORT/TABLE/TABLE

(...)

. . exported "TEST"."TEST" 191.6 MB 100001 rows

Master table "TEST"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded

******************************************************************************

Dump file set for TEST.SYS_EXPORT_TABLE_01 is:

/u01/app/oracle/admin/oradb11g/dpdump/orascn_test.dmp

Job "TEST"."SYS_EXPORT_TABLE_01" successfully completed at Tue Feb 10 12:16:49 2015 elapsed 0 00:00:12

Note: ORA_ROWSCN will only provide correct information if the SCN is stored inline with the row (ROWDEPENDENCIES) otherwise it will return the SCN of the block the row is located in (NOROWDEPENDENCIES). The difference between ROWDEPENDENCIES and NOROWDEPENDENCIES can be found in Note 748675.1 How To Identify Committed And Uncommitted Data From Table(s) in transaction.

------------how to find when record insert today---------------

You may be able to get this even if you do not have an appropriate column using ORA_ROWSCN and SCN_TO_TIMESTAMP

This query will give you the rows amended in the last 5 days

select t1.*, ora_rowscn, scn_to_timestamp(ora_rowscn) from t1

where ora_rowscn > (select min(first_change#) from v$log_history where first_time > sysdate -5);

Unfortunately, you can't go back beyond 5 days with the SCN_TO_TIMESTAMP feature, but you can still go back as far as your log history goes with

select t1.*, t1.ora_rowscn, lh.first_time from t1, v$log_history lh

where t1.ora_rowscn between lh.first_change# and lh.next_change#;

With this second query, the time is when the particular log started, rather than the row time. Also, you need to switch logs to get the most recent data.

Similarly, if you are running in archivelog mode, you can get a time range with

select t1.*, t1.ora_rowscn, lh.first_time, lh.next_time from t1, v$archived_log lh

where t1.ora_rowscn between lh.first_change# and lh.next_change#;

Hope this helps

BobB

EDIT: Unless the table has been created with rowdependencies, these queries will give all the rows in a block that has had one or more rows inserted/amended in the timeframe. With rowdependencies it gives the rows amended.

Flashback query - retrieves data from a past point in time

Example:-

Flashback Table using TIMESTAMP

This statement brings a table 'employees' back to a certain timestamp:

SQL> FLASHBACK TABLE employees

TO TIMESTAMP

TO_TIMESTAMP('03-12-2007 08:00:00','MM/DD/YY HH:MI:SS');

Reterive Data Example:-

1)select * from employees as of timestamp

to_timestamp('03-12-2007 08:00:00', 'DD-MM-YYYY HH:MI:SS')

where last_name = ahmed;

2)select employee_id, name from hr.employee as of timestamp (systimestamp - interval '15' minute);

Hopefully now can easliy do your task.

相关推荐
dessler23 分钟前
Docker-run命令详细讲解
linux·运维·后端·docker
群联云防护小杜36 分钟前
如何给负载均衡平台做好安全防御
运维·服务器·网络·网络协议·安全·负载均衡
PyAIGCMaster1 小时前
ubuntu装P104驱动
linux·运维·ubuntu
奈何不吃鱼1 小时前
【Linux】ubuntu依赖安装的各种问题汇总
linux·运维·服务器
sdaxue.com1 小时前
帝国CMS:如何去掉帝国CMS登录界面的认证码登录
数据库·github·网站·帝国cms·认证码
爱码小白1 小时前
网络编程(王铭东老师)笔记
服务器·网络·笔记
zzzhpzhpzzz1 小时前
Ubuntu如何查看硬件型号
linux·运维·ubuntu
蜜獾云1 小时前
linux firewalld 命令详解
linux·运维·服务器·网络·windows·网络安全·firewalld
陌北v11 小时前
Docker Compose 配置指南
运维·docker·容器·docker-compose
只会copy的搬运工2 小时前
Jenkins 持续集成部署——Jenkins实战与运维(1)
运维·ci/cd·jenkins