[20150806]scn headroom.txt
转载:http://www.askmaclean.com/archives/scn-headroom-1988-oracle.html
SCN是Oracle数据库内部的一种逻辑时间戳,通过SCN将数据库内的事件理清次序, 这是保证事务属性ACID的必要信息。
数据库使用SCN来帮助实现查询和跟踪变化。举例来说,当一个事务更新一行数据,那么数据库就需要将该update发生时的SCN记录下来,
该事务(transaction)中的其他修改操作通常都会使用同样的SCN。当一个事务commit提交,数据库又会相应地记录提交时的SCN。 多个事
务同事commit可能会共享同一个SCN。
SCN总是单调递增的序列, Oracle数据库最大可以使用到的SCN上限值是一个天文数字,目前该上限是281万亿,即
281,474,976,710,656(2的48次方)。这是对SCN的硬限制,理论上一个数据库的SCN总是不能超过281万亿, 以每秒16K的增速计算,花费
557年SCN上限才会被耗尽,作为一个hard limit ,我们很少有机会触及。
除了281万亿的hard limit外, Oracle数据库还存在一种 soft limit 即SCN headroom, 为了保证SCN的增长速度不要过于离谱,Oracle
使用了一种基于时间的限量供应SCN的系统。
关于headroom ,字典翻译头上空间, 实际你可以理解为 在一个房间内 天花板和 头部之间的空间, 数据库的Current SCN就是你头部
的高度,那么(房间高度-头部高度)=headroom,
在任何时间点上,Oracle数据库均会计算一个当前时间点DB 不能超过的SCN LIMIT上限, 注意这里提到了时间点 ,通俗点说这个SCN
LIMIT是随着时间流逝在增加的。
Oracle计算的算法基于从1988年到当前时间点的秒数,再乘上16,384(16k),用SQL表达就如以下语句:
select sysdate,
(((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 n30 from dual;
SYSDATE N30
------------------- -------------------------------
2015-08-06 10:08:49 14532918132736
通过将SCN的增长率和时间流逝关联起来,确保SCN的限量增长,保证Oracle数据库理论上可以处理500年的数据。
通过以上公式我们可以发现SCN每秒的合理增长量为16,384,然而Oracle公司在近年发现某些软件层面的BUG会导致数据库试图超过或接近
这个当前时间点的SCN 最大值。
常规情况下,若数据库尝试超过当前的SCN最大值,数据库将会cancel取消掉引发该超越事件的事务, 在应用程序层面将看到一个错误。
在接下来的一秒钟,上限值会随着时间而增长16k,因此通常应用程序会在短暂停顿后继续工作。 但是在极少数情况下,数据库可能需要
为了保护自身的完整性而shutdown关闭,理论上不会造成数据丢失或corrupted。
类似于计算机网络中的时钟同步,当2个数据库通过DBLINK相互交流访问时,他们会选用2者中当前Current SCN最大的一个来同步SCN,
譬如说数据库A 的SCN 是10000,而数据库B是20000,当2者发生DBLINK联系时,将会用最大的SCN (20000)来同步,数据库A的SCN将jump
跳跃到20000。 在一些环境中,往往不是本地数据库触发了SCN快速增长的bug,而是众多数据库中的某一个存在活跃的SCN BUG,而其他
数据库与该问题数据库发生DBLINK联系后,就会因为SCN同步而经历 SCN headroom的的极速减少; 换句话说就是一只老鼠坏了一锅汤,
异常高的SCN会通过DBLINK传播给正常的数据库,这种传播往往呈爆炸式发展。
由于数据库总是会拒绝SCN超过当前的SCN上限,所以Oracle官方宣称Oracle数据库理论运行500年的SCN预备量不会受以上问题的影响。
但是受到传播的数据库仍可能由于自我保护的原因而宕机。
Oracle官方宣布所有与SCN headroom相关的bug均已在January 2012 CPU 和相关的PSU中修复了, 同样的修复补丁也被包含在DB
Patchset Update (PSU) 以及最新的Exadata和Windows的Bundle Patch上。
有一些客户纠结于他们的SCN接近于当前SCN最大值,且SCN的增长量远大于他们处理数据库的合理值。在所有这些cases中Oracle 发现均
是January 2012 CPU 中已经修复bug的现象,在客户实施这些修复后SCN headroom 开始有效增长了。
为了保证系统不出现潜在的问题,用户可以运行Metalink Note"Installing, Executing and Interpreting output from the "
scnhealthcheck.sql" script [ID 1393363.1]"中包含的脚本scnhealthcheck.sql来检查特定数据库的当前SCN距离当前SCN 最大值有
多少差距。该脚本会警告用户该数据库接近于当前SCN的最大上限,在这种情况下建议立即对受影响数据库实施CPU/PSU补丁。实施以上补
丁后的预期结果是SCN headroom有效增长,官方宣称在所有case中都如预期一样。
$ oerr ora 01513
01513, 00000, "invalid current time returned by operating system"
// *Cause: The operating system returned a time that was not between
// 1988 and 2121.
// *Action: Correct the time kept by the operating system.
--昨天做了通过修改控制文件提升scn的测试,今天设置接近scn headroom的情况。
SYS@test> @10to16 14532918132736
10 to 16 HEX REVERSE16
-------------- -----------------------------------
00d37b56c4000 0x00406cb5-370d0000
--设置这个数据会出现什么情况呢?不要在生产系统做这个测试。安全期间,我还关闭了db_link的连接。
SYS@test> show parameter link
NAME TYPE VALUE
------------------------ -------- -------
open_links integer 4
open_links_per_instance integer 4
SYS@test> alter system set open_links=0 scope=spfile;
System altered.
SYS@test> alter system set open_links_per_instance=0 scope=spfile;
System altered.
SYS@test> shutdown immediate ;
ORA-01109: database not open
Database dismounted.
ORACLE instance shut down.
--这样不能从这台机器发出db_link的连接。但是别人连接这台机器是可以的。
SYS@test> show parameter link
NAME TYPE VALUE
------------------------ -------- ------
open_links integer 0
open_links_per_instance integer 0
--修改方法参考前面的关于提升scn的链接。
SYS@test> SELECT 'controlfile' "SCN location", 'SYSTEM checkpoint' NAME, checkpoint_change#,open_mode,current_scn FROM v$database;
SCN locatio NAME CHECKPOINT_CHANGE# OPEN_MODE CURRENT_SCN
----------- -------------------- ------------------ ---------- ------------
controlfile SYSTEM checkpoint 12736202601 MOUNTED 0
SYS@test> @10to16 12736202601
10 to 16 HEX REVERSE16
-------------- -----------------------------------
00002f7230769 0x690723f7-02000000
--修改为0x00406cb5-370d0000。清零检查和。
00044000 15 C2 00 00 11 00 00 00 E9 E5 C3 33 FF FF 01 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 5F 79 34 54 45 53 54 00 00 00 00 00 00 00 00 79 01 40 00 01 40 40 50 00 00 00 00 00 00 00 00 3D B8 7C F4
00044040 02 00 00 00 1B 5F 79 34 C0 CC 2A 00 00 00 00 00 F7 13 C5 33 00 00 00 00 00 03 20 0A 06 00 00 00 06 00 00 00 01 00 00 00 00 40 6C B5 37 0D 00 00 01 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00
00044080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
SYS@test> set numw 20
SYS@test> SELECT 'controlfile' "SCN location", 'SYSTEM checkpoint' NAME, checkpoint_change#,open_mode,current_scn FROM v$database;
SCN locatio NAME CHECKPOINT_CHANGE# OPEN_MODE CURRENT_SCN
----------- -------------------- -------------------- ---------- --------------------
controlfile SYSTEM checkpoint 14532918132736 MOUNTED 0
SYS@test> @10to16 14532918132736
10 to 16 HEX REVERSE16
-------------- -----------------------------------
00d37b56c4000 0x00406cb5-370d0000
--使用没有任何问题。超过限制呢?
SYS@test> SELECT 'controlfile' "SCN location", 'SYSTEM checkpoint' NAME, checkpoint_change#,open_mode,current_scn FROM v$database;
SCN locatio NAME CHECKPOINT_CHANGE# OPEN_MODE CURRENT_SCN
----------- -------------------------------------------------- -------------------- ---------- --------------------
controlfile SYSTEM checkpoint 14533018796402 MOUNTED 0
select sysdate,
(((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 n30 from dual;
SYSDATE N30
------------------- -------------------------------
2015-08-06 10:33:55 14532942807040
--已经超过限制。
SYS@test> alter database open ;
alter database open
*
ERROR at line 1:
ORA-00600: internal error code, arguments: [2252], [3383], [3144434034], [], [], [], [], []
--等1会在看看。
SYS@test> select (14533018796402-14532942807040)/16384/60 from dual;
(14533018796402-14532942807040)/16384/60
----------------------------------------
77.30037638346354167
--要等78分钟。再改小一点看看。
SYS@test> SELECT 'controlfile' "SCN location", 'SYSTEM checkpoint' NAME, checkpoint_change#,open_mode,current_scn FROM v$database;
SCN locatio NAME CHECKPOINT_CHANGE# OPEN_MODE CURRENT_SCN
----------- -------------------------------------------------- -------------------- ---------- --------------------
controlfile SYSTEM checkpoint 14532985241970 MOUNTED 0
select sysdate,
(((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 n30 from dual;
SYSDATE N30
------------------- -------------------------------
2015-08-06 10:43:23 14532952113152
SYS@test> select (14532985241970-14532952113152)/16384/60 from dual;
(14532985241970-14532952113152)/16384/60
----------------------------------------
33.70037638346354167
SYS@test> alter database open ;
alter database open
*
ERROR at line 1:
ORA-00600: internal error code, arguments: [2252], [3383], [3110879602], [], [], [], [], []
select 14532985241970,trunc(14532985241970/power(2,32)) scn_wrap,mod(14532985241970,power(2,32)) scn_base from dual
14532985241970 SCN_WRAP SCN_BASE
-------------------- -------------------- --------------------
14532985241970 3383 3110879602
--可以发现后面两个参数是SCN_WRAP,SCN_BASE.等33分钟看看情况吧。
SYSDATE N30
------------------- -------------------------------
2015-08-06 11:22:28 14532990533632
SYS@test> alter database open ;
Database altered.
--可以打开了。