暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

ORA-19706 和_external_scn_rejection_threshold_hours 的前世今生

白鳝的洞穴 2020-03-24
1534
下面的文章是老白发在ORACLEFANS网站上的一篇文章的基础上修改的。当时SCN HEADROOM的问题四处肆虐,老白也参加了几次救火,随后写了这篇文章。
最近这几天和几个客户一直在讨论一个最近爆发的ORA-19706 的故障。在一个数据库访问另外一个数据库的时候出现了:


错误,在ALERT LOG 中,也发现了一些报警信息:

Rejected the attempt to advance SCN over limit by 13 hours worth to

0x0bd8.0000133b, by distributed transaction remote logon, remote DB:

ORA10G.


通过MOS 查到了这是SCN HEEADROOM 的问题,我们暂且称之为SCN 天花板。MOS 的建议是下载并安装最新的PSU,并设置参数_external_scn_rejection_threshold_hours 为24。刚开始的时候并没有搞明白这个参数具体的含义。确实设置这个参数后,问题就没有再出现了。不过随着关于这个问题讨论的深入,很多疑问又冒了出来。特别是周末时和美国ORACLE 的一个哥们在MSN 上聊到此事,那个哥们说是由于客户安装了CPU 2012 JAN 安全补丁,才出现很多用户出现了ORA-19706 的问题。回退了这个补丁,问题就解决了。而且这个问题在ORACLE 内部讳莫如深,他们也不太清楚具体的原因是什么。


(本贴附件为各个版本的oracle 公司提供的scnhealthcheck.sql,实际上各个版本(11g 之前)的差异不是很大,部分打了补丁的11g 的系统,每秒SCN 增长阀值被加大为32K了)

今天正好没什么事,和几个DBA 又讨论起这个问题,于是我仔细翻阅了一些资料。终于把整个故事都搞明白了。ORACLE 的CPU 2012 JAN 确实对SCN 的算法做出了一系列的改进。这起源于INFOWORLD 在2011 年底发现的ORACLE 的一个安全漏洞。关于这个安全漏洞的故事,可以参考http://www.infoworld.com/d/security/fundamental-oracle-flaw-revealed-184163-0?page=0,0 。这里我简单介绍一下这个故事:

INFOWORLD 在一个测试中,发现ORACLE 11.2 中存在一个BEGIN BACKUP 的BUG,也就是当执行了ALTER DATABASE BEGIN BACKUP 后,SCN 会增长的超出正常水平,使数据库很快达到SCN 的软限制(SCN HEADROOM),一旦达到了这个限制,数据库将无法正常处理事务,甚至严重时导致宕机。更有甚者,当SCN 超过HEADROOM 的时候,可能会导致数据库出现ORA-600 [2252]而无法启动数据库(当然ORACLE 有很多保护机制,很少会出现超出的情况)。这个问题在INFOWORLD 发现之前,ORACLE 已经有所发现,就是Bug 12371955 - Hot Backup can cause increased SCN growth rate leading to ORA-600 [2252] errors [ID 12371955.8]。目前这个BUG 已经解决,并且不会出现在11g 之前的版本中。

INFOWORLD 在发现这个问题后,在进一步的测试发现更严重的问题,就是DBLINK 的SCN 同步机制。为了实现分布式处理,ORACLE 在多个库做DBLINK 访问的时候,会将SCN 进行同步,也就是将较高的SCN 同步参与DBLINK 的两个库的SCN,执行DBLINK 操作后,两个库的SCN就同步了。这个机制就可能把SCN 增长异常传播到所有的数据库服务器上。也就是说,如果一个服务级别很低的报表服务器出现故障,可能会影响服务级别特别高的生产服务器。INFOWORLD 把这个问题报告给了ORACLE,并一起进行了一系列的工作,于是在CPU 2012 JAN 中出现了对这个DBLINK 问题的补丁。在介绍这个补丁之前,我们先来了解一段ORACLE SCN 的背景资料。

背景:

ORACLE SCN 的硬限制和软限制:ORACLE 的SCN 是由48 位来表示的,因此最大值不能超过2 的48 次方,这就是ORACLE scn 的硬限制。Oracle 为了确保48 位的SCN 能够用足够长的时间(500 年),于是对SCN 做出了一个限制,就是每秒钟SCN 最大增长不能超过16K,Oracle 使用了一个十分简单的算法,就是以从1988 年1 月1 日0 点0 分0 秒为基准时间,到当前的秒钟数乘以16K,就是当前SCN 的最大允许值这就是SCN HEADROOM。如果在某个时刻SCN 达到了这个最大值,那么事务就无法提交,需要等到下一秒,这个HEAD ROOM又变大了,才能继续进行事务的提交。

关于这些背景资料请参考:

NOTE:1376995.1 - Information on the System Change Number (SCN) and ho

w it is used in the Oracle Database

NOTE:1393363.1 - Installing, Executing and Interpreting output from the

"SCNhealthcheck.sql" script

NOTE:1388639.1 - Evidence to collect when reporting "high SCN rate" i

ssues to Oracle Support

NOTE:1393360.1 - ORA-19706 and Related Alert Log Messages




对于INFOWORLD 发现的问题,ORACLE 采取了两个很重要的手段,一个是在11.2 中,将SCN 每秒最大的增长量从16K 加大为32K,第二个是引入了一个阀值,用于阻断有SCN HEADROOM问题的系统将故障传播到其他系统。这个修复包含在CPU 2012 JAN 中,打了这个补丁后,我们可以设置一个参数_external_scn_rejection_threshold_hours。这个参数的含义是,当有一个系统和我进行DBLINK 操作的时候,我需要检查他的SCN HEADROOM 的值,如果这个系统的SCN HEADROOM 的值小于这个参数所设置的小时数,那么我就拒绝这个DBLINK 访问(如果DBLINK 两端的数据库都打了补丁,设置了参数,这种检查是双向的),通过拒绝DBLINK 访问,来避免错误被传播。


由于10G 的这个补丁打了后,_external_scn_rejection_threshold_hours 的缺省值是31天(31*24),是个十分大的值,因此很多系统打了这个补丁后,就出现ORA-19706 错误了。而回退了这个补丁后,这方面的限制取消了,报错就没有了。不过隐患就出现了。

实际上这个问题包含两个方面,一方面是如何防止问题的发生,就是防止核心生产系统出现SCN 增长异常的问题出现。目前发现的一系列BUG 都已经得到了控制,包括那个INFOWORLD发现的BEGIN BACKUP 的问题。还有bug13916709,这个补丁是为了修复另外一个SCN BUG而引发的。当一个长时间运行的SQL 和DDL,job 或者GATHER 操作一起执行的时候,会引起CURSOR INVALIDATE,从而触发SCN 异常增长。

另外一个方面是如何在某个系统发生故障的时候,阻止这个故障的传播。CPU 2012 JAN就是用来解决这个问题的,不过这个补丁也摆了一个乌龙,在10g 上,新引入的参数的缺省值太大,需要设置为24,以避出现过多的ORA-19706。如果由于目前系统的SCN 已经比较高了,设置为24 还无法避免ORA-19706,可以尝试进一步减小这个参数。很多客户把这个参数减少为1,这样可以最大限度的减少ORA-19706,不过设置为1,存在一定的隐患,一旦系统遇到了一个人新的SCN 增长过快的BUG,那么,可能我们都没有时间来解决这个问题,建议尽可能不要设置这么低。

事实上,ORACLE 的这些补丁解决了一部分SCN 异常增长的情况,也防止了异常增长的扩散,不过仅仅这些还是没有彻底解决这个问题。如果SCN HEADROOM 的问题出现在一个核心系统上,那么哪怕它没有被扩散,那么核心系统业务受到影响也是无法容忍的。因此我们需要做的事情还更多,特别是如何发现SCN 的异常增长,这就需要我们经常性的对数据库进行监控,并把SCN HEADROOM 检查作为标准的健康检查项,定期进行检查。

Oracle 发布了一个补丁Patch:13498243,这个补丁实际上包含的就是一个脚本scnhealthcheck.ql,通过这个脚本可以检查目前本系统的SCN HEADROOM(单位为天),如果SCNHEADROOM 大于62,那么说明这个系统没有SCN HEADROOM 问题,如果小于62 大于10,说明存在问题,不过还不致命。如果小于10,那么就说明问题十分严重,必须立即处理了。实际上这个脚本的核心是以下的SQL:

除了这个脚本外,我们还可以通过以下手段进行检查(以下建议来自于

Doc ID 1393383.1):

1、经常性检查"calls to kcmgas"系统调用的情况,并建立基线数据。这个指标可以从V$SYSSTATE 去查找,也可以通过AWR 查找历史数据(在AWR 数据中查找历史统计数据的方法参考How to extract the historical values of a statistic from AWR Repository [ID 948272.1])。也可以通过下面的脚本检查某个会话的情况:


2、如果本机的这个调用很少,那么很可能故障是从别的机器传播过来的,如果要查找哪个远程服务器经常连接到某个数据库,可以通过下面的方法:A)对于已经打了补丁的系统,当SCN 传播发生时,ALERT LOG 中会有记录,可以通过ALERT LOG 查找问题的系统。

Advanced SCN by 13238271 minutes worth to 0x0bd6.00000f21, by distribu

ted transaction remote logon, remote DB: ORA10G.

Client info : DB logon user SCOTT, machine gc, program sqlplus@gc

(TNS V1-V3), and OS user oracle

3、除了上面的脚本外,ORACLE 官方还在

How to handle "high SCN rate" Service Requests (Doc ID 1393383.1 中提

供了一个脚本,可以查找历史的SCN HEADROOM:











解决方式:

Oracle 官方关于这个问题的解决方案中,还有两条,一是在今后的版本中将SCN 扩展到64位,第二是今后的版本中可能进一步加大SCN HEADROOM 为更大的值,因为目前已经出现了每秒超过16K 个事务的系统。

如果你的系统已经出现了问题,发现某台核心系统的SCN 被传染了,想要找出是哪些系统和本机有DBLINK 连接,可以通过两个方法,一是通过系统的LOGON 触发器,记录LOGON 的情况,二是通过LOGON 审计,将LOGON 审计数据写入DB,只要设置"AUDIT CREATE SESSION"审计,就可以通过下面的SQL 查询到相关信息:

select distinct "COMMENT$TEXT",userhost from aud$ where "COMMENT$TEXT" like '%DBLINK%'。


以下内容摘自Oracle 公司给客户下发的SCN 问题紧急处置方案中的内容:

在《关于Oracle DB SCN 生成率过高的预警及处理建议》的文章中,我们已经提出SCN生产率过高的原因。作为oracle db 的一种重要预警,我们建议对此作重点关注。在此,我们提出以下几点处理建议:

1. 在全系统内做SCN 生成率的普查,看看各系统的SCN 生成情况是否牵涉生成率过高的现象;

2. 发现SCN 生成率过高的相关数据库,根据本指南及时进行修正处理;

3. 形成日常检查机制,每半月或者每月运行scnhealthcheck.sql,例行检查SCN 的生成率情况;

4.根据相关数据库的dblink 使用情况,形成dblink 跟踪列表,便于日后检查SCN 状态。列表内容包括源数据库名称、目标数据库名称、dblink 名称、dblink 用途,甚至包括关联对象等信息。


方案一:安装PSU/CPU 补丁修复方案

本方案主要针对以下数据库版本:

Oracle 10.2.0.5

Oracle 11.1.0.7

Oracle 11.2.0.2

Oracle 11.2.0.3

针对上述版本的数据库,oracle 建议给数据库安装2012 年4 月发布的PSU,并在安装该PSU的基础上,安装补丁13916709。如果是集群架构,同时给集群软件最新安装PSU。《《《白鳝注:也可以直接安装2012 年7 月的PSU,这个PSU 已经包含了13916709 补丁的修复,如果觉得暂时无法升级PSU,那么也可以单独打13916709 的独立补丁,这个补丁的目的是解决SCN 异常增长的BUG》》》》》

Ø 10.2.0.5 数据库

对于版本为10.2.0.5 的数据库, 建议安装2012 年4 月发布的PSU 13632743,并在安装PSU 13632743 的基础上,安装补丁13916709。参数

_external_scn_rejection_threshold_hours 在2012 年4 月(包含2012 年4 月)以后发布的PSU/CPU 中已经定义默认值为24,所以安装最新PSU 补丁以后,不需要再设该参数。如果是集群架构,同时给集群软件安装PSU 9952245。

Ø 11.1.0.7 数据库

对于版本为11.1.0.7 的数据库,建议安装2012 年4 月发布的PSU 13621679,并在安装PSU 13621679 的基础上,安装补丁13916709。参数

_external_SCN_rejection_threshold_hours 在2012 年4 月(包含2012 年4 月)以后发布的PSU/CPU 中已经定义默认值为24,所以安装最新PSU 补丁以后,不需要再设该参数。如果是集群架构,同时给集群软件安装PSU 11724953。

Ø 11.2.0.2 数据库

对于版本为11.2.0.2 的数据库,建议安装2012 年4 月发布的PSU 13696224,并在安装PSU 13696224 的基础上,安装补丁13916709。如果是集群架构,同时给集群软件安装PSU 13696242。

Ø 11.2.0.3 数据库

对于版本为11.2.0.3 的数据库,建议安装2012 年4 月发布的PSU 13696216,并在安装PSU 3696216 的基础上,安装补丁13916709。如果是集群架构,同时给集群软件安装PSU 13696251。


《《白鳝注:10.2.0.4 目前在PSU 中也已经包含了13916709 的修复。对于目前无补丁发布的版本,Oracle 10.2.0.1、Oracle 10.2.0.2、Oracle 10.2.0.3》》》

10.2.0.4 版本解决方案

本方案针对数据库版本是Oracle 10.2.0.4。oracle 为此提供两种修正方式:


方式一:紧急修复方案

采用前提:数据库SCN 问题急需解决,但升级数据库版本从管理、业务应用、时间上都不适合。

方式建议程度:中

处理方式:保持数据库版本不变,安装2012 年4 月发布的PSU 12879933。在安装12879933之前,必须先安装9352164,这是安装10.2.0.4.4 之后PSU 的前提条件。如果是集群架构,同时给集群软件安装PSU 9294403。参数_external_SCN_rejection_threshold_hours 在2012 年4 月(包含2012 年4 月)以后发布的PSU/CPU 中已经定义默认值为24,所以安装新PSU 补丁以后,不需要再设该参数。


方式二:补丁集升级修复方案

采用前提:数据库SCN 问题急需解决,安装最近补丁集,从管理、应用、时间上都比较适合,但数据库版本升级计划不能在短期内完成。

方式建议程度:中

处理方式:将数据库升级到10.2.0.5 的版本,安装2012 年4 月发布的PSU 13632743,并在安装PSU 13632743 的基础上,安装补丁13916709。如果是集群架构,同时给集群软件安装PSU 9952245。

《《白鳝注:对于其他未涉及版本,ORACLE 为发出补丁包,ORACLE 建议升级到上述已发补丁包的版本:

Oracle 9.2.0.1~9.2.0.8

Oracle 10.1.0.3~10.1.0.5

Oracle 11.1.0.6

Oracle 11.2.0.1

》》》


Oracle 11.2 引入了一个新的隐含参数来控制每秒的SCN HEADROOM,11G 的缺省值是32K

Parameter Sessio

n Value

---------------------------------------- -------------------------------------

---

_max_reasonable_scn_rate 32768

在网上看到一个查SCN 增长速度的脚本,挺有用的



2013年,我的一个客户突然爆发SCN HEAD ROOM故障,导致大量应用受到影响,为了尽快在数百套数据库中排查出问题,我和海军连夜写了两个用于检查kcmgas 的脚本,9i 采集了statspack 就可以使用。10g,11g 基于awr kcmgas_9i.sql。然后让全省十多个地市和省公司的dba分头排查,耗时70多个小时,终于找到了源头,一台地市公司的某个业务员在WINDOWS上建的一个统计库,这个库要从好多生产库中通过DBLINK抽取数据,然后自己计算。最恐怖的是这套数据库是在这个业务人员的个人电脑上装的,一下班,电脑关机,啥事没有。第二天这哥们一开机,我们忙活一天的成果化为乌有。

最后修改时间:2020-03-25 21:08:29
文章转载自 白鳝的洞穴,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论