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.

相关推荐
极小狐1 分钟前
极狐GitLab 项目功能和权限解读
运维·git·安全·gitlab·极狐gitlab
宁酱醇2 分钟前
GitLab_密钥生成(SSH-key)
运维·ssh·gitlab
hnlucky5 分钟前
redis 数据类型新手练习系列——Hash类型
数据库·redis·学习·哈希算法
秋风起,再归来~8 分钟前
【Linux庖丁解牛】—进程优先级!
linux·运维·服务器
Lalolander34 分钟前
设备制造行业如何避免项目管理混乱?
运维·制造·工程项目管理·四算一控·epc·环保设备工程·设备制造
LucianaiB1 小时前
【金仓数据库征文】_AI 赋能数据库运维:金仓KES的智能化未来
运维·数据库·人工智能·金仓数据库 2025 征文·数据库平替用金仓
prinrf('千寻)1 小时前
nacos设置权重进行负载均衡不生效
运维·负载均衡
时序数据说1 小时前
时序数据库IoTDB在航空航天领域的解决方案
大数据·数据库·时序数据库·iotdb
Lary_Rock1 小时前
Android 编译问题 prebuilts/clang/host/linux-x86
android·linux·运维
.生产的驴1 小时前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven