Scn Internal

调高SCN的方法

http://yangtingkun.itpub.net/post/468/527032

有的时候出于恢复或其他目的的需要,需要将现有的SCN提升。

在10g以前,一般使用event的方式:

SQL> alter session set events '10015 trace name adjust_scn level 1';

Session altered.

在MOUNT状态下运行上面的SQL,可以根据调整SCN的需要设置不同的LEVEL。此外还存在类似的方法:

alter system set events 'immediate trace name adjust_scn level 10;

除了EVENT的设置外,还有一个隐藏参数也可以轻易的达到目标。使用_minimum_giga_scn参数,可以将SCN提高1G的倍数:

SQL> select current_scn from v$database;

CURRENT_SCN


5310856

SQL> alter system set "_minimum_giga_scn" = 1 scope = spfile;

System altered.

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.

Total System Global Area 524288000 bytes
Fixed Size 2097560 bytes
Variable Size 150998632 bytes
Database Buffers 369098752 bytes
Redo Buffers 2093056 bytes
Database mounted.
Database opened.
SQL> select current_scn from v$database;

CURRENT_SCN


1073741909

SQL> select * from v$version;

BANNER


Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi
PL/SQL Release 10.2.0.5.0 - Production
CORE 10.2.0.5.0 Production
TNS for Linux: Version 10.2.0.5.0 - Production
NLSRTL Version 10.2.0.5.0 - Production

使用这种方法,就可以轻易的提升SCN到指定大小。

SCN、ORA-19706错误和_external_scn_rejection_threshold_hours参数

http://www.laoxiong.net/scn-ora-19706-_external_scn_rejection_threshold_hours-parameter.html
by 老熊

Oracle数据库在安装了2012年1月发布的CPU或PSU补丁之后,经常出现下面一些现象:
应用出现ORA-19706: invalid SCN错误。
在alert日志中出现类似于:
Wed May 30 15:09:57 2012
Advanced SCN by 68093 minutes worth to 0×0ba9.4111a520, by distributed transaction remote logon, remote DB:xxxx.
Client info : DB logon user xxxx, machine xxxx, program oracle@xxxx (J001), and OS user oracle
这样的警告。
在alert日志中出现类似于:
Wed May 30 12:02:00 2012
Rejected the attempt to advance SCN over limit by 166 hours worth to 0×0ba9.3caec689, by distributed transaction remote logon, remote DB: xxxx.
Client info : DB logon user xxxx, machine xxxx, program oracle@xxxx (J000), and OS user oracle
这样的错误信息。
在alert日志中出现类似于:
Sat Mar 17 05:57:45 2012
ALTER DATABASE OPEN

Warning: The SCN headroom for this database is only 38 days!

这样的信息。
在MOS文档《ORA-19706 and Related Alert Log Messages [ID 1393360.1]》中还提到其他会出现在alert中的一些警告信息:
Warning - High Database SCN: Current SCN value is 0×0b7b.0008e40b, threshold SCN value is 0×0b75.055dc000, If you have not previously reported this warning on this database, please notify Oracle Support so that additional diagnosis can be performed.
WARNING: This patch can not take full effect until this RAC database has been completely shutdown and restarted again.Oracle recommends that it is done at the earliest convenience.
如果说以上的现象只是警告或应用级报错,影响范围有限,那么不幸的是如果遇到RECO进程在恢复分布式事务时遇到SCN问题,则可能使数据库宕掉,例如:
view plaincopy to clipboardprint?
Wed May 30 14:44:02 2012
Errors in file /oracle/admin/miboss/bdump/xxxx_reco_225864.trc:
ORA-19706: invalid SCN
Wed May 30 14:44:02 2012
Errors in file /oracle/admin/miboss/bdump/xxxx_reco_225864.trc:
ORA-00600: internal error code, arguments: [18348], [0x000000000], [485331304561], [], [], [], [], []
………
RECO: terminating instance due to error 476
Intance terminated by RECO, pid s= 225864
那么2012年1月发布的CPU或PSU补丁到底使数据库在SCN处理方面产生了什么样的变化?这种变化对数据库有什么危害吗?甚至于说,以上提示的信息是由于这个补丁的BUG引起的吗?
要回答这些问题,得先从SCN讲起。SCN可以说是Oracle中的很基础,但同时也是很重要的东西,它是一个单向增长的“时钟”,广泛应用于数据库的恢复、事务ACID、一致性读还有分布式事务中。那么除了这些,SCN还有以下一些知识点:
SCN的内部存储方式:在Oracle内部,SCN分为两部分存储,分别称之为scn wrap和scn base。实际上SCN长度为48位,即它其实就是一个48位的整数。只不过可能是由于在早些年通常只能处理32位甚至是16位的数据,所以人为地分成了低32位(scn base)和高16位(scn wrap)。为什么不设计成64位,这个或许是觉得48位已经足够长了并且为了节省两个字节的空间:)。那么SCN这个48位长的整数,最大就是2^48(2的48次方, 281万亿,281474976710656),很大的一个数字了。
Maximum Reasonable SCN:在当前时间点,SCN最大允许达到(或者说最大可能)的SCN值。也称为Reasonable SCN Limit,简称RSL。这个值是一个限制,避免数据库的SCN无限制地增大,甚至达到了SCN的最大值。这个值大约是这样一个公式计算出来的:(当前时间-1988年1月1日)*24*3600*SCN每秒最大可能增长速率。当前时间减1988年1月1日的结果是天数,24表示1天24小时,3600表示1小时3600秒。不过这个公式里面“当前时间-1988年1月”部分并不是两个时间直接相减,而是按每月31天进行计算的(或许是为了计算简单,因此在Oracle内部可能要频繁地计算,这个计算方法可以在安装了13498243这个补丁后得到的scnhealthcheck.sql文件中看到,《Installing, Executing and Interpreting output from the “scnhealthcheck.sql” script [ID 1393363.1]》这篇MOS文档解释了这个脚本的使用及对结果的解释,实际上直接看脚本代码更为清楚)。那么SCN最秒最大可能增长速率是多少呢,这个跟Oracle版本有一定的关系,在11.2.0.2之前是16384(即16K),在11.2.0.2及之后版本是32768(即32K)。在11.2.0.2的版本中有一个隐含参数,_max_reasonable_scn_rate,其默认值就是32768(不建议调整这个值)。如果按16K的最大值,SCN要增长到最大,要超过500年。
SCN Headroom:这个是指Maximum Reasonable SCN与当前数据库SCN的差值。在alert中通常是以“天”为单位,这个只是为了容易让人读而已。天数=(Maximum Reasonable SCN-Current SCN)/16384/3600/24。这个值就的意思就是,如果按SCN的每大增长速率,多少天会到达Maximum Reasonable SCN。但实际上即使如此,也不会到达Maximum Reasonable SCN,因为到那时Maximum Reasonable SCN也增大了(越时间增大),要到达Maximum Reasonable SCN,得必须以SCN最大可能速率的2倍才行。
SCN的异常增长:通常来说,每秒最大允许的16K/32K增长速率已经足够了,但是不排除由于BUG,或者人为调整导致SCN异常增长过大。特别是后者,比如数据库通过特殊手段强制打开,手工把SCN递增得很大。同时Oracle的SCN会通过db link进行传播。如果A库通过db link连接到B库,如果A库的SCN高于B库的SCN,那么B库就会递增SCN到跟A库一样,反之如果A库的SCN低于B库的SCN,那么A库的SCN会递增到跟B库的SCN一样。也就是说,涉及到db link进行操作的多个库,它们会将SCN同步到这些库中的最大的SCN。
那么,如果是数据库本身操作而不是通过db link同步使得SCN的增长,其增长速率如何判断呢,这个可以通过系统的统计量“calls to kcmgas”和”DEBUG calls to kcmgas”来得到。kcmgas的意思是get and advance SCN,即获取并递增SCN。
在两个库通过db link进行分布式事务时,假设B库的SCN值要高于A库的SCN,因此要将B库的SCN增同步到A库,但是如果B库的SCN过高,这样同步到A库之后,使得A库面临Headroom过小的风险,那么A库会拒绝同步SCN,这个时候就会报ORA-19706: Invalid SCN错误。分布式事务,或者说是通过db link的操作就会失败,即使是通过db link的查询操作。这里显然有一个阈值,如果递增SCN使得Headroom过小到什么值时,就会拒绝递增(同步)SCN?目前来看是这样:如果打了2012年1月CPU或PSU补丁,11.2.0.2及以后的版本,是1天即24小时,其他版本是31天即744小时,打了补丁之后可以由隐含参数_external_scn_rejection_threshold_hours来调整。而没有打补丁的情况下,视同此参数设为0,实际最小为1小时。由于Oracle 9.2.0.8没有了最新的补丁集,显示也不会有这个参数,保持默认为1小时。注意这是一个静态参数。所以打了2012年1月CPU或PSU补丁的一个重要变化是增加了_external_scn_rejection_threshold_hours参数,同时使11.2.0.2以下版本的数据库其Headroom的阈值增得较大。这带来的影响就是ORA-19706的错误出现的概率更高。解决的办法将_external_scn_rejection_threshold_hours这个隐含参数设置为较小的值,推荐的值是24,即1天。从_external_scn_rejection_threshold_hours这个参数名的字面意思结合它的作用,可以说这个参数就是”拒绝外部SCN“的阈值。对于数据库自身产生的SCN递增是没有影响的。
虽然11.2.0.2及之后的版本,其默认的每秒最大可能SCN增长速率为32K,这使得Maximum Reasonable SCN更大,也就是说其SCN可以增长到更大的值。那也就是可能会使11.2.0.2的库与低版本的数据库之间不能进行db link连接。或者是11.2.0.2的库不能与16K速率的(比如调整了_max_reasonable_scn_rate参数值)的11.2.0.2的库进行db link连接。
现在是时候来回答以下几个问题了:
2012年1月后发布的CPU或PSU补丁到底使数据库在SCN处理方面产生了什么样的变化?答案是:增加了_external_scn_rejection_threshold_hours参数,11.2.0.2及以上版本的这个参数默认值是24,其他版本默认值是744。这样使11.2.0.2以下版本的数据库其Headroom的阈值增得较大。
这种变化对数据库有什么危害吗?答案是:在一个具有很多系统的大型企业环境里面,db link使用很多,甚至有一些不容易管控到的数据库也在跟关键系统通过 db link进行连接,在这样的环境中,过高的SCN扩散到关键系统,而系统如果打了这个补丁,其Headroom阈值变大,那么就更容易出现ORA-19706错误,对db link依赖很严重的系统可能会导致业务系统问题,严重情况下甚至会宕库。不过通过设置隐含参数_external_scn_rejection_threshold_hours可解决这样的问题。所以,如果你安装了2012年1月的CPU或PSU补丁,请尽快设置此参数为建议的值24,极端情况下你可以设置为1。。
alert中的那些提示或警告信息是BUG引起的吗?答案是:这些提示或警告不是BUG引起的。它只是提醒你注意SCN过高增长,或者是你的Headroom较小(在Headroom小于62天时可能会提醒),引起你的重视。实际上根据MOS文档《System Change Number (SCN), Headroom, Security and Patch Information [ID 1376995.1]》的说法,这个补丁修复了SCN相关的一些BUG。如果非要说BUG,可以勉强认为补丁安装后新增的参数_external_scn_rejection_threshold_hours其默认值过大。Bug 13554409 - Fix for bug 13554409 [ID 13554409.8]就是说的这个问题。不过这个问题已经在2012年4月的CPU或PSU补丁中得到修复。
在最后我们来解读一下alert日志中的一些信息:
信息:
Wed May 30 15:09:53 2012
Completed crash recovery at
Thread 1: logseq 3059, block 19516, scn 12754630269552
2120 data blocks read, 2120 data blocks written, 19513 redo blocks read
…..
Wed May 30 15:09:57 2012
Advanced SCN by 68093 minutes worth to 0×0ba9.4111a520, by distributed transaction remote logon, remote DB:xxxx.
Client info : DB logon user xxxx, machine xxxx, program oracle@xxxx (J001), and OS user oracle
这里是说,SCN向前(跳跃)递增了68098分钟,其递增后的SCN是0×0ba9.4111a520。注意这里的分钟的计算就是根据SCN每秒最大可能增长速率为16K来的。我们计算一下:
0×0ba94111a520转换成10进制12821569053984。
在alert日志中,这个信息是刚打开数据库的时候,所以 crash recovery完成时的scn可以做为近似的当前SCN,其值为12754630269552:
(12821569053984-12754630269552)/16384/60=68093.65278320313
这里16384值的是SCN每秒最大可能增长速率,可以看到计算结果极为接近。
我们再来计算一下这个SCN的headroom是多少:
view plaincopy to clipboardprint?
SQL> select
2 ((((
3 ((to_number(to_char(cur_date,'YYYY'))-1988)*12*31*24*60*60) +
4 ((to_number(to_char(cur_date,'MM'))-1)*31*24*60*60) +
5 (((to_number(to_char(cur_date,'DD'))-1))*24*60*60) +
6 (to_number(to_char(cur_date,'HH24'))*60*60) +
7 (to_number(to_char(cur_date,'MI'))*60) +
8 (to_number(to_char(cur_date,'SS')))
9 ) * (16*1024)) - 12821569053984)
10 / (16*1024*60*60*24)
11 ) headroom
12 from (select to_date('2012-05-30 15:09:57','yyyy-mm-dd hh24:mi:ss') cur_date from dual);

HEADROOM
--
24.1496113
可以看到结果为24天,由于这个时候_external_scn_rejection_threshold_hours参数值为24,即1天,所以虽然有这么大的跳跃,但SCN仍然增长成功。
信息:
Wed May 30 12:02:00 2012
Rejected the attempt to advance SCN over limit by 166 hours worth to 0×0ba9.3caec689, by distributed transaction remote logon, remote DB: xxxx.
Client info : DB logon user xxxx, machine xxxx, program oracle@xxxx (J000), and OS user oracle
在这个信息中,拒绝了db link引起的SCN增加。计算一下这个SCN的headroom:
0×0ba93caec689转换成10进制是12821495465609
当前时间是2012-05-30 12:02:00,
view plaincopy to clipboardprint?
SQL> select
2 ((((
3 ((to_number(to_char(cur_date,'YYYY'))-1988)*12*31*24*60*60) +
4 ((to_number(to_char(cur_date,'MM'))-1)*31*24*60*60) +
5 (((to_number(to_char(cur_date,'DD'))-1))*24*60*60) +
6 (to_number(to_char(cur_date,'HH24'))*60*60) +
7 (to_number(to_char(cur_date,'MI'))*60) +
8 (to_number(to_char(cur_date,'SS')))
9 ) * (16*1024)) - 12821495465609)
10 / (16*1024*60*60*24)
11 ) headroom
12 from (select to_date('2012-05-30 12:02:00','yyyy-mm-dd hh24:mi:ss') cur_date from dual);

HEADROOM
--
24.0710752
由于这个时候_external_scn_rejection_threshold_hours参数值为744,即31天,计算出的headroom在这个阈值之内,因此拒绝增加SCN。
(31-24.0710752)*24=166.2941952,正好是166小时。
update on 2012/6/2
实际上2012年1月的CPU或PSU补丁之后还会有下面的变化:
_minimum_giga_scn这个隐含没有了,可惜了这个手工增加SCN的利器。
11.2.0.2及之后的版本,从原来的32K SCN最大速率调整回了16K速率。可以用下面的SQL来得到结果:
view plaincopy to clipboardprint?
SQL&gt select decode(bitand(DI2FLAG,65536),65536,'Y','N') using16
2 from x$kccdi2;

U
-
Y
上面的SQL的结果只有在11.2.0.2及以上版本才有意义,结果为Y,表示使用的是16K的速率,否则是使用32K速率。
本文涉及的一些参数,和SCN的一些算法,可能会随着版本或补丁的变化而产生较大的变化。