完全无事务的数据库SCN增长之谜

[复制链接]
查看11 | 回复6 | 2010-10-8 09:28:51 | 显示全部楼层 |阅读模式
原文在blog上:
http://space.itpub.net/15415488/viewspace-616264

欢迎大家指正和讨论。
在深入区有一个帖子讨论一个没有任何事务的Oracle数据库如果一直打开,那么SCN会不会增大?
http://www.itpub.net/thread-1221754-1-1.html
现象是显而易见的,SCN会随时间而增加。
然后有人说:SCN就像Oracle的一个内部时钟一样,会随时间的增加而相应的增加。
再然后又有人会问:SCN的增加到底是不是因为Oracle后台进程做了一些内部的change?

对于Oracle内部时钟的比喻,我觉得是非常感性的认识,很形象地描述了一种实际存在并发生的现象。但是我实在是非常好奇,Oracle自己到底是如何维护这个内部时钟的呢?
对于SCN是否是Oracle后台进程的内部change导致的,我起初是非常赞同的,因为我觉得这种解释是非常理性也看似合理的。

最后所有的问题还是通过自己的实验得到了验证,原来这里面其实包含了两种Oracle的行为,所以非常容易混淆大家的思路。
第一种行为是Oracle的内部每三秒的heartbeat checkpoint,它不产生任何redo,但是会增加SCN+1。
第二种行为是Oracle的内部维护一张SCN和时间的mapping关系的表--SMON_SCN_TIME,在9i中这个表大约每5分钟被更新一次。它会产生redo,当然也会增大SCN。这种行为是由SMON后台进程产生的。
由于这两种行为的共同作用,于是产生了我们可以看见的现象:SCN在完全没事务发生的数据库中增加了,redo也增加了。

结论阐明了,那么我是如何得出这两个结论的呢?
通过如下实验(也在我的回帖中)。
1.每三秒的heartbeat checkpoint产生的SCN+1
SQL> select sysdate,dbms_flashback.get_system_change_numberscn from dual;
SYSDATE
SCN
----------------- --------------------
20091010 22:50:19
11723811783
SQL> /
SYSDATE
SCN
----------------- --------------------
20091010 22:50:20
11723811784
SQL> /
SYSDATE
SCN
----------------- --------------------
20091010 22:50:22
11723811785
首先从一次的结果来看,确实是一个scn差了3秒。
让我们等待更久一点
SQL> /
SYSDATE
SCN
----------------- --------------------
20091010 22:51:00
11723811797
SQL> /
SYSDATE
SCN
----------------- --------------------
20091010 22:51:29
11723811806
两者时间相差29s,SCN相差trunc(29/3)=9
SQL> select sysdate,dbms_flashback.get_system_change_numberscn from dual;
SYSDATE
SCN
----------------- --------------------
20091010 23:02:05
11723812015
SQL> /
SYSDATE
SCN
----------------- --------------------
20091010 23:03:55
11723812051

两者时间相差110s,SCN相差trunc(110/3)=36
于是查询v$sysstat的redo size,会发现一点都没有变。
SQL> select sysdate,s.value
2from v$sysstat s,v$statname n
3where s.STATISTIC#=n.STATISTIC#
and n.name='redo size';4
SYSDATE
VALUE
----------------- --------------------
20091010 23:06:26
66608
SQL> /
SYSDATE
VALUE
----------------- --------------------
20091010 23:08:00
66608

2.但是从更长的时间上来看,除了这每隔三秒增加的1个scn,还有其他scn增加,也有redo的少量产生,所以我认为我们应该区分开来前者和后者。
于是现在我需要寻找到底是谁产生了除了每隔3s产生的这个scn以外的scn和redo。
结论2:在空闲状态下的DB会产生一定的redo,而这些redo是由SMON后台进程产生的。
create table stat1 as select * from v$sesstat;

SQL>select sysdate,s.value
from v$sysstat s,v$statname n
where s.STATISTIC#=n.STATISTIC#
and n.name='redo size';
SYSDATE
VALUE
----------------- --------------------
20091010 23:17:55
221544
SQL> select sysdate,s.value
from v$sysstat s,v$statname n
where s.STATISTIC#=n.STATISTIC#
and n.name='redo size';
SYSDATE
VALUE
----------------- --------------------
20091010 23:26:37
227980

create table stat2 as select * from v$sesstat;
我们可以看到两个时间点相差了227980-221544=6436的redo。
SQL> select stat1.sid,n.name,stat1.value,stat2.value,
2stat1.value-stat2.value diff
from stat1,stat2,v$statname n
where stat1.sid=stat2.sid
and stat1.STATISTIC#=stat2.STATISTIC#
and stat1.STATISTIC#=n.STATISTIC#
and stat1.valuestat2.value
and n.name='redo size'
order by stat1.sid,diff
;3456789 10
SID NAME
VALUEVALUE DIFF
---------- ---------------------------------------------------------------- ---------- ---------- ----------
8 redo size
2177628212-6436
13 redo size
128200 164712 -36512

sid 13是我建stat1、2表的session,而sid 8 恰好就是产生着多余的6436 redo的 session。
我们可以看出redo的差量完全吻合。
ora sid2pid 8
Connected.
SPID sid/serial PROGRAM
SQL_HASH_VALUE PREV_HASH_VALUE
------------ ---------- ------------------------------------------------ -------------- ---------------
238238,1[email=oracle@(SMON[/email])
20955433142095543314

原来,产生这多出来的redo是由smon干的。
那到底smon干了什么产生了这些redo呢?
sql trace SMON,但是没有产生任何trc文件。
我只得log miner一个archivelog当smon又产生了一些redo之后:
SQL> begin
2DBMS_LOGMNR.ADD_LOGFILE( LOGFILENAME=>'xxx.arc',
OPTIONS => DBMS_LOGMNR.NEW);
end;34
5/
PL/SQL procedure successfully completed.
SQL> EXECUTE DBMS_LOGMNR.START_LOGMNR(OPTIONS =>DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG);
PL/SQL procedure successfully completed.
SQL> create table haologminer as select * from v$logmnr_contents;
Table created.
SQL> select SCN,to_char(TIMESTAMP,'yyyymmdd hh24:mi:ss') TIMESTAMP,
2SQL_REDO,SESSION# from haologminer ;
SCN TIMESTAMP
---------- -----------------
SQL_REDO
--------------------------------------------------------------------------------------------------------------------------------------------
SESSION#
----------
1.1724E+10 20091010 23:57:43
set transaction read write;
8
1.1724E+10 20091010 23:57:43
update "SYS"."SMON_SCN_TIME" set "TIME_MP" = '1255244262', "TIME_DP" = TO_DATE('10-OCT-09', 'DD-MON-RR'), "SCN_WRP" = '2', "SCN_BAS" = '3133
878649' where "THREAD" = '1' and "TIME_MP" = '1230774206' and "TIME_DP" = TO_DATE('31-DEC-08', 'DD-MON-RR') and "SCN_WRP" = '2' and "SCN_BAS
" = '3133713182' and ROWID = 'AAAAICAABAAADqRACn';
8
1.1724E+10 20091010 23:57:43
commit;
8
3 rows selected.
原来,我们都错怪SMON了,他产生了这些redo,原来是为了更新我们的SMON_SCN_TIME这个表。
这个表是作为time和scn的一个mapping关系,是需要时时更新的。
终于,知道原因了,可以睡个好觉了~

回复

使用道具 举报

千问 | 2010-10-8 09:28:51 | 显示全部楼层
学习了。。赞一个。。
回复

使用道具 举报

千问 | 2010-10-8 09:28:51 | 显示全部楼层
学习
回复

使用道具 举报

千问 | 2010-10-8 09:28:51 | 显示全部楼层
支持原创,好贴!
回复

使用道具 举报

千问 | 2010-10-8 09:28:51 | 显示全部楼层
赞!
恐怖的钻研精神啊
回复

使用道具 举报

千问 | 2010-10-8 09:28:51 | 显示全部楼层
好像有点问题。。。。。楼主的贴
回复

使用道具 举报

千问 | 2010-10-8 09:28:51 | 显示全部楼层
学习
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行