转载请注明出处,谢谢!
--- 好久没来逛ITPUB了,发一篇大家关心的问题
1. SCN headroom简介
SCN是Oracle内部使用的逻辑时钟,用于区分事务操作的先后次序以及确保事务操作的一致性。它由48位的一串单向序列数字来实现的,因此最大值不能超过2的48次方,为了确保这个48位的SCN能够用足够长的时间(500年),Oracle对SCN序列做出了一个限制,即每秒钟SCN最大增长不能超过16K。为了平衡业务的高峰和低谷,Oracle使用了一个十分简单的算法来贯彻上述限制,就是以从1988年1月1日0点0分0秒为基准时间,至当前时间的秒钟数乘以16K,就是当前SCN的最大允许值,我们称为SCN Headroom。从SCN Headroom 的算法可知,Headroom值是随时间动态变化的,按照oracle公司说法,如果在某个时刻SCN达到了这个最大值,那么事务就无法提交,需要等到下一秒,当Headroom值又变大了,才能继续进行事务的提交;但在实际运行时,如果数据库当前的SCN已经达到了Headroom的最大值时,该机制有很大可能会造成数据库保护性宕机。
当然,在正常情况下,每秒16K的SCN增量完全可以满足应用的正常使用,但是在实际使用中,已经证实一些特定的应用模式会触发Oracle的内部Bug,根据经验这些应用基本都是跑报表类型的业务、采用高并发、select... for update 、执行效率非常差的sql和相同对象的DDL语句同时执行、大量数据处理一次性提交(大事物)等等。最终导致SCN在短时间内的大幅增长,久而久之,SCN很快就会逼近Headroom的上限。
除了Oracle Bug引发SCN大幅增长以外,Oracle数据库固有的DBLINK运作机制也在其中起了推波助澜的作用。
Oracle数据库为了实现分布式处理,在多个数据库之间做DBLINK访问的时候,会将两个数据库的SCN进行同步,也就是将较高的SCN同步至参与DBLINK的另外一个库,使两个库的SCN序列一致。这个机制就可能把SCN增长异常传播到其它的数据库服务器上,并且随着不同数据库的业务高峰和低谷相互传染,大大加速了SCN的增长,并最终造成严重的后果。
2. SCN跳变源的寻找方式
2.1. 寻找跳变源的有效方法
为了找到跳变源,如果现网的dblink使用非常复杂并且headroom下降的问题涉及了几十套甚至是上百套数据库,这个时候查找跳变源会变得复杂。对于打了2012年1月以后的psu补丁的数据库系统可以通过alert判断,对于没有打2012年1月以后的补丁就需要我们做好监控。所以一般这种情况下我们会对现网的所有的数据库进行监控,这样做的好处是我们可以第一时间知道当前所有系统的scn headroom的现状,并且如果出现headroom骤降我们可以第一时间进行相应查找跳变源,而不需要等到数据库后台报错了才知道headroom问题,如果后台已经报错说明headroom问题已经非常严重。
1) 对于已经打了2012 年1 月以后PSU 补丁的数据库系统,当SCN 传播发生时,
ALERT LOG 中会有记录,可以通过ALERT LOG 查找问题的系统:
Advanced SCN by 13238271 minutes worth to 0x0bd6.00000f21, by distributed transaction remote logon, remote DB: ORA10G. Client info : DB logon user SCOTT, machine gc, program sqlplus@gc (TNS V1-V3), and OS user oracle
2) 而对于未安装上述补丁的数据库,则可以通过在数据库上运行3.1步骤中提供的脚本,列出SCN历史的剩余天数,依照SCN 序列突变的先后时间来找出源头,或是缩小范围便于进一步查证。但是如果现网数据库数量非常多的话一套一套查是非常不现实的,所以一般情况下我们都会做SCN的监控。
2.2. SCN headroom的实时情况监控
分钟级监控(时间可以自行调整):监控主机上的部署crontab sh /u01/oracle/ljl/scn_monitor.sh 调用存过scn_monitor生成监控表scn_mon(最好建成分区表提升查询效率)。
监控脚本内容略:
NOTE:脚本内容可以根据需求自己控制,如果担心监控库会加重库与库之间的scn同步并且影响我们对跳变源的判断,可以使用shell或者python直接调用,从而避免监控库使用dblink。近期在电力使用的python脚本监控方式待验证成功后续再增加。
3. SCN跳变源分析
3.1. SCN headroom历史纪录分析
查看近期的headroom历史记录(按分统计)时间范围不要选的太大,因为我们选择的是小时为单位所以时间跨度大了以后曲线会反映不出跳变点,定位SCN headroom下降的大概时间点和当前SCN headroom总体趋势,查询语句如下:
select *
from monitor.scn_mon a
where a.date_time >= '2016/10/23'
order by a.date_time
定位SCN headroom下降的大概时间点和当前SCN headroom总体趋势:
先把我所有系统的大体scn headroom的趋势对比不同时间点的headroom剩余时间,如果呈现下降趋势的,取其中一套headroom在下降的数据库,进行plsql作图找到大致的下降时间点和整体的下降趋势
select *
from monitor.scn_mon a
where a.date_time >= '2016/10/23'
and a.host_name = ''
order by a.date_time
图1-1
如果曲线如图1-1,有明显的垂直下降的情况,很可能是被其他数据库通过dblink传染的,这个时候就要定位这个断崖的时间点,然后执行如下语句找到当前时间或者前一分钟的headroom剩余时间最小的那台主机(也就是最先跳变的数据库),如果确定了有一套库在每次的垂直下降的时间点headroom都最先下降那么他往往就是源头库或者最先感染的库。
select *
from monitor.scn_mon a
where a.date_time >= '2016/10/23 21:00:00'
and a.date_time <= '2016/10/23 21:02:00'
order by a.date_time
如果曲线如图1-2,虽然headroom是一直在下降的但是下降的幅度很缓慢甚至有些时间点还是往上涨的,那么headroom下降的原因往往是它本身进程异常调用而引起的问题,这个时候基本可以判定他的scnheadroom下降问题不是其他系统通过dblink同步而导致的。
图1-2
3.2. 数据库SCN自增长情况分析
数据库SCN自增长查看(即call scn kcmgas的平均每秒调用值),SCN自增长平均每秒超过16000需要重点分析(按照SCN headroom 的计算方式,平均每秒超过16000,会引起全网SCN headroom下降),可以通过下面语句查看SCN自增长:
9i数据库(需开启STATSPACK)
10g以上数据库
单实例查询:
select to_char(b.end_interval_time,'YYYY-MM-DD HH24:MI:SS') as time,
c.snap_id,
trunc((lead(c.value, 1, c.value) over(order by c.snap_id) - c.value) / (select to_number(substr(replace(a.snap_interval, '+00000 ', ''), 1, 2), 99) * 3600 +
to_number(substr(replace(a.snap_interval, '+00000 ', ''), 4, 2), 99) * 60 +
to_number(substr(replace(a.snap_interval, '+00000 ', ''), 7, 2), 99)
from dba_hist_wr_control a)) as per_s_value
from dba_hist_sysstat c,dba_hist_snapshot b
where
b.snap_id=c.snap_id
and b.instance_number=c.instance_number
and c.instance_number = 1 ----或者2
and c.stat_name = 'calls to kcmgas'
order by 1 desc;
多实例查询:
select c.instance_number,
to_char(b.end_interval_time, 'YYYY-MM-DD HH24:MI:SS') as time,
c.snap_id,
trunc((lead(c.value, 1, c.value)
over(partition by c.instance_number order by c.snap_id) -
c.value) /
(select to_number(substr(replace(a.snap_interval, '+00000 ', ''),
1,
2),
99) * 3600 +
to_number(substr(replace(a.snap_interval, '+00000 ', ''),
4,
2),
99) * 60 +
to_number(substr(replace(a.snap_interval, '+00000 ', ''),
7,
2),
99)
from dba_hist_wr_control a)) as per_s_value
from dba_hist_sysstat c, dba_hist_snapshot b
where b.snap_id = c.snap_id
and b.instance_number = c.instance_number
and c.stat_name = 'calls to kcmgas'
order by 1, 2 desc;
3.3. Session SCN调用情况分析
如果前两步都无法定位,则需要关注持续活动非常久的session,并且关注session的SCN调用情况:
---建议通过value desc,last_call_et desc 排序来看,一般情况下value过千万,甚至上亿,LAST_CALL_ET超过几个小时那么该会话可能就是引起跳变的可疑的会话。
3.4. 确认感染源
分析到了源头库或者是最先感染的库,通过取下降高峰时段的AWR进行最终确认。
select b.end_interval_time,
c.snap_id,
trunc((lead(c.value, 1, c.value) over(order by c.snap_id) - c.value) / (select to_number(substr(replace(a.snap_interval, '+00000 ', ''), 1, 2), 99) * 3600 +
to_number(substr(replace(a.snap_interval, '+00000 ', ''), 4, 2), 99) * 60 +
to_number(substr(replace(a.snap_interval, '+00000 ', ''), 4, 2), 99)
from dba_hist_wr_control a))
from dba_hist_sysstat c,dba_hist_snapshot b
where
b.snap_id=c.snap_id
and b.instance_number=c.instance_number
and c.instance_number = 1 ----或者2
and c.stat_name = 'calls to kcmgas'
order by 1 desc;
3.5. 异常session定位
如果已经分析到源头库,紧接着来定位session,可以直接登录该库进行检查定位:
脚本略
当前面的2、3、4基本初步能找出跳变源,确定了可能的跳变源数据库后,可以通过本语句进行确认相关异常会话,使用VALUE,PREVALUE,LAST_CALL_ET,event,SQL_TEXT结合起来综合判断。
如:value过千万,甚至上亿,LAST_CALL_ET超过几个小时,event是异常等待,且SQL_TEXT进行了append insert操作或者语句中有parallel参数那么该会话就是引起跳变的最可疑的会话。
处理可疑会话跟业务侧确认该会话的用途是否可以停止或者后台数据库层直接kill,并且对这些会话进行优化接下来继续观察headroom是否回涨,如果并没有发现可疑会话那就继续重点监控该数据库观察时候有可以会话或者后台进程异常调用scn,必要时可以尝试申请在scn headroom下降的大概时间点窗口申请尝试停数据库,然后对比headroom曲线是否有变化,如果headroom回涨,那么可以基本定位是该数据库,如果以上步骤对headroom没有任何影响,则该可以跳变源可能就不是真正的跳变源请从第一步开始分析另一个可疑的跳变源。
4. SCN问题解决方案
1)数据库被外部数据库通过DBLINK传染,造成SCN序列异常增长
如果数据库被外部数据库通过DBLINK传染,而造成SCN序列异常增长,而应用改造减少DBLink有无法在短期实现,那么未防止进一步传染其他健康的数据库,请及时将它们进行dblink的隔离。
2)数据库本身触发Bug,造成SCN序列的异常增长
如果数据库本身触发Bug,造成SCN序列的异常增长,即3.2步骤发现数据库scn自身调用异常,则可以对该库应用2012年一月份以后的补丁(该补丁也存在部分bu所以建议打到最新的补丁),并且设置:_external_scn_rejection_threshold_hours=24。这个设置降低可以SCN Headroom的顶部空间,11.2.0.2以前的版本缺省的设置容量至少为31天,降低为 24 小时,可以增大SCN允许增长的合理空间。如果该数据库版本没有对应的补丁,建议升级,如果升级需要跨多个版本为了降低风险可以进行业务改造防止传染其他健康数据库或者直接进行迁移。
因为没有对应的补丁的版本数据库往往是比较旧的,升级的可能会涉及跨多个版本,所以一般情况下我们不建议升级而是直接迁移更安全或者进行业务改造禁用dblink。
以下版本oracle是对应没有补丁程序的:
· All versions up to and including 9.2.0.7
· Versions 10.1.0.2 to 10.1.0.4 inclusive
· Versions 10.2.0.1 and 10.2.0.2
· Version 11.1.0.6
· Version 11.2.0.1
备注:所有的解决方案都是存在风险的,所以请考虑周全在确定使用哪一种方式。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30068249/viewspace-2130002/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/30068249/viewspace-2130002/