zoukankan      html  css  js  c++  java
  • Oracle SCN机制解析

    SCN(System Chang Number)作为oracle中的一个重要机制,在数据恢复、Data Guard、Streams复制、RAC节点间的同步等各个功能中起着重要作用。理解SCN的运作机制,可以帮助你更加深入地了解上述功能。

    在理解SCN之前,我们先看下oracle事务中的数据变化是如何写入数据文件的:

    1、事务开始;

    2、buffer cache中找到需要的数据块,如果没有找到,则从数据文件中载入buffer cache中;

    3、事务修改buffer cache的数据块,该数据被标识为“脏数据”,并被写入log buffer中;

    4、事务提交,LGWR进程将log buffer中的“脏数据”写入redo log file中;

    5、当发生checkpoint,CKPT进程更新所有数据文件的文件头中的信息,DBWn进程则负责将Buffer Cache中的脏数据写入到数据文件中。

    经过上述5 个步骤,事务中的数据变化最终被写入到数据文件中。但是,一旦在上述中间环节时,数据库意外宕机了,在重新启动时如何知道哪些数据已经写入数据文件、哪些 没有写呢(同样,在DG、streams中也存在类似疑问:redo log中哪些是上一次同步已经复制过的数据、哪些没有)?SCN机制就能比较完善的解决上述问题。

    SCN是一个数字,确切的说是一个只会增加、不会减少的数字。正是它这种只会增加的特性确保了Oracle知道哪些应该被恢复、哪些应该被复制。

    总共有4 中SCN:系统检查点(System Checkpoint)SCN、数据文件检查点(Datafile Checkpoint)SCN、结束SCN(Stop SCN)、开始SCN(Start SCN)。其中其面3中SCN存在于控制文件中,最后一种则存在于数据文件的文件头中。

    在控制文件中,System Checkpoint SCN是针对整个数据库全局的,因而之存在一个,而Datafile Checkpoint SCN和Stop SCN是针对每个数据文件的,因而一个数据文件就对应在控制文件中存在一份Datafile Checkpoint SCN和Stop SCN。在数据库正常运行期间,Stop SCN(通过视图v$datafile的字段last_change#可以查询)是一个无穷大的数字或者说是NULL。

    在一个事务提交后(上述第四个步骤),会在redo log中存在一条redo记录,同时,系统为其提供一个最新的SCN(通过函数 dbms_flashback.get_system_change_number可以知道当前的最新SCN),记录在该条记录中。如果该条记录是在 redo log被清空(日志满做切换时或发生checkpoint时,所有变化日志已经被写入数据文件中),则其SCN被记录为redo log的low SCN。以后在日志再次被清空前写入的redo记录中SCN则成为Next SCN。

    当日志切换或发生checkpoint(上 述第五个步骤)时,从Low SCN到Next SCN之间的所有redo记录的数据就被DBWn进程写入数据文件中,而CKPT进程则将所有数据文件(无论redo log中的数据是否影响到该数据文件)的文件头上记录的Start SCN(通过视图v$datafile_header的字段checkpoint_change#可以查询)更新为Next SCN,同时将控制文件中的System Checkpoint SCN(通过视图v$database的字段checkpoint_change#可以查询)、每个数据文件对应的Datafile Checkpoint(通过视图v$datafile的字段checkpoint_change#可以查询)也更新为Next SCN。但是,如果该数据文件所在的表空间被设置为read-only时,数据文件的Start SCN和控制文件中Datafile Checkpoint SCN都不会被更新。

    那系统是如何产生一个最新的SCN 的?实际上,这个数字是由当时的timestamp转换过来的。每当需要产生一个最新的SCN到redo记录时,系统获取当时的timestamp,将其 转换为数字作为SCN。我们可以通过函数SCN_TO_TIMESTAMP(10g以后)将其转换回timestamp:

    SQL> select dbms_flashback.get_system_change_number, SCN_TO_TIMESTAMP(dbms_flashback.get_system_change_number) from dual;
     
    GET_SYSTEM_CHANGE_NUMBER
    ------------------------
    SCN_TO_TIMESTAMP(DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER)
    ---------------------------------------------------------------------------
                  2877076756
    17-AUG-07 02.15.26.000000000 PM

    也可以用函数timestamp_to_scn将一个timestamp转换为SCN

    SQL> select timestamp_to_scn(SYSTIMESTAMP) as scn from dual;
     
           SCN
    ----------
    2877078439

    最后,SCN除了作为反映事务数据变化并保持同步外,它还起到系统的“心跳”作用——每隔3秒左右系统会刷新一次系统SCN。

    下面,在简单介绍一下SCN如何在数据库恢复中起作用。

    数据库在正常关闭(shutdown immediate/normal)时,会先做一次checkpoint,将log file中的数据写入数据文件中,将控制文件、数据文件中的SCN(包括控制文件中的Stop SCN)都更新为最新的SCN。

    数据库异常/意外关闭不会或者只更新部分Stop SCN。

    当数据库启动时,Oracle 先检查控制文件中的每个Datafile Checkpoint SCN和数据文件中的Start SCN是否相同,再检查每个Datafile Checkpoint SCN和Stop SCN是否相同。如果发现有不同,就从Redo Log中找到丢失的SCN,重新写入数据文件中进行恢复。具体的数据恢复过程这里就不再赘述。

    SCN作为Oracle中的一个重要机制,在多个重要功能中起着“控制器”的作用。了解SCN的产生和实现方式,帮助DBA理解和处理恢复、DG、Streams复制的问题。

    最后提一句,利用SCN机制,在Oracle10g、11g中又增加了一些很实用的功能——数据库闪回、数据库负载重现等。

     

     

    首先这里我们先介绍四个SCN概念。
    1、系统检查点scn
    当一个检查点动作完成后,Oracle就把系统检查点的SCN存储到控制文件中。
    select checkpoint_change# from v$database;
    2,数据文件检查点scn
    当一个检查点动作完成后,Oracle就把每个数据文件的scn单独存放在控制文件中。
    select name,checkpoint_change# from v$datafile;
    3,启动scn
    Oracle把这个检查点的scn存储在每个数据文件的文件头中,这个值称为启动scn,因为它用于在数据库实例启动时,
    检查是否需要执行数据库恢复
    select name,checkpoint_change# from v$datafile_header
    4、终止scn
    每个数据文件的终止scn都存储在控制文件中。
    select name,last_change# from v$datafile

     

    以下条件需要使用using backup controlfile
    1)、使用备份控制文件
    2)、重建resetlogs控制文件,如果重建立noresetlogs不必要使用using backup controlfile

     


    2、alter database open resetlog
    指定RESETLOGS将重设当前LOG sequence number为1,抛弃所有日志信息。
    以下条件需要使用resetlog
    1)在不完全恢复(介质恢复)
    2)使用备份控制文件
    使用resetlogs打开数据库后无必完整地备份一次数据库。
    3、create controlfile resetlogs/noresetlogs
    1).用Noresetlogs重建控制文件时,控制文件中 datafile Checkpoint来自Online logs中的Current log头
    2).用Resetlogs重建控制文件时,控制文件中datafile Checkpoint来自各数据文件头。

     

    当system scn,datafile scn,start scn 不全相等,需要介质恢复,如果stopscn null需要实例恢复
    resetlogs抛弃所有在上一次恢复没有用到的日志信息,确保不被重新用与恢复。
    1、系统正常关闭:
    system scn=datafile scn=start scn=stop scn
    1)system scn=datafile scn=start scn,不需要介质恢复
    2)stopscn not null,不需要实例恢复
    2、系统异常关闭:
    system scn=datafile scn=start scn,stop scn null
    1)system scn=datafile scn=start scn,不需要介质恢复
    2)stopscn null,需要实例恢复
    3、旧数据文件
    system scn=datafile scn>start scn,stop scn null/notnull
    1)system scn=datafile scn>start scn,需要介质恢复成system scn=datafile scn=start scn
    2)stopscn null,需要实例恢复,not null 不需要实例恢复
    4、备份控制文件
    system scn=datafile scn<=start scn(当数据文件为旧的相等),stop scn notnull/null
    1)system scn=datafile scn<=start scn,需要使用using backup controlfile介质恢复成system scn=datafile scn=start scn=current log scn(当前日志最大SCN)
    2)为保证上一次恢复没有用到log日志不被使用,必须resetlogs
    5、重建noresetlogs控制文件
    控制文件中 datafile Checkpoint来自Online logs中的Current log头
    current log scn=system scn=datafile scn>=start scn,stop scn not null/null
    1)current log scn=system scn=datafile scn>=start scn,需要介质恢复成system scn=datafile scn=start scn=redolog scn(当前日志最大SCN),stop scn not null
    2)stopscn not null 不需要实例恢复
    6、重建resetlogs控制文件
    控制文件中datafile Checkpoint来自各数据文件头。
    system scn>=datafile scn=start scn,stop scn not null/null
    1)system scn>=datafile scn=start scn,需要使用using backup controlfile介质恢复成system scn=datafile scn=start scn(当前日志最大SCN),stop scn not null
    2)stop notnull,因为SCN已经为redolog scn,log已经不能使用,必须resetlogs

     

     

     

     

     

    目录

    1SCN的介绍

    2SCN的工作机制

    3SCN的增加

    4、其他的SCN

    5测试

    6小结

    7问题

     

    1SCN的介绍


    Oracle中的SCN有下面几种:

    1)系统检查点scn(v$database(checkpoint_change#))

    当一个检查点动作完成之后,Oracle就把系统检查点的SCN存储到控制文件中

       select checkpoint_change# from v$database;

    2)数据文件检查点scn (v$datafile(checkpoint_change#))

        当一个检查点动作完成之后,Oracle就把每个数据文件的scn单独存放在控制文件中

            select name,checkpoint_change# from v$datafile;

    3)数据文件终止scn (v$datafile(last_change#))

        每个数据文件的终止scn都存储在控制文件中。在正常的数据库操作过程中,所有正处于联机读写模式下的数据文件的终止scn都为null,异常关闭后的Stop SCN,也为NULL.

         select name,last_change# from v$datafile;

    4)数据文件启动scn (v$datafile_header(checkpoint_change#)

        Oracle把这个检查点的scn存储在每个数据文件的文件头中,这个值称为启动scn,因为它用于在数据库实例启动时,检查是否需要执行数据库恢复

         select name,checkpoint_change# from v$datafile_header;

     

     

    2SCN的工作机制

    1)在数据库打开并运行之后,控制文件中的系统检查点scn、控制文件中的数据文件检查点scn和每个数据文件头中的启动scn都是相同的

     2 )控制文件中的每个数据文件的终止scn都为null

     3) NORMALIMMEDIATE关闭数据库的过程中,系统会执行一个检查点动作,这时所有数据文件的终止scn都会设置成数据文件头中的那个启动scn的值。

    4)在数据库重新启动的时,Oracle将执行两次检查

           ◆看数据文件头中的ckpt计数器(v$datafile_header.checkpoint_count)是否与对应控制文件中的ckpt计数器(v$datafile.)一致。若相等,进行第二次检查

           ◆比较文件头中的启动scn和对应控制文件中的终止scn进行比较,如果终止scn等于启动scn,则不需要对那个文件进行恢复

     5)数据库打开之后,存储在控制文件中的数据文件终止scn的值再次被更改为null,这表示数据文件已经打开并能够正常使用了

       注:当ABORT强制关闭数据库时不进行检查点处理,所以终止scn仍然为无穷大。在下次启动期间,发现启动scn和终止scn不同,需要进行线程恢复。

    3SCN的增加

    1)     SCN(System Change Number)只要数据库被修改,就会+1,而不是一定要进行checkpoint,例如DML的发生即使没有提交也会使SCN+1.(哪些情况下SCN会发生变化?)

       注:SCN增加并不代表会在数据文件头中表现出来,而是需要等到checkpoint执行后才写入(当然可能已经增加了很多)

     2)如果一个DML导致产生事务,则会产生一个SCN。这个意思是说如果一个事务包含多个dml,则只有第一个初始产生事务的dml产生scn,提交的时候又是一个scn,如果一个事务只有一个dml,那看起来就是dml产生一个scn,提交或者回滚产生一个scn

    3) Oracle10g内部的SCN会默认不管有没有动作,每隔3s自动增加一次。其他需要增加的情况则再加。

     4)只有ckpt进程才会修改文件头中的checkpoint计数器和SCNDBWR只会修改数据块,即ckpt通知dbwr写数据文件,写完之后ckpt更新控制文件和数据文件头。此时若DBWR发现数据块的log block还没有被写入日志文件,则在dbwr写块之前通知lgwrlog buffer中的日志写入log文件。

       注:总结一下,日志切换必定触发ckpt,但ckpt不一定会触发lgwr,但是一定会触发dbwr

    4、其他的SCN

    1)日志文件头中包含了Low scnNext scn,表示所给日志文件包含有从Low scnNext scnredo record. (如何查看? REDO SCN)

       注:当系统运行时,日志文件的Next scn同样为无穷大。而且需要注意:在恢复时定位到底使用哪个日志文件的时候,并不是用数据文件中的low scn去框,也不是只要在日志文件的low scn and next scn之间就利用该日志文件。而是在数据文件头中有RBA的记录,RBA包含了日志序号Sequence#、block number、slot number。 这样可以直接定位到日志文件(归档日志文件)和具体的位置。

    在确定了哪个数据文件必须redo后,oracle会比较change vector(向量)中的SCN和数据文件数据块中的SCN,如果change vector的SCN小于数据块的scn,则跳过此change vector,否则应用redo.

    2)数据块中的SCN

    data block里面的SCN是当block被更改的时候的SCN,而数据文件有那么多block,自然不同的block有不同的SCNblock中存在block SCNITL中的commit SCNblock SCN又在块头和块位都有,若不一致意味着block损坏。而ITL中的commit SCN则跟consistent gets and delay block cleanout有关。(Block SCN如何查看?)

    3) v$database中的checkpoint_change#dbms_flashback.get_system_change_number不同。前者是作为数据库的最后一次checkpoint是的SCN,而后者是系统的最新SCN,所以一般后者都会比前者大,而当刚做完checkpoint时候两者会差不多。(Checkpoint的触发机制?)

     4)begin backup命令发出后,相关数据文件的checkpoint scn被冻结(以及状态标志被改变),其他一切照旧。例如:日志切换时checkpoint count正常递增/检查点照常写文件,自然文件中的数据块内的各种scn也照常递增。

     

    5测试:

     

    A.正常关闭,mount数据库

     

    SQL> col system_scn format 999999999999999999

    SQL> col datafile_scn format 999999999999999999

    SQL> col start_scn format 999999999999999999

    SQL> col stop_scn format 999999999999999999

    SQL> select a.checkpoint_change# system_scn, c.checkpoint_change# start_scn, scn, re rownum=1) c;

                  b.checkpoint_change# datafile_scn, decode(b.last_change#,NULL,'null',b.last_change#) stop_scnp_scn

                  from v$database a,

                  (select checkpoint_change#, last_change# from v$datafile where rownum =1 ) b, 

                 (select checkpoint_change# from v$datafile_header where rownum=1) c;

     

    SYSTEM_SCN          START_SCN       DATAFILE_SCN  STOP_SCN

    ------------------- ------------------- ------------------- ----------------------------------------

         2696048203982      2696048203982      2696048203982 2696048203982

     

    上述查询结果表明:

    结束SCN都是跟启动SCN是一样的,这样,当数据库open的时候就可以不用recover了。

     

    把数据库打开open

     

    SQL> alter database open;

      Database altered.

     

    SQL> select a.checkpoint_change# system_scn, c.checkpoint_change# start_scn,

     2 b.checkpoint_change# datafile_scn, decode(b.last_change#,NULL,'null',b.last_change#) stop_scn

     3 from v$database a,

     4 (select checkpoint_change#, last_change# from v$datafile where rownum =1 ) b,

     5 (select checkpoint_change# from v$datafile_header where rownum=1) c;

     

            SYSTEM_SCN          START_SCN       DATAFILE_SCN STOP_SCN

    ------------------- ------------------- ------------------- ----------------------------------------

         2696048203983      2696048203983      2696048203983 null

     

    系统检查点scn增加了1

    控制文件中的数据文件检查点scn和数据文件的文件头中的启动scn也都各自增加了1

    控制文件中的数据文件终止scn,变为NULL.

    C.对系统触发检查点

     

    SQL> alter system checkpoint;

      System altered.

     

    SQL> select a.checkpoint_change# system_scn, c.checkpoint_change# start_scn,

     2 b.checkpoint_change# datafile_scn, decode(b.last_change#,NULL,'null',b.last_change#) stop_scn

     3 from v$database a,

     4 (select checkpoint_change#, last_change# from v$datafile where rownum =1 ) b,

     5 (select checkpoint_change# from v$datafile_header where rownum=1) c;

     

            SYSTEM_SCN          START_SCN       DATAFILE_SCN STOP_SCN

    ------------------- ------------------- ------------------- ----------------------------------------

         2696048204212      2696048204212      2696048204212 null

     

    系统检查点scn发生变化,增加不止1,这与检查点产生机制有关。

    D异常关闭启动!没有将Start SCN同步给Stop SCN,造成不一致.需要Instance Recovery

     

    SQL> shutdown abort

    SQL> startup mount

    Database mounted.

     

    SQL> select a.checkpoint_change# system_scn, c.checkpoint_change# start_scn,

     2 b.checkpoint_change# datafile_scn, decode(b.last_change#,NULL,'null',b.last_change#) stop_scn

     3 from v$database a,

     4 (select checkpoint_change#, last_change# from v$datafile where rownum =1 ) b,

     5 (select checkpoint_change# from v$datafile_header where rownum=1) c;

     

            SYSTEM_SCN          START_SCN       DATAFILE_SCN STOP_SCN

    ------------------- ------------------- ------------------- ----------------------------------------

         2696048204212      2696048204212      2696048204212 null

     

    按理说在数据文件启动之前End SCN的值不应为NULL,但这里查出却为NULL ,之前的理解是有误的,Shutdown Abort, Stop SCN仍为NULL. (异常关闭后的Start Mount,在打开之前要做Instance Recovery)

     

    SQL> alter database open;

    Database altered.

     

    Vi alert.log

     

    alter database open

    Mon Feb 1 14:27:05 2010

    Beginning crash recovery of 1 threads

    Mon Feb 1 14:27:05 2010

    Started first pass scan

    Mon Feb 1 14:27:05 2010

    Completed first pass scan

     61 redo blocks read, 30datablocks need recovery

    Mon Feb 1 14:27:05 2010

    Started recovery at

     Thread 1: logseq 71, block 7466, scn 0.0

    Recovery of Online Redo Log: Thread 1 Group 1 Seq 71 Reading mem 0

     Mem# 0 errs 0: /opt/oracle/oradata/mydb/redo01.log

    Mon Feb 1 14:27:05 2010

    Completed redo application

    Mon Feb 1 14:27:05 2010

    Ended recovery at

     Thread 1: logseq 71, block 7527, scn 627.3103729640

     30 data blocks read, 30 data blocks written, 61 redo blocks read

    Crash recovery completed successfully

     

    完成在线日志应用

     

    SQL> select a.checkpoint_change# system_scn, c.checkpoint_change# start_scn, scn,

    b.checkpoint_change# datafile_scn, decode(b.last_change#,NULL,'null',b.last_change#) stop_scnp_scn

     3 from v$database a,

     4 (select checkpoint_change#, last_change# from v$datafile where rownum =1 ) b,

     5 (select checkpoint_change# from v$datafile_header where rownum=1) c;

     

            SYSTEM_SCN          START_SCN       DATAFILE_SCN STOP_SCN

    ------------------- ------------------- ------------------- ----------------------------------------

         2696048224234      2696048224234      2696048224234 null

     

     

    6小结

     

    1、系统正常关闭:

      1)system checkpoint scn = datafile checkpoint scn = start scn,不需要介质恢复

      2)stop scn is not null = start SCN,不需要实例恢复

     

    2、系统异常关闭:

      1)system checkpoint scn = datafile checkpoint scn = start scn,不需要介质恢复

      2)stop scn is null,需要实例恢复

     

    3、旧数据文件

      会使得:system checkpoint scn = datafile checkpoint scn > start scnstop scn is null/ is not null

      1)system checkpoint scn = datafile checkpoint scn > start scn

    需要介质恢复成system checkpoint scn = datafile checkpoint scn = start scn

    2)stop scn is null,需要实例恢复,is not null不需要实例恢复

     

    4备份控制文件

      会使得:system checkpoint scn = datafile checkpoint scn <= start scn(当数据文件为旧且和旧控制文件为同一版本的时候相等,如果数据文件是当前的数据文件则是小于)stop scn notnull/null

    1)system checkpoint scn = datafile checkpoint scn <= start scn,需要使用using backup controlfile介质恢复成system scn = datafile scn = start scn = current log scn(当前日志最大SCN)

    2)为保证上一次恢复没有用到log日志不被使用,必须在恢复完成后用resetlogs打开数据库

     

     

    5、以noresetlogs方式重建控制文件

      在以这种方式重建控制文件时,控制文件中的datafile checkpoint scn来自于Online logs中的Current log头,因此

      current log scn = system checkpoint scn = datafile scn >= start scn(如果数据文件为备份而来则会大于start SCN,如果是当前的则为相等于start SCN), stop scn not null/null

    1)current log scn = system checkpoint scn = datafile checkpoint scn >= start scn,因此需要介质恢复成system checkpoint scn = datafile scn = start scn = redolog scn(当前日志最大SCN) 

    2)stopscn is not null不需要实例恢复

     

    6、以resetlogs方式重建控制文件

      控制文件中datafile checkpoint scn来自各数据文件头(start scn),而且system checkpoint scn会归为0

      system checkpoint scn < datafile checkpoint scn = start scn,stop scn not null/null

     

    1)system checkpoint scn < datafile checkpoint scn = start scn,需要使用using backup controlfile介质恢复成system checkpoint scn = datafile checkpoint scn = start scn(当前日志最大SCN),stop scn not null

    2)     stopscn is not null不需要实例恢复,而且因为SCN已经为redolog scnlog已经不能使用,必须用resetlogs方式打开数据库

     

    7问题:

    7.1数据库启动过程的两个比较.

     v$datafile_header.checkpoint_count VS 对应控制文件中的ckpt计数器(v$datafile.)在哪个视图?

     

    7.2 哪些情况下SCN会发生变化?这几个SCN如何变化?

     

    7.3      如何查看REDO SCN?

     

    7.4      Block SCN如何查看?

     

    7.5 Checkpoint的触发机制?

    下面这些操作将会触发checkpoint事件:

    1)       日志切换,通过ALTER SYSTEM SWITCH LOGFILE。(之前的资料说这里,发出的应是增量检查点 ?是的,日志切换只能产生增量检查点)

    2)       DBA发出checkpoint命令,通过ALTER SYSTEM checkpoint。

    3)       对数据文件进行热备时,针对该数据文件的checkpoint也会进行,ALTER TABLESPACE TS_NAME BEGIN BACKUP/END BACKUP。

    4)       当运行ALTER TABLESPACE/DATAFILE READ ONLY的时候。

    5)       SHUTDOWN命令发出时。

     

     

    人生有三宝:终身运动,终身学习,终身反醒.吸收新知,提高效率,懂得相处,成就自己,也成就他人,创造最高价值。

  • 相关阅读:
    SQL 在数据库中查找包含指定关键字的存储过程或函数
    根据名称查找存储过程或函数
    根据最后修改时间查找存储过程或函数
    SQL 数据过度事务模板
    Feeling something wrong
    发布一个倒计时软件(C# 开源)
    SpringBoot中的配置文件信息加密
    springboot中mysql连接配置
    React学习2_运行项目
    React学习0_文章目录
  • 原文地址:https://www.cnblogs.com/bolang100/p/6834219.html
Copyright © 2011-2022 走看看