一、参与检查点的进程主要包括lgwrdbwnckpt,分为两大类:完全检查点和增量检查点
  (1)完全检查点主要包括以下步骤:
  ①首先,在日志缓冲中确定当前的(也就是最新的)重做记录,提取其RBASCN作为检查点目标
  ②LGWR清空日志缓存,将重作记录写入在线日志
  ③DBWn进程将检查点目标(RBASCN)产生的及检查点目标之前产生的脏数据块,按RBA的顺序写入数据文件
  ④最后,CKPT进程将检查点目标(RBASCN)写入数据文件的头部和控制文件

  (2)触发完全检查点的条件:
    ①执行shutdown immediate命令
    ②执行alter systemcheckpoint命令
    ③LGWR切换在线日志,不论是因为日志写满还是执行alter system switch logfile命令
    ④执行部分表空间维护命令:altertablespace ...offline|online|begin backup|end backup|read only|read write

二、增量检查点并不会去更新数据文件头,而只是每3秒由CKPT进程去更新控制文件中的LRBASCN
(1)增量检查点主要包含以下步骤
    ①CKPT3秒一次记录检查点位置的工作(更新7控制文件)
    ②CKPT定期触发DBWR
(2)增量检查点的意义有以下两个:
   ①减少发生完全检查点时DBWn进程的工作负担
   ②提高实例恢复的速度

 完全检查点与增量检查点的区别



由于OracleLGWRDBWR工作的不一致,Oracle引入了检查点的概念,用于同步数据库,保证数据库的一致性。在Oracle里面,检查点分为两种:完全检查点和增量检查点。下面我们分别介绍这两种检查点的作用:

1
、完全检查点
(
完全检查点会将数据缓冲区里面所有的脏数据块写入相应的数据文件中,同时将最新的checkpoint  scn更新到所有的数据文件头部控制文件)

 

(完全检查点发生时,记录到数据文件头和控制文件的SCN不是检查点发生时的SCN,因为检查点发生时DBWn还没有来得及将所有数据都写入,自然不能将当前SCN写入。而是将发生完全检查点时,触发的DBWn将当前dirty buffer写完后,dirty buffer对应的SCN更新到数据文件头和控制文件)

(DBWn被触发时,会将dirty buffer里的数据块无序的写入,在写入期间,所有的DML操作将被冻结,知道dirty buffer写完)
Oracle8i之前,数据库的发生的检查点都是完全检查点。完全检查点会将数据缓冲区里面所有的脏数据块写入相应的数据文件中同时将最新的checkpoint scn更新到所有的数据文件头部及控制文件。保证数据库的处于一致的状态。需要注意的是,完全检查点产生的时候,CKPT并不是把当前完全检查点发生那一时刻的SCN更新到控制文件和数据文件头而是将这个触发检查点时刻DBWn当前刚写完 dirty buffer对应的SCN更新到控制文件和数据文件头也就是说,更新控制文件和数据文件头的SCN是滞后于完全检查点的发生那一时刻的SCN,这个从恢复的原理也很容易理解,因为检查点发生的时候要写入dirty buffer还没有写入自然不能立即更新成当前的SCN。需要注意的是, oracle8之前,由于没有chekpointqueue,也没有增量检查点的概念,oracle8之前发生完全检查点时,DBWn会以一种无序的方式将所有的 dirty buffer写出到数据文件,这个时候Oracle会冻结所有DML操作等候所有dirty buffer被写出,巨大的IO往往会影响到数据库的性。后来随着Oracle数据库的发展和buffer cache的不断增大,oracle 意识到这个单一的Full checkpoint机制已经不能满足需要,所以在Oracle8i后提出增量检查点的概念,建立了checkpoint queue dirty bufferheader根据首次变化时候的顺序(LRBA)排列在queue里面。这样DBWn只要顺着queue的顺序写,而其他进程不必等候dbwr的写完成就可以继续。因此增量检查点的概念就由此产生了。

完全检查点在8i之后只有在下列两种情况下才会发生:

DBA
手工执行alter system checkpoint的命令;

数据库正常shutdown (immediate,transcational,normal)

2
、增量检查点   说白了,就是

CKPT3秒一次的检查DBWn写进度并在控制文件中记录检查点位置(checkpoint position)和更新heartbeat(心跳)信息
以及
CKPT定期触发DBWn去写checkpointqueue中的脏数据
这两项操作合一起被称为增量检查点。 -->可能这块描述的过于笼统,大家继续往下看:-)
我们都知道:

被修改过的数据块,在oracle中都被统称为脏数据块(dirty buffer)

所有的脏块被一个链表串起来,称做检查点队列(checkpoint queue)

 

buffer cache(缓冲区),每一个块都有一个buffer header简称BH,

 

BH中有一个ckptq, 此项目中记录了指向检查点队列上一个块和下一个块的指针。

 

如果某一个块不在检查点队列中,他的ckptq项为空.通过ckptqoracle将所有的脏块串成了一个双向链表。这个双向链表就是检查点队列了。

Oracle
8i开始引入了检查点队列(checkpointqueue)的概念,用于记录数据库里面当前所有的dirty buffer的信息,这些dirty buffer的信息按被修改的时间先后存放在checkpoint queue里面(当块首次被更改时,块会立即被加进检查点队列),所涉及的条目主要包含

 

RBA (RedoBlock Address重做日志里面,用于标识事务期间,数据块在重做日志里面发生更改的编号)  数据块发生改变时在重做日志里面会发生相应的编号更改记录

一个脏块第一次被更新的时候产生的重做日志记录在重做日志文件中所对应的位置数据块的数据文件号块号checkpoint queue1RBA2,数据块文件号,3,块号)


论数据块(buffer)更改几次,它在checkpointqueue里面的位置始终保持不变,checkpoint queue也只会记录它最早的RBA(这个最早的RBA其实就是LowRBA,也就是数据块第一次被修改时所对应的RBA),从而保证最早更改的数据块能够尽快从内存写入数据文件。DBWR每到一定的时机,就会被触发 (DBWn并不是只有当检查点发生的时候才写,它大约有10几种条件触发写操作)沿着检查点队列的顺序刷新脏块,同时CKPT进程,会监控着检查点队列的长度,当检查点队列的长度达到一定限制时(具体有几个参数来确定checkpoing queue的长度,下面会提到比如log_checkpoint_timeout,fast_start_mttr_target)CKPT会通知DBWR写脏块。CKPT会根据几个参数的设置和I/O的速度以及繁忙程度,计算出来一个Target rba(目标rba)DBWn会沿着检查点队列,按照dirty bufferLow RBA顺序将所有Target rba之前对应的脏块从内存写入数据磁盘文件。当CKPT通知完DBWnTarget rba后,CKPT的任务就结束了。他并不会等待DBWn写完所有的Target rba之前的脏块。因此这里CKPT只是起到了一个通知DBWn进程写入的作用。

当完全检查点发生的时候,Oracle一方面通知DBWn进行下一批写操作,另一方面是将这个触发检查点时刻DBWn当前刚写完dirty buffer对应的SCN写入数据文件头和控制文件这个SCN就是checkpoint scn。但Oracle考虑到检查点SCN的间隔还是太大了,因为检查点的触发条件有限,周期可能比较长,有些情况下比如检查点需要5分钟左右才触发,那这个时候系统crash再重新启动就意味着很可能系统需要5分钟左右才能启动。于是Oracle采用了一个heartbeat的概念,3秒的频率将DBWn写的进度反应到控制文件中,这样系统crash重新启动的时候将从更近的一个时间点开始恢复。Oracle这么做的目的就是要缩短崩溃恢复时间!因此CKPT另外一个任务就是每3秒,检测一次DBWn的写进度DBWn是沿着检查点队列写脏块,由于这里有一个顺序的关系,所以DBWn的写的进度就是可衡量的,写到哪个buffer的时候该buffer的首次变化时候的scn(对应了LRba)就是当前所有数据文件block的上面最新scn,但是由于无法适时的将DBWn的进度记录下来,所以Oracle选择了一些策略。其中就包括CKPT进程的检查点位置更新和心跳所以说CKPT3秒钟查看一下DBWn沿检查点队列写到了哪里,并且将这个位置设置为检查点位置 (checkpont position)。也就是说检查点位置之前的块,都是已被DBWn刷新到磁盘上的块。因此我们可以理解为,CKPT进程每3秒会根据DBWn写的进度设置并记录一个检查点位置,也就是说这个检查点位置就是由DBWn的在往Target RBA写过程中的进度决定的(如果没有dirtybuffer产生,那么就不会更新检查点位置信息)CKPT3秒会将检查点位置对应的数据块的rba(low cache rba-表示Instance Recovery时开始恢复的日志条目)更新和记录到控制文件的CHECKPOINT PROGRESS RECORDS区域当然同时被记录进控制文件的还有heartbeat等其他信息DBWn将检查点队列里面的dirty buffer写入到数据文件后,检查点的位置也要相应地往后移。
查点位置(checkpoint position)实际上就可以直接理解为是一个rba他指向着重做日志文件中的某条重做记录。在此检查点位置前的重做记录,其对应的buffercache中的dirty buffer已经被写进了数据文件,在此位置后的重做记录,所对应数据脏块有可能还在内存中。如果发生了实例崩溃,只需要在日志文件中找到检查点位置 (lowcache rba),从此处开始应用所有的重做日志文件,就完成了前滚操作。实例崩溃后,再次启动数据库,oracle会到控制文件中读取low cache rba,这就是检查点位置。从此处开始应用重做日志,应用到on disk rba的位置。on disk rba是磁盘中重做日志文件的最后一条重做记录的rba。如果某条重做记录的rba高于on disk rba,那说明此重做记录还没有被写进日志文件中,崩溃发生时,他是不可能被恢复的。on disk rbaoracle前滚操作的终点比这个更高的rba,都应该还驻留在log buffer中。还没有被LGWR写入日志文件。所以是不能被用于恢复的

DBWndirty buffer这个检查点过程中,Oracle也可以继续产生dirty bufferDBWn也不是一次要把所有dirty buffer全部写到磁盘(不同于完全检查点的地方),这样就提高了检查点的效率,使得数据库要做恢复的时候从这个最新位置开始做恢复,而不是从数据文件中的checkpoint scn(上一个完全检查点位置) 开始做恢复,这样将缩短恢复时间。

Oracle 11g
Concept里面提到:Anincremental checkpoint is a type of thread checkpoint partly intended to avoidwriting large numbers of blocks at online redo log switches. DBWn checks atleast every three seconds to determine whether it has work to do. When DBWnwrites dirty buffers, it advances the checkpoint position, causing CKPT towrite the checkpoint position to the control file, but not to the data fileheaders.
因此我们需要注意的是:增量检查点并不会去更新数据文件头,以及控制文件中数据库SCN以及数据文件条目的SCN信息而只是每3秒由CKPT进程去更新控制文件中的low cache rba信息,也就是检查点的位置

检查点位置发生变更后, Oracle主要通过4个参数和1个机制来控制检查点位置和最后的重做日志条目之间的距离(检查点队列的长度)Low cache rabàon disk rab之间的长度

fast_start_io_target (Oracle 9i
以后已经废弃)

参数用于表示数据库发生Instance Recovery的时候需要产生的IO总数,它通过v$filestatAVGIOTIM来估算的。比如我们一个数据库在发生Instance Crash后需要在10分钟内恢复完毕,假定OSIO每秒为500个,那么这个数据库发生Instance Recovery的时候大概将产生500*10*60=30,000IO,也就是我们将可以把fast_start_io_target设置为 30000

fast_start_mttr_target

们从上面可以看到fast_start_io_target来估算检查点位置比较麻烦。Oracle为了简化这个概念,从9i开始引入了fast_start_mttr_target这么一个参数,用于表示数据库发生Instance Recovery的时间,以秒为单位。这个参数我们从字面上也比较好理解,其中的mttrmeantime to recovery(平均恢复时间)的简写,如上例中的情况我们可以将fast_start_mttr_target设置为600。注意当设置了fast_start_mttr_target, fast_start_io_target这个参数将不再生效,从9ifast_start_io_target这个参数被Oracle废除了。

log_checkpoint_timeout

该参数用于表示检查点位置和重做日志文件末尾之间的时间间隔,以秒为单位默认情况下是1800。相fast_start_mttr_target,它也是时间,但它的时间值表示完成恢复操作所需要的时间,即从最后的检查点位置开始,应用所有日志直到日志末尾所需要的时间。而本参数log_checkpoint_timeout表示从最后的检查点位置开始,到日志末尾经过的时间。
low cache rba àon disk rba 之间的时间间隔


log_checkpoint_interval

该参数是表示检查点位置和重做日志末尾的重做日志块的数量,以OS块表示
low cache rba àon disk rba之间的数据块,块数量

 


90% OF SMALLEST REDO LOG

除了以上4个初始化参数外,Oracle内部事实上还将重做日志文件末尾前面90%的位置设为检查点位置。在每个重做日志中,这么几个参数指定的位置可能不尽相同,Oracle将离日志文件末尾最近的那个位置确认为检查点位置。

Oracle 9i,对检查点频率,建议只设置fast_start_mttr_target。根据需要,也可以通过设置 log_checkpoint_timeout,设置一个脏块保持脏状态的最大时间,而其他两个参数 fast_start_io_target,log_checkpoint_interval建议不再使用



实验:
SQL> show parameter log_checkpoints_to_
NAME                               TYPE        VALUE
------------------------------------ -----------------------------------------
log_checkpoints_to_alert            boolean     FALSE

SQL> alter system setlog_checkpoints_to_alert=true;
System altered
SQL> alter system checkpoint;
System altered
手工触发一个完全检查点,告警日志记录如下:
Thu Jun 07 01:27:17 2012
Beginning global checkpoint up to RBA[0x2d.1e4.10], SCN: 1716634
Completed checkpoint up to RBA [0x2d.1e4.10], SCN:1716634

接下来手工触发一个增量检查点:
SQL> alter system switch logfile;
System altered
告警日志如下:
Thu Jun 07 01:28:15 2012
Beginning log switch checkpoint up to RBA[0x2e.2.10], SCN: 1716660
Thread 1 advanced to log sequence 46
  Current log# 3 seq# 46 mem# 0:D:\ORACLE\...... \ONLINELOG\O1_MF_3_7TQZWZOY_.LOG
  Current log# 3 seq# 46 mem# 1:D:\ORACLE\ ……\ONLINELOG\O1_MF_3_7TQZX11D_.LOG

从这两个告警日志中,我们可以看到,完全检查点会马上将RBA下移,而增量检查点就会悠着点了。