SCN Head Room相关
本文链接:https://blog.youkuaiyun.com/Hehuyi_In/article/details/89926951
公众号里看到SCN Head Room相关的问题,整理记录一下主要概念和脚本
https://mp.weixin.qq.com/s/Cvo89ApoOm4ZC3cSX4g3SA
关于SCN
SCN即系统改变号(System Change Number),是在某个时间点定义数据库已提交版本的时间戳标记。 Oracle为每个已提交的事务分配一个唯一的SCN。 SCN的值是对数据库进行更改的逻辑时间点。 Oracle使用此编号记录对数据库所做的更改。在数据库中,SCN也可以说是无处不在,数据文件头,控制文件,数据块头,日志文件等等都标记着SCN。也正是这样,数据库的一致性维护和SCN密切相关。不管是数据的备份,恢复都是离不开SCN的。
当前的SCN可以通过以下查询获得:
-
select dbms_flashback.get_system_change_number scn from dual;
-
select current_scn from v$database;
SCN最大值(硬限制)
ORACLE的SCN是一个6字节(48bit)的数字,因此最大值不超过2^48,即是:281,474,976,710,656(281万亿)。
如果达到了这个最大值,只能重建数据库以重置SCN。
https://yq.aliyun.com/articles/266908
最大可允许SCN增长速率(Maximum Reasonable SCN Rate)
为了防止因为软件BUG或者人为恶意修改当前SCN, 导致数据库SCN直接达到最大值,最终必须重建数据库。 Oracle决定限制数据库每秒的SCN变化, 依据当时系统负荷和预测, 定义了一个通用的SCN增长速率, 每秒最大增长不超过16K, 按照这个速率, 281万亿的SCN上限,需要大约544年才能达到
-
SQL> select power(2,48) / 16 / 1024 / 3600 / 24 / 365 from dual;
-
POWER(2,48)/16/1024/3600/24/365
-
-------------------------------
-
544.770078
当前最大可允许SCN(Maximum Reasonable SCN,软限制)
Oracle使用了一个十分简单的算法——以1988年1月1日0点0分0秒为基准时间,到当前的秒钟数乘以16K,就是当前最大可允许SCN。如果在某个时刻SCN达到了这个最大值,那么事务就无法提交,系统会hang住,需要等到下一秒,这个值又变大了,才能继续进行事务的提交。
-
col scn for 999,999,999,999,999,999
-
select (( ((((to_char(sysdate, 'YYYY') - 1988) * 12 +
-
to_char(sysdate, 'mm') - 1) * 31 + to_char(sysdate, 'dd') - 1) * 24 +
-
to_char(sysdate, 'hh24')) * 60 + to_char(sysdate, 'mi')) * 60 +
-
to_char(sysdate, 'ss')) * to_number('ffff', 'XXXXXXXX') / 4 Max_Reasonable_SCN
-
from dual;
SCN Head Room
正常情况下所有数据库的当前SCN会落后于当前最大可允许SCN,这两个数字之间的差异, 就叫做SCN Head Room(即是(1988年到当前时间的秒数*16384)与当前SCN之间的差距)。 由于数字太大,为了便于理解,这个差值会按照每秒16K的折算, 再次折算成时间。所以一般而言,我们看到的是一个数据库的Head room还有多少天。
-
select version,
-
date_time,
-
dbms_flashback.get_system_change_number current_scn,
-
SCN_Head_Room
-
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)) SCN_Head_Room
-
from v$instance);
Oracle提供了一个脚本scnhealthcheck.sql 用于检查数据库当前SCN的剩余情况。
@?/rdbms/admin/scnhealthcheck.sql
CHECK RESULT:(SCN Headeroom>=62是A、<10是C、中间是B)
当你的数据库SCN Head Room不足时, 数据库Alert 日志当中也会有Warning。
例如:Warning: The SCN headroom for this database is only 3 days!
是不是我的数据库在SCN Head Room天后就不能用了?
事实上, 因为最大可用SCN一直在稳定地以每秒16K的速度在增长, 只要用户的SCN增长速率不是持续超过16K, 就不可能出现追上的情况。
查询历史SCN及SCN Headeroom(一天内,间隔为1小时)
-
SELECT sysdate - (rownum / 24) datetimestamp,
-
timestamp_to_scn(sysdate - (rownum / 24)) SCN,
-
((sysdate - (rownum / 24)) - to_date('01-01-1988', 'DD-MM-YYYY')) * 24 * 60 * 60 *
-
16384 SCN_Head_Room
-
FROM dual
-
CONNECT BY rownum <= 24;
Finding the top SCN rate
查询最近3天SCN增长量及增速(间隔为15分钟)
-
WITH datelist AS
-
( SELECT sysdate - (rownum/1440) - (15/1440) starttime -- 15 minute interval
-
, sysdate - (rownum/1440) endtime
-
FROM dual
-
CONNECT BY rownum <= (3*1440) -- 3 days history
-
)
-
SELECT starttime
-
, endtime
-
, timestamp_to_scn(endtime) - timestamp_to_scn(starttime) scngrowth
-
, round((timestamp_to_scn(endtime) - timestamp_to_scn(starttime)) /
-
(((24*60*60)*(endtime-starttime )))) scnrate
-
FROM datelist
-
/*WHERE round((timestamp_to_scn(endtime) - timestamp_to_scn(starttime)) /
-
(((24*60*60)*(endtime-starttime )))) >= 14000*/
-
ORDER BY 4 DESC
为什么这里要使用 1988年到当前时间的秒数,1988这个年份有什么意义?
根据以下文章的说法,在1988年发布了Oracle V6,首次实现了行级锁定,首次实现了数据库热备份,Oracle公司从Belmont移到加利福尼亚的redwood shores,并引入了PL/SQL。目前使用版本7-11g 仍沿用了大量的V6的代码,V6的代码中做了大量DEFINE的工作,这大概是一切的开始。这就好像是”And God said, Let there be light”!
https://www.askmaclean.com/archives/scn-headroom-1988-oracle.html
在新的算法中,Oracle改变了 SCN 算法的起点值,在32K和96K的增长率下,起点分别近似调整为:
2:~ 1998/07/01
3: ~ 2008/03/30
这也可算作起征点调整吧,所以经过调整最大支持到大约 2097年(极限不稳定值 Oracle 最高可以用到 2105 年),你可能会问,那到了2097年怎么办?这个,呵呵。。。