Chinaunix首页 | 论坛 | 博客
  • 博客访问: 163655
  • 博文数量: 32
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 155
  • 用 户 组: 普通用户
  • 注册时间: 2013-03-08 09:08
个人简介

胖子不是一口吃成滴!

文章分类

全部博文(32)

文章存档

2017年(1)

2016年(4)

2014年(1)

2013年(26)

分类: Oracle

2016-06-07 22:51:03

原文地址:Oracle的SCN剖析 作者:digdeep126

1. SCN的本质
SCN即System Change Number。它的本质是一个时间点,可以精确到纳秒。而个人电脑的微处理器执行一道指令(如将两数相加)约需2至4纳秒。所以这个时间点已经是十分的精确了。Oracle在内部用这个时间点来标识某个操作的完成
当Oracle数据库某个操作后,SCN由DBMS自动递增。SCN被用来保证数据库的一致性以及数据恢复等。SCN几乎存在于Oracle系统的任何地方。

SQL> select dbms_flashback.get_system_change_number scn, scn_to_timestamp(dbms_flashback.get_system_change_number) timestamp from dual;

       SCN        TIMESTAMP
-------------  ----------------------------------
-------
    931316      17-OCT-12 03.11.56.000000000 PM

SCN的最大值:
SQL> 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 scn from dual;
       SCN
----------
1.3057E+13
这样看来SCN的最大的值,随着时间的推移会逐渐的增大。

 

1.oracle 为了防止scn的异常增长所以限制每一秒钟允许最多产生 256*256/4 个scn
2.oracle 内部使用了一个4G范围的数据来表示01/01/1988 00:00:00 ~ 08/18/2121 06:28:15 这段时间.它的算法简单,说来就是每个月都是用的31天来表示时间,每增加1秒,这个数值就增加1.  可以从redo file dump ,control file dump,datafile head dump 观察到这个值.

当前系统可能的最大scn 就是上面两个值的乘积:1988/01/01 00:00:00到当前时间的秒数 乘以 256*256/4
256=power(2,8),所以256*256=power(2,16)=0xffff=to_number('ffff','xxxxxxxx')

我们看一下 LRBA 对应的日志中的SCN:
SQL>  select CPDRT,CPLRBA_SEQ||'.'||CPLRBA_BNO||'.'||CPLRBA_BOF "Low RBA",
          CPODR_SEQ||'.'||CPODR_BNO||'.'||CPODR_BOF "On disk RBA",
          CPODS,CPODT,CPHBT from X$KCCCP;

  CPDRT  Low RBA     On disk RBA   CPODS      CPODT                          CPHBT
-------- ----------  ------------  ---------   ---------------------   -------------
        62 26.80884.0   26.81039.0   934874     10/17/2012 15:53:58       795883580
         0  0.0.0             0.0.0             0                                                         0

         0  0.0.0             0.0.0             0                                                         0
         0  0.0.0             0.0.0             0                                                         0
         0  0.0.0             0.0.0             0                                                         0
         0  0.0.0             0.0.0             0                                                         0
         0  0.0.0             0.0.0             0                                                         0
         0  0.0.0             0.0.0             0                                                         0

8 rows selected.

CPDRT:是检查点队列中的脏块数目(dirt).
CPODS:是On Disk rba的SCN,表示日志文件中最新的那条日志记录中的SCN。
CPODT:是On Disk rba的Timestamp.
CPHBT:心跳(heart beat).

2. 常见的十分重要的SCN
1) 控制文件中的有三种SCN:系统SCN、数据文件SCN、数据文件结束SCN。
2) 数据文件中的SCN:数据文件头部的SCN,叫start SCN,也叫启动SCN。
3) redo logfile中的SCN:每一条日志记录有一个SCN,
                       每一个日志文件有一个first scn和一个next scn.
4) 数据块中的SCN:数据块头部ITL事务槽中有SCN(在跑日志时,会对ITL中的SCN和日志文件中的SCN进行比较,如果ITL中的SCN大一些,那么会进行空跑日志,如果ITL中的SCN小一些,则实际修改数据块.
5) 回滚段事务表中也有SCN。

系统SCN
当一个检查点动作完成后,Oracle就把系统检查点的SCN存储到控制文件中。
SQL> select checkpoint_change# from v$database;
CHECKPOINT_CHANGE#
------------------------------
            924192

数据文件SCN
当一个检查点动作完成后,Oracle就把每个数据文件的scn单独存放在控制文件中。
SQL> select name,checkpoint_change# from v$datafile;
NAME                                                                       CHECKPOINT_CHANGE#
--------------------------------------------------        -------------------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                 924192
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                924192
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                  924192
/u01/app/oracle/oradata/jiagulun/users01.dbf                    924192
/u01/app/oracle/oradata/jiagulun/example01.dbf                924192

文件结束SCN
当数据库正常关闭时,会将文件结束SCN存放在控制文件中。而在数据库正常运行时,控制文件中的文件结束SCN为空,当数据库非正常关闭时,那么文件结束SCN的值会为空,所以在数据库启动时,会根据文件结束SCN来判断是否要进行实例崩溃恢复

SQL> select name,last_change# from v$datafile;
NAME                                                                       LAST_CHANGE#
--------------------------------------------------         ------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                 null
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                null
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                  null
/u01/app/oracle/oradata/jiagulun/users01.dbf                    null
/u01/app/oracle/oradata/jiagulun/example01.dbf                null

数据文件头部SCN
在每一个数据文件的头部还有一个开始SCN
SQL> select name,checkpoint_change# from v$datafile_header;
NAME                                                                      CHECKPOINT_CHANGE#
----------------------------------------------             ------------------
/u01/app/oracle/oradata/jiagulun/system01.dbf                  924192
/u01/app/oracle/oradata/jiagulun/undotbs01.dbf                 924192
/u01/app/oracle/oradata/jiagulun/sysaux01.dbf                   924192
/u01/app/oracle/oradata/jiagulun/users01.dbf                     924192
/u01/app/oracle/oradata/jiagulun/example01.dbf                 924192

开始SCN也叫启动scn,因为它用于在数据库实例启动时,检查是否需要执行数据库恢复。在数据库启动时,如果在控制文件中的文件SCN和数据文件头部的SCN不一致,那么就要进行恢复。可能会用到归档日志。而数据库实例崩溃恢复只会用到ACTIVE和CURRENT中的日志,因为INACTIVE对应的脏数据块已经写入到了磁盘中。

日志文件中的SCN
redo logfile中的每一条日志记录有一个SCN,
              每一个日志文件的头部有两个SCN:first SCNnext SCN.
first SCN即该日志文件中第一条日志记录中的SCN,而next SCN是 该日志文件的最后一条日志文件的SCN,也就是下一个日志文件的第一条日志记录中的SCN,也就是说下一个日志文件的first SCN等于上一个日志文件的next SCN. 所以first SCN和next SCN记录了该日志文件的日志记录的范围。这样通过每一个日志文件头部的first SCN和next SCN可以将所有的日志文件串联起来,当成一个整体的日志文件。sybase的日志文件好像就是一个整体的日志文件。而Oracle却巧妙地通过日志文件头部的first SCN和next SCN将所有的日志文件连了起来
SQL> select recid,sequence#,first_change#,next_change# from v$log_history where rownum<6;

     RECID  SEQUENCE# FIRST_CHANGE# NEXT_CHANGE#
---------- ----------- ---------------   ------------
         1          1         446075               473470
         2          2         473470               480715
         3          3         480715               498876
         4          4         498876               520938
         5          5         520938               555508
从上面的结果我们可以清楚的看到first SCN和next SCN是串联起来的。

SQL> select * from v$log;
 GROUP# THREAD# SEQUENCE# BYTES    MEMBERS ARC  STATUS    FIRST_CHANGE#
-------- --------- ----------  --------- ---------  ---  ---------  -----------------
         1          1         26       52428800          1    NO   CURRENT             924192
         2          1         24       52428800          1    YES  INACTIVE            906864
         3          1         25       52428800          1    YES  INACTIVE            907884

我们知道日志文件分为CURRENT, ACTIVE, INACTIVE三者,CURRENT表示当前正在使用的日志文件,ACTIVE表示日志文件中对应的脏块还没有写到磁盘中,而INACTIVE则表示日志文件中对应的所有脏块都写到了磁盘中。

系统SCN、文件SCN、数据文件头部SCN三者的值等于ACTIVE, CURRENT中最老的一个日志文件的头部的first SCN. 这三个值只有在日志文件由ACTIVE变为INACTIVE时,才会更新。因为INACTIVE日志对应的脏块都写入到了磁盘中,不需要恢复。而增量checkpoint操作只是将checkpoint-Q中的最老的脏块对应的日志的地址即LRBA写到控制文件中,它并不会修改SCN. 所以在恢复时,可以根据系统SCN与日志文件头部的first SCN比较就可以找到要使用那个日志文件,然后再向新的日志方向寻找LRBA地址对应的具体的那一条日志记录。然后从LRBA到On disk RBA进行前滚,前滚之后在利用undo进行回滚。

日志记录中的SCN与commit的关系

当我们执行 commit 时,LGWR会将log buffer写入redo logfile,同时也会将对应的SCN同步写入到redo logfile内(wait-until-completed)。因此当你commit transaction时,在成功返回之前,LGWR必须先完整的完成上述行为之后,否则你是看不到提交成功的返回的。
可以查询目前系统最新的SCN
SQL> select dbms_flashback.get_system_change_number scn from dual;
       SCN
----------
    944406

可以理解,这里返回的SCN,也是目前redo logfile最新的SCN纪录。因为commit后才会有SCN,而一旦commit就会立刻写入redo logfile中。

CHECKPOINT和SCN的关联:
完全Checkpoint 发生的目的就是要把存储在buffer内的已提交数据写回disk,否则一旦发生crash,需要进行recovery时,就必须花很多时间进行recovery,这样在商业应用上是很浪费时间和没有效率的。

当commit一笔交易时,只会立刻将redo buffer写入redo logfile内,但是并不会马上将该update后的block(dirty block)同步写回disk datafile中,这是为了减少过多disk IO,所以采取batch方式写入。

When a checkpoint occurs. Oracle must update the headers of all datafiles to record the details of the checkpoint.  This is done by the CKPT process. The CKPT process does not write blocks to disk; DBWn always performs that work.

在shutdown normal or shutdown immediate下,也就是所谓的clean shutdown, checkpoint也会自动触发。当发生完全checkpoint时,会把SCN写到四个地方去。三个地方在control file 内,一个在各个datafile的header。

在数据库运行期间的scn值:
在数据库打开并运行之后,控制文件中的系统检查点、控制文件中的数据文件检查点scn和每个数据文件头中的启动scn都是相同的。控制文件中的每个数据文件的终止scn都为null.

在安全关闭数据库的过程中,系统会执行一个检查点动作,这时所有数据文件的终止scn都会设置成数据文件头中的那个启动scn的值。在数据库重新启动的时候,Oracle将文件头中的那个启动scn与数据库文件检查点scn进行比较,如果这两个值相互匹配,oracle接下来还要比较数据文件头中的启动scn和控制文件中数据文件的终止scn。如果这两个值也一致,就意味着所有数据块多已经提交,所有对数据库的修改都没有在关闭数据库的过程中丢失,因此这次启动数据库的过程也不需要任何恢复操作,此时数据库就可以打开了。当所有的数据库都打开之后,存储在控制文件中的数据文件终止scn的值再次被更改为null这表示数据文件已经打开并能够正常使用了。


阅读(2085) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~