ITPub博客

首页 > 数据库 > Oracle > 第70期 检查大名鼎鼎的SCN 急速增长漏洞的脚本

第70期 检查大名鼎鼎的SCN 急速增长漏洞的脚本

原创 Oracle 作者:pxbibm 时间:2026-07-09 09:27:02 0 删除 编辑
define LOWTHRESHOLD=10
define MIDTHRESHOLD=62
define VERBOSE=TRUE
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;
/

scnhealthcheck.sql 完整深度解析

一、脚本来源与背景

  1. 文件归属:Oracle TFA/ORACH K 内置巡检脚本( orach k 是 Oracle 官方数据库健康检查工具)

  2. 核心背景:大名鼎鼎  SCN 急速增长漏洞(MOS 1393363.1)

    Oracle 旧版本存在缺陷:外部工具(Data Pump、GoldenGate、dblink、外部客户端)可推送超大 SCN,快速耗尽数据库可用 SCN 空间;SCN 存在理论上限,一旦耗尽数据库直接宕机无法写入,属于致命故障。该脚本用来提前测算 剩余可用 SCN 余量(SCN Headroom,SCN 剩余可用天数),分级预警风险。

二、核心概念说明

  1. SCN(System Change Number)数据库全局递增序列号,所有事务、数据修改都分配 SCN,有最大上限阈值。
  2. SCN Headroom(脚本核心指标 indicator)单位: 天含义:以当前时间增长速度,数据库距离 SCN 耗尽还能正常运行多少天。数值越小风险越高:很快 SCN 耗尽,数据库写操作阻塞宕机。
  3. 阈值定义(脚本开头宏变量)

define LOWTHRESHOLD=10  -- 剩余≤10天:高危C级,立刻打补丁+联系Oracle支持
define MIDTHRESHOLD=62  -- 10<剩余≤62天:中危B级,尽快补丁-- >62天:安全A级
define VERBOSE=FALSE    -- 是否打印详细Headroom数值

     4.隐藏参数 _external_scn_rejection_threshold_hours=24补丁配套参数:拦截外部传入超过 24 小时的超大 SCN,防止外部工具恶意 / 异常推高 SCN。

三、脚本逐段拆解

1. 宏定义 & SQLPlus 环境配置

define LOWTHRESHOLD=10
define MIDTHRESHOLD=62
define VERBOSE=FALSE
set veri off;
set feedback off;
set serverout on
  • 关闭校验、执行反馈,开启输出打印巡检结果;

  • 可执行时传参修改阈值: define VERBOSE=TRUE 输出精确剩余天数。

2. 核心计算公式(indicator = SCN 剩余可用天数)

indicator = 
(
  (
    (基准时间换算总秒数)*16*1024 
    - 当前系统SCN(dbms_flashback.get_system_change_number)
  ) / (16*1024*60*60*24)
)
公式逻辑:

  1. Oracle 标准 SCN 速率: 每 1 秒最大消耗 16*1024 = 16384 个 SCN

  2. 用固定时间基准算出理论最大允许 SCN;

  3. 减去当前已使用 SCN,得到剩余 SCN 总量;

  4. 除以一天总秒数 × 每秒最大 SCN,换算为 剩余可用天数。

3. 查询数据源

select
 version, -- 数据库版本
 to_char(SYSDATE,'YYYY/MM/DD HH24:MI:SS') DATE_TIME, -- 当前时间
 dbms_flashback.get_system_change_number current_scn, -- 当前实时SCN
 indicator -- 计算出的剩余可用天数
from v$instance
单实例 / RAC 单节点执行,读取实例版本、实时 SCN,算出风险指标。

4. 分级判断逻辑(按数据库版本分支)

脚本分两大版本区间做差异化判断:

分支 1:版本 >10.2.0.5 且不是 9i(11g、12c 主流版本)

  1. indicator >62 → A 安全:按计划定期打补丁

  2. 10<indicator ≤62 → B 中危:立刻打最新补丁

  3. indicator ≤10 → C 高危:紧急补丁 + 立刻联系 Oracle 技术支持

    11.2.0.2 以下版本打完补丁必须配置 _external_scn_rejection_threshold_hours=24

分支 2:10.1.0.5 ~ 10.2.0.5(10g 老版本)

  1. indicator ≤62 → C 高危,紧急处理
  2. indicator >62 → A 安全
10g 区间打完补丁强制配置拦截参数

5. 输出内容

  • 当前时间、实时 SCN、数据库版本

  • 可选输出精确剩余天数(VERBOSE=TRUE)

  • 风险等级 A/B/C + 补丁操作指引

  • 关联 MOS 文档:1393363.1(SCN 耗尽故障官方说明)

四、风险等级对照表

等级 剩余 SCN 天数 (indicator) 风险 处置要求
A 安全 >62 天 低 日常维护周期打补丁
B 预警 10~62 天 中 立即安排停机打 SCN 修复补丁
C 紧急 ≤10 天 极高 立刻停机维护、打补丁、联系 Oracle Support

五、使用场景

场景 1:数据库上线前验收巡检

新上线 10g/11g 老旧库,执行脚本检查 SCN 余量,规避上线后短期宕机风险。

场景 2:ORACH K/TFA 自动化巡检标配

Oracle 官方巡检工具内置此脚本,每日自动输出巡检报告,作为高危项告警。

场景 3:OGG/DATAPUMP 大量同步业务库

OGG、dblink、外部客户端极易推送外部超大 SCN,加速 SCN 消耗;定期执行监控余量。

场景 4:老旧 10g/11g 无补丁环境月度安全巡检

无计划升级的历史业务库,每月跑脚本预判宕机窗口期,预留维护窗口。

场景 5:故障事后排查

数据库出现 ORA-19969/ORA-22924 SCN 相关报错,用脚本快速确认是否 SCN 余量耗尽。

场景 6:等保、安全基线核查

数据库安全检查必查项,证明已监控 SCN 耗尽高危漏洞。

六、真实业务案例

案例 1:高危 C 级故障预警(剩余 8 天)

  1. 环境:Oracle 11.2.0.1,大量 OGG 双向同步,未打 SCN 修复补丁
  2. 脚本输出:


Current Date: 2026/07/09 15:30:22
Current SCN:  14289654721
Version:      11.2.0.1.0
Result: C - SCN Headroom is low
If you have not already done so apply
the latest recommended patches right now
set _external_scn_rejection_threshold_hours=24 after apply
AND contact Oracle support immediately.
    3.根因:OGG 同步持续推送外部 SCN,SCN 消耗速度远超正常业务,仅剩 8 天耗尽。
    4.处置:
      1)紧急停机安装 SCN 修复补丁;
      2)参数文件添加 _external_scn_rejection_threshold_hours=24;3)重启数据库,拦截外部超大 SCN,Headroom 恢复至 300 + 天。

案例 2:中危 B 级预警(剩余 45 天)

  1. 环境:11.2.0.1 生产交易库,存在第三方 dblink 同步数据
  2. 脚本返回 B 级预警;
  3. 处置:下一周维护窗口批量打 CPU 季度补丁,配置拦截参数,消除风险。

案例 3:A 级安全(剩余 128 天)

  1. 环境:19c 新版本数据库,官方已内置 SCN 防护机制;

  2. 脚本输出 A 安全,仅提示按季度更新补丁,无紧急操作。

案例 4:10.2.0.5 老库高危故障

  1. 数据库 10g,无补丁,脚本显示剩余 5 天;

  2. 若未及时处理,5 天后数据库所有 DML、DDL 直接报错,业务完全中断;

  3. 临时应急:断开所有 dblink、OGG 同步减缓 SCN 上涨,连夜停机打补丁。

七、执行与扩展用法

1. 基础执行(默认不打印精确天数)

sqlplus / as sysdba @scnhealthcheck.sql

2. 输出详细剩余天数(开启 VERBOSE)

define VERBOSE=TRUE@scnhealthcheck.sql
会多一行输出: SCN Headroom: 126.35 代表剩余 126.35 天。

3. 关键 MOS 参考文档

MOS ID: 1393363.1 - ORA-19969 / ORA-22924 Database Cannot Allocate New SCN (SCN Wraparound)文档说明 SCN 耗尽故障原理、补丁清单、隐藏参数配置方案。

八、补充重要说明

  1. 12cR2/18c/19c 新版本内核已修复该 SCN 漏洞,脚本大多返回 A 级安全,但仍建议定期巡检;
  2. 仅打补丁不配置 _external_scn_rejection_threshold_hours=24 防护参数,无法完全拦截外部异常 SCN;
  3. 脚本仅做 预判测算,不能修复 SCN 耗尽问题,预警后必须通过补丁 + 参数根治;
  4. 若 Headroom 持续快速下降,需排查 OGG、dblink、第三方 ETL 工具是否异常推送超大 SCN。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12798004/viewspace-3175501/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle ACE。ACOUG核心成员,Oracle用户组年轻专家。熟悉Oracle的体系结构,擅长Oracle数据库架构规划、SQL优化、OWI方面性能的优化。曾服务于航天、航空、机车、大型制造行业数据库的维护以及系统开发工作,开发过基于Oracle数据库的大型ERP系统。
  • 博文量
    345
  • 访问量
    2477883