由於通過database link進行遠程數據庫的數據讀取時,會自動同步當前庫和遠程庫的SCN,老楊在文章中做過描述,並且提到:
而對於實際環境中,SCN的增加可能是幾倍、幾十倍甚至是上百倍,從而引發一些其他的bug。
下面就來看一個問題。該錯誤會在應用了2012年1月份CPU的Oracle數據庫中出現,而在原始版本中,比如10.2.0.5.0之中不會出現此錯誤。
--通過dblink進行簡單的查詢報ORA-19706錯誤
SQL> SELECT sysdate FROM dual@AIX12;
SELECT sysdate FROM dual@AIX12
ORA-19706: invalid SCN
--登錄遠程庫,檢查SCN,很大的一個數字
SQL> SELECT current_scn FROM v$database;
CURRENT_SCN
-----------
12763142641
--而當前庫,由於新創建,所以SCN並不大,與遠程庫想比相差幾個數量級
SQL> SELECT current_scn FROM v$database;
CURRENT_SCN
-----------
5017684
看一下ORA-19706錯誤的解釋。可以看到too large是產生該問題的原因之一。
$oerr ora 19706
19706, 00000, "invalid SCN"
// *Cause: The input SCN is either not a positive integer or too large.
// *Action: Check the input SCN and make sure it is a valid SCN.
SCN是一個可以容納很長時間的數字,爲什麼會出現too large的情況呢?這是由於SCN有headroom限制的原因,headroom是一個固定值,從1988年開始計算,以每秒16K的速度遞增。當突然請求的SCN超過跟SCN headroom之間允許的差值時,則會出現ORA-19706錯誤。
詳細的解釋可以參看MOS Note – System Change Number (SCN), Headroom, Security and Patch Information [ID 1376995.1]。
解決方法:
1. 設置隱含參數_external_scn_rejection_threshold_hours,具體解釋可以參看:
MOS Note – Installing, Executing and Interpreting output from the “scnhealthcheck.sql” script [ID 1393363.1]。
該參數在10.2.0.5中默認是744,設置爲24通常可以解決問題(表示允許跟headroom之間的差距相差24小時)。
SQL> ALTER system SET "_external_scn_rejection_threshold_hours"=24 scope=spfile;
也就是如果遠端數據庫的SCN由於某些bug導致異常增長,那麼這個SCN跟headroom之間的差距將會低於默認值744小時(31天),當本地數據庫(打了2012年1月份CPU補丁後的)通過dblink查詢遠端數據,由於SCN同步機制,本地數據庫嘗試將SCN同步爲跟遠端一樣大小,但是這個值超過了跟SCN headroom之間允許的差值,因此報錯。
實際上具體設置的值應該根據上面MOS文檔中scnhealthcheck.sql的結果,該SQL應該在遠端數據庫中運行(或者說在具有最大的SCN的數據庫中運行),假設運行結果顯示:
SCN Headroom: 14.55
那麼則表示目前SCN距離headroom只有14.55天的空間,此時我們將_external_scn_rejection_threshold_hours參數設置爲13*24=312,即可解決問題。但是要注意,遠端數據庫SCN仍在不停異常增長,等到某一天遠端數據庫的SCN Headroom降低爲小於13天的時候,ORA-19706錯誤又會再次出現。
2. 回滾打上的2012年1月份CPU。當然這並不是推薦的方法。
3. 最終極的解決方案,將環境中所有通過dblink互相連接的數據庫全部打上最新的PSU,比如目前10205的最新PSU是10.2.0.5.7,這將會解決所有SCN異常增長的問題,只要數據庫每秒增長的SCN不會超過16K,那麼就會離headroom越來越遠。
原文地址:http://www.dbform.com/html/2012/1846.html