程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle數據庫基礎 >> Oracle安全:SCN可能最大值與耗盡問題

Oracle安全:SCN可能最大值與耗盡問題

編輯:Oracle數據庫基礎

在2012年第一季度的CPU補丁中,包含了一個關於SCN修正的重要變更,這個補丁提示,在異常情況下,Oracle的SCN可能出現異常增長,使得數據庫的一切事務停止,由於SCN不能後退,所以數據庫必須重建,才能夠重用。

我曾經在以下鏈接中描述過這個問題:

http://www.eygle.com/archives/2012/03/Oracle_scn_bug_exhaused.Html

Oracle使用6 Bytes記錄SCN,也就是48位,其最大值是:

  1. SQL> col scn for 999,999,999,999,999,999
  2. SQL> select power(2,48) scn from dual;
  3. SCN
  4. ------------------------
  5. 281,474,976,710,656


Oracle在內部控制每秒增減的SCN不超過 16K,按照這樣計算,這個數值可以使用大約544年:

  1. SQL> select power(2,48) / 16 / 1024 / 3600 / 24 / 365 from dual;
  2. POWER(2,48)/16/1024/3600/24/365
  3. -------------------------------
  4. 544.770078


然而在出現異常時,尤其是當使用DB Link跨數據庫查詢時,SCN會被同步,在以下鏈接中,我曾經描述過此問題:

http://www.eygle.com/archives/2006/11/db_link_checkpoint_scn.Html

一個數據庫當前最大的可能SCN被稱為"最大合理SCN",該值可以通過如下方式計算:

  1. col scn for 999,999,999,999,999,999
  2. select
  3. (
  4. (
  5.  (
  6. (
  7. (
  8. (
  9. to_char(sysdate,'YYYY')-1988
  10. )*12+
  11. to_char(sysdate,'mm')-1
  12. )*31+to_char(sysdate,'dd')-1
  13. )*24+to_char(sysdate,'hh24')
  14. )*60+to_char(sysdate,'mi')
  15. )*60+to_char(sysdate,'ss')
  16. ) * to_number('ffff','XXXXXXXX')/4 scn
  17. from dual
  18. /

這個算法即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尚余的頂部空間,這個頂部空間最後折合成天數:

以下是這個腳本的內容:

  1. Rem
  2. Rem $Header: rdbms/admin/scnhealthcheck.sql st_server_tbhukya_bug-13498243/8 2012/01/17 03:37:18 tbhukya Exp $
  3. Rem
  4. Rem scnhealthcheck.sql
  5. Rem
  6. Rem Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
  7. Rem
  8. Rem NAME
  9. Rem scnhealthcheck.sql - Scn Health check
  10. Rem
  11. Rem DESCRIPTION
  12. Rem Checks scn health of a DB
  13. Rem
  14. Rem NOTES
  15. Rem .
  16. Rem
  17. Rem MODIFIED (MM/DD/YY)
  18. Rem tbhukya 01/11/12 - Created
  19. Rem
  20. Rem
  21. define LOWTHRESHOLD=10
  22. define MIDTHRESHOLD=62
  23. define VERBOSE=FALSE
  24. set veri off;
  25. set feedback off;
  26. set serverout on
  27. DECLARE
  28. verbose boolean:=&&VERBOSE;
  29. BEGIN
  30. For C in (
  31. select
  32. version,
  33. date_time,
  34.  dbms_Flashback.get_system_change_number current_scn,
  35. indicator
  36. from
  37. (
  38. select
  39. version,
  40. to_char(SYSDATE,'YYYY/MM/DD HH24:MI:SS') DATE_TIME,
  41. ((((
  42. ((to_number(to_char(sysdate,'YYYY'))-1988)*12*31*24*60*60) +
  43. ((to_number(to_char(sysdate,'MM'))-1)*31*24*60*60) +
  44. (((to_number(to_char(sysdate,'DD'))-1))*24*60*60) +
  45. (to_number(to_char(sysdate,'HH24'))*60*60) +
  46. (to_number(to_char(sysdate,'MI'))*60) +
  47. (to_number(to_char(sysdate,'SS')))
  48. ) * (16*1024)) - dbms_Flashback.get_system_change_number)
  49. / (16*1024*60*60*24)
  50. ) indicator
  51. from v$instance
  52. )
  53. ) LOOP
  54. dbms_output.put_line( '-----------------------------------------------------'
  55. || '---------' );
  56. dbms_output.put_line( 'ScnHealthCheck' );
  57. dbms_output.put_line( '-----------------------------------------------------'
  58. || '---------' );
  59. dbms_output.put_line( 'Current Date: '||C.date_time );
  60. dbms_output.put_line( 'Current SCN: '||C.current_scn );
  61. if (verbose) then
  62. dbms_output.put_line( 'SCN Headroom: '||round(C.indicator,2) );
  63. end if;
  64. dbms_output.put_line( 'Version: '||C.version );
  65. dbms_output.put_line( '-----------------------------------------------------'
  66. || '---------' );
  67. IF C.version > '10.2.0.5.0' and
  68. C.version NOT LIKE '9.2%' THEN
  69. IF C.indicator>&MIDTHRESHOLD THEN
  70. dbms_output.put_line('Result: A - SCN Headroom is good');
  71. dbms_output.put_line('Apply the latest recommended patches');
  72. dbms_output.put_line('based on your maintenance schedule');
  73. IF (C.version < '11.2.0.2') THEN
  74. dbms_output.put_line('AND set _external_scn_rejection_threshold_hours='
  75. || '24 after apply.');
  76. END IF;
  77. ELSIF C.indicator<=&LOWTHRESHOLD THEN
  78. dbms_output.put_line('Result: C - SCN Headroom is low');
  79. dbms_output.put_line('If you have not already done so apply' );
  80. dbms_output.put_line('the latest recommended patches right now' );
  81. IF (C.version < '11.2.0.2') THEN
  82. dbms_output.put_line('set _external_scn_rejection_threshold_hours=24 '
  83. || 'after apply');
  84. END IF;
  85. dbms_output.put_line('AND contact Oracle support immediately.' );
  86.  ELSE
  87. dbms_output.put_line('Result: B - SCN Headroom is low');
  88. dbms_output.put_line('If you have not already done so apply' );
  89. dbms_output.put_line('the latest recommended patches right now');
  90. IF (C.version < '11.2.0.2') THEN
  91. dbms_output.put_line('AND set _external_scn_rejection_threshold_hours='
  92. ||'24 after apply.');
  93. END IF;
  94. END IF;
  95. ELSE
  96. IF C.indicator<=&MIDTHRESHOLD THEN
  97. dbms_output.put_line('Result: C - SCN Headroom is low');
  98. dbms_output.put_line('If you have not already done so apply' );
  99. dbms_output.put_line('the latest recommended patches right now' );
  100. IF (C.version >= '10.1.0.5.0' and
  101. C.version <= '10.2.0.5.0' and
  102. C.version NOT LIKE '9.2%') THEN
  103. dbms_output.put_line(', set _external_scn_rejection_threshold_hours=24'
  104. || ' after apply');
  105. END IF;
  106. dbms_output.put_line('AND contact Oracle support immediately.' );
  107. ELSE
  108. dbms_output.put_line('Result: A - SCN Headroom is good');
  109. dbms_output.put_line('Apply the latest recommended patches');
  110. dbms_output.put_line('based on your maintenance schedule ');
  111. IF (C.version >= '10.1.0.5.0' and
  112. C.version <= '10.2.0.5.0' and
  113. C.version NOT LIKE '9.2%') THEN
  114. dbms_output.put_line('AND set _external_scn_rejection_threshold_hours=24'
  115. || ' after apply.');
  116. END IF;
  117. END IF;
  118. END IF;
  119. dbms_output.put_line(
  120. 'For further information revIEw MOS document id 1393363.1');
  121. dbms_output.put_line( '-----------------------------------------------------'
  122. || '---------' );
  123. END LOOP;
  124. end;
  125. /

在應用補丁之後,一個新的隱含參數 _external_scn_rejection_threshold_hours 引入,通常設置該參數為 24 小時:

_external_scn_rejection_threshold_hours=24

這個設置降低了SCN Headroom的頂部空間,以前缺省的設置容量至少為31天,降低為 24 小時,可以增大SCN允許增長的合理空間。

但是如果不加控制,SCN仍然可能會超過最大的合理范圍,導致數據庫問題。

這個問題的影響會極其嚴重,我們建議用戶檢驗當前數據庫的SCN使用情況,以下是檢查腳本的輸出范例:

  1. --------------------------------------
  2. ScnHealthCheck
  3. --------------------------------------
  4. Current Date: 2012/01/15 14:17:49
  5.  Current SCN: 13194140054241
  6. Version: 11.2.0.2.0
  7. --------------------------------------
  8. Result: C - SCN Headroom is low
  9. If you have not already done so apply
  10. the latest recommended patches right now
  11. AND contact Oracle support immediately.
  12. For further information revIEw MOS document id 1393363.
  13. --------------------------------------

這個問題已經出現在客戶環境中,需要引起大家的足夠重視

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved