关于SCN Headroom
参考文献
一、 再来谈谈SCN
上一篇文章谈到了SCN的一些种类和查询方式,这一篇再来具体看看SCN。
SCN是Oracle数据库为了确保数据和事务的一致性设计的逻辑时间戳,在Oracle数据库内部用6个字节、48位记录SCN,SCN由SCN Base和SCN Wrap组成,其中SCN Base占用4个字节,而SCN wrap占用2个字节,且有:
scn=scn wrap * power(2,32)+scn base
更多关于SCN Base和SCN Wrap的内容可看参考文献2
显然,SCN的最大值
Col SCN FOR 99999999999999999
SELECT Power(2, 48) SCN
FROM dual;
输出结果为:
SCN
------------------
281 4749 7671 0656
这个值是Oracle数据库设定的SCN理论上限,也就是所谓的hard limit,一旦达到这个值,SCN将无法继续增长,数据库也将变得不再可用,只能重新建库。Oracle为了确保数据库的长期可用,还设计了个soft limit,也就是headroom,将SCN的增长速度控制在每秒不超过16k,并且当前SCN不得大于1988年到当前时间点的最大SCN,在此限制下,Oracle数据库的理论最大可用年限为
SELECT Power(2, 48) / 16 / 1024 / 3600 / 24 / 365 AS years
FROM dual;
输出结果为:
YEARS
----------
544.770078
使用五百多年后才可能达到hard limit。当前时刻的最大SCN取值为
SET numw 20
SELECT ( ( ( To_number(To_char(sysdate, 'YYYY')) - 1988 ) * 12 * 31 * 24 * 60 * 60 ) + ( ( To_number(To_char(sysdate, 'MM')) - 1 ) * 31 * 24 * 60 * 60 ) + ( (( To_number(To_char(sysdate, 'DD')) - 1 )) * 24 * 60 * 60 ) + ( To_number(To_char(sysdate, 'HH24')) * 60 * 60 ) + ( To_number(To_char(sysdate, 'MI')) * 60 ) + ( To_number(To_char(sysdate, 'SS')) ) ) * 16384 AS MAXSCN
FROM dual;
其计算公式为:当前时刻最大SCN=1988年至当前时刻的秒数*16k
headroom的计算方式为:当前时刻最大SCN-当前实际SCN
SELECT VERSION,
date_time,
dbms_flashback.get_system_change_number current_scn,
INDICATOR
FROM (SELECT VERSION,
To_char(SYSDATE, 'YYYY/MM/DD HH24:MI:SS') DATE_TIME,
( ( ( ( ( ( To_number(To_char(sysdate, 'YYYY')) - 1988 ) * 12 * 31 * 24 * 60 * 60 ) + ( ( To_number(To_char(sysdate, 'MM')) - 1 ) * 31 * 24 * 60 * 60 ) + ( (( To_number(To_char(sysdate, 'DD')) - 1 )) * 24 * 60 * 60 ) + ( To_number(To_char(sysdate, 'HH24')) * 60 * 60 ) + ( To_number(To_char(sysdate, 'MI')) * 60 ) + ( To_number(To_char(sysdate, 'SS')) ) ) * ( 16 * 1024 ) ) - dbms_flashback.get_system_change_number ) / ( 16 * 1024 * 60 * 60 * 24 ) ) INDICATOR
FROM v$instance)
正常情况下,SCN的增长也不会大于soft limit所限制的最大SCN,但是怕就怕它不正常。
二、 SCN的BUG与DB_LINK共同引发的灾难事件
如果某一个数据库存在SCN异常增长的BUG,而其他数据库通过DB_LINK与其相互连接,DB_LINK在工作时会取两端数据库SCN值较大的一个来作为同步SCN,这意味着其他SCN正常的数据库也会发生异常,而其他原本正常的数据库也通过DB_LINK连向另外的数据库的话,则会导致SCN异常增长的问题进一步扩大另外的数据库,发生链式反应。
在2012年1月的补丁中,增加了参数external_scn_rejection_threshold_hours,这个参数设定了同步过来的SCN值计算出的headroom小于多少时拒绝DB_LINK连接的SCN同步请求。