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.

相关推荐
萨格拉斯救世主19 分钟前
jenkins使用slave节点进行node打包报错问题处理
运维·jenkins
川石课堂软件测试29 分钟前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
十叶知秋33 分钟前
【jmeter】jmeter的线程组功能的详细介绍
数据库·jmeter·性能测试
龙哥说跨境38 分钟前
如何利用指纹浏览器爬虫绕过Cloudflare的防护?
服务器·网络·python·网络爬虫
pk_xz1234562 小时前
Shell 脚本中变量和字符串的入门介绍
linux·运维·服务器
小珑也要变强2 小时前
Linux之sed命令详解
linux·运维·服务器
瓜牛_gn2 小时前
mysql特性
数据库·mysql
海绵波波1072 小时前
Webserver(4.3)TCP通信实现
服务器·网络·tcp/ip
奶糖趣多多3 小时前
Redis知识点
数据库·redis·缓存
九河云4 小时前
AWS账号注册费用详解:新用户是否需要付费?
服务器·云计算·aws