ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 完全无事务的数据库SCN增长之谜

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

原创 Linux操作系统 作者:viadeazhu 时间:2009-10-11 15:56:31 0 删除 编辑

    在深入区有一个帖子讨论一个没有任何事务的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_number  scn 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_number  scn 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
  2  from v$sysstat s,v$statname n
  3  where 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,
  2  stat1.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.value<>stat2.value
and n.name='redo size'
order by stat1.sid,diff
;  3    4    5    6    7    8    9   10 

       SID NAME                                                                  VALUE      VALUE       DIFF
---------- ---------------------------------------------------------------- ---------- ---------- ----------
         8 redo size                                                             21776      28212      -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
------------ ---------- ------------------------------------------------ -------------- ---------------
23823        8,1       
" = '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关系,是需要时时更新的。
终于,知道原因了,可以睡个好觉了~

 

 

 

 

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/15415488/viewspace-616264/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-08-22

  • 博文量
    79
  • 访问量
    368409