一、 基础概念
1、SCN(System Change Number)值是Oracle数据库运行每次变化的一个逻辑点,相当于数据库内部的一个时钟,是个只增不减的数字,广泛应用于数据库的恢复、事务ACID、一致性读以及分布式事务中。
2、SCN的内部存储方式:在Oracle内部,SCN分为两部分存储,分别称之为scn wrap和scn base。实际上SCN长度为48位,即它其实就是一个48位的整数。由于在早些年通常只能处理32位甚至是16位的数据,所以分成了低32位(scn base)和高16位(scn wrap)。那么SCN这个48位长的整数,最大就是2^48(281万亿,281474976710656)
3、Maximum Reasonable SCN:在当前时间点,SCN最大允许达到的SCN值。也称为Reasonable SCN Limit,简称RSL。SCN Headroom即当前时间点SCN以每秒最大的增长速度达到RSL值所需时间,其计算公式为:
(当前时间-1988年1月1日00:00:00)×24×3600×SCN每秒最大的可能增长速度
注:
- (当前时间-1988年1月1日)得到天数,为方便计算,每月按照31天计算。
- SCN每秒最大的可能增长速率跟Oracle版本有一定的关系,在11.2.0.2之前是16384(即16K),在11.2.0.2及之后版本是32768(即32K)。在11.2.0.2及以上的版本中有一个隐含参数_max_reasonable_scn_rate,其默认值就是32768(不建议调整这个值)。根据对各个数据库版本的补丁13498243中自带的scnhealthcheck.sql研究,SCN Headroom计算公式中的最大速率均为定义为16k。
- Alert日志中的SCN Headroom剩余天数为此刻达到RSL所需天数,并非真正耗尽数据库SCN的时间,SCN Headroom每一秒都在增长。
二、 研究过程
1、 SCN Headroom过低问题发现
(1) alert日志可能出现以下告警:
1、Warning - High Database SCN: Current SCN value is 0x0b7b.0008e40b, threshold SCN value is 0x0b75.055dc000
If you have not previously reported this warning on this database, please notify Oracle Support so that additional diagnosis can be performed.
2、Warning: The SCN headroom for this database is only NN days!
3、Warning: The SCN headroom for this database is only N hours!
4、WARNING: This patch can not take full effect until this RAC database has been completely shutdown and restarted again.
Oracle recommends that it is done at the earliest convenience.
5、Rejected the attempt to advance SCN over limit by 9374 hours worth to 0x0c00.00000f66, by distributed transaction remote logon, remote DB: REMDB.XX.ORACLE.COM.
Client info : DB logon user ME, machine yy, program sqlplus@yy (TNS V1-V3), and OS user uuu
6、Rejected the attempt to advance SCN over limit by 9375 hours worth to 0x0c00.000003c6, by distributed transaction logon, remote DB: REMDB.XX.ORACLE.COM.
Client info : DB logon user TC, machine xx, program oracle@xx (TNS V1-V3), and OS user xxx
7、Rejected the attempt to advance SCN over limit by 9374 hours worth to 0x0c00.00000f66, by XXXXX
Client info : DB logon user TC, machine mmm, program sqlplus@mmm (TNS V1-V3), and OS user uuu
Where XXXXX is a string such as:
? PL/SQL RPC (remote)
? sql exec with curSCN
? sql exec with outSCN
(2) 脚本检查
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 --day
from v$instance;
注:根据scnhealthcheck.sql定义:
- 当SCN Headroom > 62天则健康状态为A,系统无SCN问题;
- 当10 < SCN Headroom <= 62天则健康状态为B,系统存在SCN问题,尚不致命;
- 当SCN Headroom <=10天则健康状态为C,系统存在致命的SCN问题,需立即处理。
(3) 问题发生可能原因:
- 本地数据库自身业务问题导致SCN激增
- DB Link传染
数据库之间可以通过dblink来进行数据访问,当通过dblink进行业务提交的时候,由于数据库之间存在不同的SCN,因此,为了让事务一致,Oracle将会以两者之间较大的SCN来进行同步,更新dblink两端的数据库SCN。但是,如果源数据库出现SCN生成率过高的问题,随着业务的不断运行,SCN的异常就会通过dblink传染到其他相关的数据库,而dblink使用的频率越大,这种传染的速度也就越快。如果企业内部存在网状的dblink结构,那么这将很容易将SCN的问题扩大到全网,极端情况下会引起大范围的宕机。
通过以下脚得到数据库的scn headroom变化趋势图,如果 SCN Headroom 的剩余天数的历史变化很突然,那么就说明数据库主要被外部通过DBLINK 传染,导致SCN异常增长。
#查看scn headroom变化趋势(前提是数据库开启归档模式)
set numwidth 17
set pages 1000
alter session set nls_date_format='DD/Mon/YYYY HH24:MI:SS';
SELECT tim, gscn,
round(rate_per_sec),
round((chk16kscn - gscn)/24/3600/16/1024,1) "Headroom"
FROM
(
select tim, gscn, rate_per_sec,
((
((to_number(to_char(tim,'YYYY'))-1988)*12*31*24*60*60) +
((to_number(to_char(tim,'MM'))-1)*31*24*60*60) +
(((to_number(to_char(tim,'DD'))-1))*24*60*60) +
(to_number(to_char(tim,'HH24'))*60*60) +
(to_number(to_char(tim,'MI'))*60) +
(to_number(to_char(tim,'SS')))
) * (16*1024)) chk16kscn
from
(
select FIRST_TIME tim , FIRST_CHANGE# gscn,
((NEXT_CHANGE#-FIRST_CHANGE#)/
((NEXT_TIME-FIRST_TIME)*24*60*60)) rate_per_sec
from v$archived_log
where (next_time > first_time)
)
)
order by 1,2
对于非归档模式的数据库可以通过以下脚本查询SCN增长速度,通过了解SCN的走势诊断SCN Headroom问题,发现系统中存在的跳变情况则可确认为DB Link传染导致SCN异常。
with t1 as(
select time_dp , 24*60*60*(time_dp - lag(time_dp) over (order by time_dp)) timediff,
scn - lag(scn) over(order by time_dp) scndiff
from smon_scn_time
)
select time_dp , timediff, scndiff,
trunc(scndiff/timediff) rate_per_sec
from t1
order by 1
/
2、 建议解决方式
(1) 应用ORACLE官方推荐的补丁13498243,调整隐含参数:_external_scn_rejection_threshold_hour(11.2.0.2及以上版本的这个参数默认值是24,其他版本默认值是744,官方建议调整为24小时,以避出现过多的ORA-19706)、
_external_scn_logging_threshold_second(建议为86400,相关的信息会记录到Alert log中。通过这些记录的信息,日后可以查找导致SCN跳变的源头。)、_external_scn_rejection_delta_threshold_minute
这三个参数最大限度保障业务系统正常运行需安装到所有db link操作相关的数据库上,同是将SCN Headroom加入监控指标进行规律监控。
(2) 查找SCN传染源数据库并进行隔离通过其他手段使用数据,如使用OGG同步相关数据,减少DB Link使用,避免数据库之间通过DB Link传染高SCN值,传染源数据库打完13498243补丁,可直接在alert日志中找到传染源数据库的相关信息:
Advanced SCN by 2280 minutes worth to 0x0e26.e74b94ff, by distributed transaction end, remote DB: ORCL.
Client info: DB logon user DB_CX, machine HDDS-FXGLDB, program ORACLE.EXE, and OS user SYSTEM
另外,12cr2可利用新特性监视数据库链接,可确认SCN暴增原因,主要通过这3个视图:DBA_DB_LINKS,DBA_EXTERNAL_SCN_ACTIVITY、DBA_DB_LINK_SOURCES。
通过dbms_tns包的函数resolve_tnsname可以分析判断数据库链接目标主机是否可用,dba_db_link_sources可以获取到存在的数据库链接信息,DBA_EXTERNAL_SCN_ACTIVITY可以记录分布式事务和分布式读在分布式数据库环境中的一致性即来判断SCN是否高速率增长。
执行以下脚本,如无结果,则数据库无SCN高生成率活动,否则,会返回造成SCN高生成率相关信息。
(SELECT RESULT, OPERATION_TIMESTAMP, EXTERNAL_SCN, SCN_ADJUSTMENT, HOST_NAME, DB_NAME,
SESSION_ID, SESSION_SERIAL#
FROM DBA_EXTERNAL_SCN_ACTIVITY a, DBA_DB_LINK_SOURCES s
WHERE a.INBOUND_DB_LINK_SOURCE_ID = s.SOURCE_ID) --返回通过DB Link导致SCN增长的远程数据库信息
UNION
(SELECT RESULT, OPERATION_TIMESTAMP, EXTERNAL_SCN, SCN_ADJUSTMENT,
dbms_tns.resolve_tnsname(HOST) HOST_NAME, NULL DB_NAME, SESSION_ID,
SESSION_SERIAL#
FROM DBA_EXTERNAL_SCN_ACTIVITY a, DBA_DB_LINKS o, DBA_DB_LINK_SOURCES s
WHERE a.OUTBOUND_DB_LINK_NAME = s.SOURCE_ID AND
OUTBOUND_DB_LINK_OWNER = o.OWNER) --返回通过DB Link导致SCN增长的远程数据库信息
UNION
(SELECT RESULT, OPERATION_TIMESTAMP, EXTERNAL_SCN, SCN_ADJUSTMENT,
s.MACHINE HOST_NAME, NULL DB_NAME, SESSION_ID, SESSION_SERIAL#
FROM DBA_EXTERNAL_SCN_ACTIVITY a, V$SESSION s
WHERE a.SESSION_ID = s.SID AND
a.SESSION_SERIAL#=s.SERIAL# AND
INBOUND_DB_LINK_SOURCE_ID IS NULL AND
OUTBOUND_DB_LINK_NAME IS NULL AND
OUTBOUND_DB_LINK_OWNER IS NULL); --返回通过用户连接导致SCN增长的相关信息
--脚本源自《Oracle® Database Administrator’s Guide 12c Release 2 (12.2)》32.5.5 Determining the Source of High SCN Activity for Incoming Database Links
--《Oracle® Database Administrator’s Guide 12c Release 2 (12.2)》4.242 DBA_EXTERNAL_SCN_ACTIVITY
--尚未进行相关验证
三、 总结
1. 在全系统内做SCN生成率的普查,看看各系统的SCN生成情况是否牵涉生成率过高的现象;
2. 发现SCN生成率过高的相关数据库,及时进行修正处理;
3. 形成日常检查机制,每半月或者每月运行scnhealthcheck.sql,例行检查SCN的生成率情况;
4. 根据相关数据库的dblink使用情况,形成dblink跟踪列表,便于日后检查SCN状态。列表内容包括源数据库名称、目标数据库名称、dblink名称、dblink用途,甚至包括关联对象等信息,
5. 目前的Oracle官方并没有给出完全解决SCN headroom过低问题,只能通过设置相关隐含参数最大限度保障业务系统的正常运行,隔离高SCN值数据库通过DB link传染,极端情况下还需关闭数据库等待SCN headroom增长。
四、 相关SQL脚本附录
#隐含参数查询
select name
,value
,decode(isdefault, 'TRUE','Y','N') as "Default"
,decode(ISEM,'TRUE','Y','N') as SesMod
,decode(ISYM,'IMMEDIATE', 'I','DEFERRED', 'D','FALSE', 'N') as SysMod
,decode(IMOD,'MODIFIED','U','SYS_MODIFIED','S','N') as Modified
,decode(IADJ,'TRUE','Y','N') as Adjusted
,description
from ( --GV$SYSTEM_PARAMETER
select x.inst_id as instance
,x.indx+1
,ksppinm as name
,ksppity
,ksppstvl as value
,ksppstdf as isdefault
,decode(bitand(ksppiflg/256,1),1,'TRUE','FALSE') as ISEM
,decode(bitand(ksppiflg/65536,3),1,'IMMEDIATE',2,'DEFERRED','FALSE') as ISYM
,decode(bitand(ksppstvf,7),1,'MODIFIED','FALSE') as IMOD
,decode(bitand(ksppstvf,2),2,'TRUE','FALSE') as IADJ
,ksppdesc as description
from x$ksppi x,x$ksppsv y
where x.indx = y.indx
and substr(ksppinm,1,1) = '_'
and x.inst_id = USERENV('Instance')
)
where name like '%&par%'
order by name
/
五、 参考资料
System Change Number (SCN), Headroom, Security and Patch Information (文档 ID 1376995.1)
Installing, Executing and Interpreting output from the "scnhealthcheck.sql" script (文档 ID 1393363.1)
ORA-19706 and Related Alert Log Messages (文档 ID 1393360.1)
How to Extract the Historical Values of a Statistic from the AWR Repository (文档 ID 948272.1)