在2012年第一季度的CPU補丁中,包含了一個關於SCN修正的重要變更,這個補丁提示,在異常情況下,Oracle的SCN可能出現異常增長,使得數據庫的一切事務停止,由於SCN不能後退,所以數據庫必須重建,才能夠重用。
我曾經在以下鏈接中描述過這個問題:
http://www.eygle.com/archives/2012/03/Oracle_scn_bug_exhaused.Html
Oracle使用6 Bytes記錄SCN,也就是48位,其最大值是:
- SQL> col scn for 999,999,999,999,999,999
- SQL> select power(2,48) scn from dual;
- SCN
- ------------------------
- 281,474,976,710,656
Oracle在內部控制每秒增減的SCN不超過 16K,按照這樣計算,這個數值可以使用大約544年:
- SQL> select power(2,48) / 16 / 1024 / 3600 / 24 / 365 from dual;
- POWER(2,48)/16/1024/3600/24/365
- -------------------------------
- 544.770078
然而在出現異常時,尤其是當使用DB Link跨數據庫查詢時,SCN會被同步,在以下鏈接中,我曾經描述過此問題:
http://www.eygle.com/archives/2006/11/db_link_checkpoint_scn.Html
一個數據庫當前最大的可能SCN被稱為"最大合理SCN",該值可以通過如下方式計算:
- col scn for 999,999,999,999,999,999
- 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。
這個內容可以參考如下鏈接:
http://www.eygle.com/archives/2006/01/how_big_scn_can_be.Html
在CPU補丁中,Oracle提供了一個腳本 scnhealthcheck.sql 用於檢查數據庫當前SCN的剩余情況。
該腳本的算法和以上描述相同,最終將最大合理SCN 減去當前數據庫SCN,計算得出一個指標:HeadRoom。也就是SCN尚余的頂部空間,這個頂部空間最後折合成天數:
以下是這個腳本的內容:
- Rem
- Rem $Header: rdbms/admin/scnhealthcheck.sql st_server_tbhukya_bug-13498243/8 2012/01/17 03:37:18 tbhukya Exp $
- Rem
- Rem scnhealthcheck.sql
- Rem
- Rem Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- Rem
- Rem NAME
- Rem scnhealthcheck.sql - Scn Health check
- Rem
- Rem DESCRIPTION
- Rem Checks scn health of a DB
- Rem
- Rem NOTES
- Rem .
- Rem
- Rem MODIFIED (MM/DD/YY)
- Rem tbhukya 01/11/12 - Created
- Rem
- Rem
- define LOWTHRESHOLD=10
- define MIDTHRESHOLD=62
- define VERBOSE=FALSE
- set veri off;
- set feedback off;
- set serverout on
- DECLARE
- verbose boolean:=&&VERBOSE;
- BEGIN
- For C in (
- 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
- )
- ) LOOP
- dbms_output.put_line( '-----------------------------------------------------'
- || '---------' );
- dbms_output.put_line( 'ScnHealthCheck' );
- dbms_output.put_line( '-----------------------------------------------------'
- || '---------' );
- dbms_output.put_line( 'Current Date: '||C.date_time );
- dbms_output.put_line( 'Current SCN: '||C.current_scn );
- if (verbose) then
- dbms_output.put_line( 'SCN Headroom: '||round(C.indicator,2) );
- end if;
- dbms_output.put_line( 'Version: '||C.version );
- dbms_output.put_line( '-----------------------------------------------------'
- || '---------' );
- IF C.version > '10.2.0.5.0' and
- C.version NOT LIKE '9.2%' THEN
- IF C.indicator>&MIDTHRESHOLD THEN
- dbms_output.put_line('Result: A - SCN Headroom is good');
- dbms_output.put_line('Apply the latest recommended patches');
- dbms_output.put_line('based on your maintenance schedule');
- IF (C.version < '11.2.0.2') THEN
- dbms_output.put_line('AND set _external_scn_rejection_threshold_hours='
- || '24 after apply.');
- END IF;
- ELSIF C.indicator<=&LOWTHRESHOLD THEN
- dbms_output.put_line('Result: C - SCN Headroom is low');
- dbms_output.put_line('If you have not already done so apply' );
- dbms_output.put_line('the latest recommended patches right now' );
- IF (C.version < '11.2.0.2') THEN
- dbms_output.put_line('set _external_scn_rejection_threshold_hours=24 '
- || 'after apply');
- END IF;
- dbms_output.put_line('AND contact Oracle support immediately.' );
- ELSE
- dbms_output.put_line('Result: B - SCN Headroom is low');
- dbms_output.put_line('If you have not already done so apply' );
- dbms_output.put_line('the latest recommended patches right now');
- IF (C.version < '11.2.0.2') THEN
- dbms_output.put_line('AND set _external_scn_rejection_threshold_hours='
- ||'24 after apply.');
- END IF;
- END IF;
- ELSE
- IF C.indicator<=&MIDTHRESHOLD THEN
- dbms_output.put_line('Result: C - SCN Headroom is low');
- dbms_output.put_line('If you have not already done so apply' );
- dbms_output.put_line('the latest recommended patches right now' );
- IF (C.version >= '10.1.0.5.0' and
- C.version <= '10.2.0.5.0' and
- C.version NOT LIKE '9.2%') THEN
- dbms_output.put_line(', set _external_scn_rejection_threshold_hours=24'
- || ' after apply');
- END IF;
- dbms_output.put_line('AND contact Oracle support immediately.' );
- ELSE
- dbms_output.put_line('Result: A - SCN Headroom is good');
- dbms_output.put_line('Apply the latest recommended patches');
- dbms_output.put_line('based on your maintenance schedule ');
- IF (C.version >= '10.1.0.5.0' and
- C.version <= '10.2.0.5.0' and
- C.version NOT LIKE '9.2%') THEN
- dbms_output.put_line('AND set _external_scn_rejection_threshold_hours=24'
- || ' after apply.');
- END IF;
- END IF;
- END IF;
- dbms_output.put_line(
- 'For further information revIEw MOS document id 1393363.1');
- dbms_output.put_line( '-----------------------------------------------------'
- || '---------' );
- END LOOP;
- end;
- /
在應用補丁之後,一個新的隱含參數 _external_scn_rejection_threshold_hours 引入,通常設置該參數為 24 小時:
_external_scn_rejection_threshold_hours=24
這個設置降低了SCN Headroom的頂部空間,以前缺省的設置容量至少為31天,降低為 24 小時,可以增大SCN允許增長的合理空間。
但是如果不加控制,SCN仍然可能會超過最大的合理范圍,導致數據庫問題。
這個問題的影響會極其嚴重,我們建議用戶檢驗當前數據庫的SCN使用情況,以下是檢查腳本的輸出范例:
- --------------------------------------
- ScnHealthCheck
- --------------------------------------
- Current Date: 2012/01/15 14:17:49
- Current SCN: 13194140054241
- Version: 11.2.0.2.0
- --------------------------------------
- Result: C - SCN Headroom is low
- If you have not already done so apply
- the latest recommended patches right now
- AND contact Oracle support immediately.
- For further information revIEw MOS document id 1393363.
- --------------------------------------
這個問題已經出現在客戶環境中,需要引起大家的足夠重視