oracle-scn

在2012年第一季度的CPU补丁中,包含了一个关于SCN修正的重要变更,这个补丁提示,在异常情况下,Oracle的SCN可能出现异常增长,使得数据库的一切事务停止,由于SCN不能后退,所以数据库必须重建,才能够重用。
这个BUG的影响在于,Oracle的SCN可能会被异常的增进,而至于极限,导致数据库无法正常工作,在这种情况下,只能重建数据库。但是这个风险的发生概率低,因为Oracle会在数据库内部控制SCN的合理增长,每秒SCN最多增长16348,这会将SCN控制在一个合理的增长范畴内。

Oracle使用6 Bytes记录SCN,也就是48位,其最大值是:
select power(2,48) scn from dual;

Oracle在内部控制每秒增减的SCN不超过 16K,按照这样计算,这个数值可以使用大约544年:
select power(2,48) / 16 / 1024 / 3600 / 24 / 365 from dual;

一个数据库当前最大的可能SCN被称为"最大合理SCN",该值可以通过如下方式计算:
select
(
    (
        (
            (
                (  
                    (
                        to_char(sysdate,'YYYY')-1988
                    )*12+
                to_char(sysdate,'mm')-1
                )*31+to_char(sysdate,'dd')-1
            )*24+to_char(sysdate,'hh24')
        )*60+to_char(sysdate,'mi')
    )*60+to_char(sysdate,'ss')
) * to_number('ffff','XXXXXXXX')/4 scn
from dual;

这个算法即SCN算法,以1988年1月1日 00点00时00分开始,每秒计算1个点数,最大SCN为16K

1.oracle 为了防止scn的异常增长所以限制每一秒钟允许最多产生 256*256/4 个scn
2.oracle 内部使用了一个4G范围的数据来表示01/01/1988 00:00:00 ~ 08/18/2121 06:28:15 这段时间.它的算法简单,说来

就是每个月都是用的31天来表示时间,每增加1秒,这个数值就增加1.  可以从redo file dump ,control file dump,datafile

ora_rowscn不应该被认为是一个完全的scn。如果一个事务更改了行R(以块的方式),并提交时scn是10。小于10的永远不会返回,大于等于10可能返回
如果是以行的方式的话,每一行都有不同的scn

对于每一行数据,ora_rowscn返回每一行最近被修改的大概时间.这对于判断一行数据大概是在什么时间被修改的还是有用的.因Oracle是通过事务提交对行所在数据块来进行scn的跟踪的所以说它不精确.可以通过在创建表时使用行级别的依赖跟踪来获得一个更加精确的scn.create table ... norowdependencies|rowdependencies
在对视图进行查询时不能使用ora_rowscn.但对于视图的基表是可以使用ora_rowscn.

也能在update或delete语句中的where子句中使用ora_rowscn
ora_rowscn不能用于回闪查询,但是可以用回闪版本查询来代替ora_rowscn
ora_rowscn也不能用于外部表


在这介绍两个Oracle 10G开始提供的一个伪列ORA_ROWSCN,它又分为两种模式一种是基于block,这是默认的模式,还有一种是基于row上,这种模式只能在建里表时指定ROWDEPENDENCIES,不可以通过后期的alter table ,同时会给数据库带来性能负载
每个Block在头部是记录了该block最近事务的SCN的,所以默认情况下,只需要从block头部直接获取这个值就可以了,不需要其他任何的开销,Oracle就能做到这一点。但是这明显第一种模式是scn是不准确的,因为不可能每个事务都能修改整个 块的数据。

在10g之前,很多系统要实现增量数据抽取,要么通过解析日志,要么加触发器,要么就在表上加一个时间截字段。ORA_ROWSCN其实就是第三种方式,只是这个字段由Oracle来维护,这样可以避免一些应用绕过时间截去更新其他字段带来的问题。


块级
insert into te values('dd',test.nextval);
select ora_rowscn,scn_to_timestamp(ora_rowscn),id,name from te;


行级
create table te1 ROWDEPENDENCIES as select * from te;
select * from te1;
insert into te1 values('ee',test.nextval);
select ora_rowscn,scn_to_timestamp(ora_rowscn),id,name from te1;
原文地址:https://www.cnblogs.com/createyuan/p/6770294.html