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.

相关推荐
时间的拾荒人7 小时前
Redis 主从复制详解:配置实操 + 原理机制
数据库·redis·面试
火云代理7 小时前
更换网络后为什么会退出登录?分清 IP、Cookie 与会话的关系
服务器·网络·网络协议·tcp/ip·php·ip
隔窗听雨眠7 小时前
MySQL三表JOIN执行内核与优化器决策机制
数据库·mysql·sql优化
威嵌神州8 小时前
嵌入式排故实录:高并发下串口数据“超时丢包”的根因剖析与架构优化
运维·服务器·嵌入式硬件·缓存
Decay__8 小时前
SQLServer 索引与 SQL 优化 —— 聚集索引、非聚集索引、覆盖索引、碎片维护与执行计划
运维·数据库·sql·mysql·架构
java_logo9 小时前
Docker 部署 DeepSeek Harness(moelin):轻松搭建带登录的本地 AI Agent 平台
运维·docker·容器·ai agent·deepseek·harness·轩辕镜像
笃行35010 小时前
【金仓数据库产品体验官】订单增量同步实战:MERGE、OUTPUT 与 IDENTITY 的兼容验证
数据库
火云代理11 小时前
同一个网站,有的网络能打开、有的打不开?认识 IPv4 与 IPv6 的访问差异
服务器·网络·网络协议·tcp/ip·测试工具·php·状态模式
坤坤子吖11 小时前
Linux网络编程:TCP 粘包与半包问题,如何正确处理 TCP 流式数据?
linux·服务器·网络·笔记·网络协议·学习
星恒随风13 小时前
MySQL 从零入门(六):复合查询详解——多表查询、自连接、子查询与 UNION
linux·服务器·数据库·mysql