oracle完全检查点和增量检查点
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
由于Oracle中LGWR和DBWR工作的不一致,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之前,由于没有chekpoint queue,也没有增量检查点的概念,oracle8之前发生完全检查点时,DBWn 会以一种无序的方式将所有的dirty buffer写出到数据文件,这个时候Oracle会冻结所有DML操作等候所有dirty buffer被写出,巨大的IO往往会影响到数据库的性能。后来随着Oracle数据库的发展和buffer cache的不断增大,oracle 意识到这个单一的Full checkpoint 机制已经不能满足需要,所以在Oracle 8i后提出增量检查点的概念,建立了checkpoint queue ,让dirty buffer header根据首次变化时候的顺序(LRBA)排列在queue里面。这样DBWn只要顺着queue的顺序写,而其他进程不必等候dbwr的写完成就可以继续。因此增量检查点的概念就由此产生了。
完全检查点在8i之后只有在下列两种情况下才会发生:
DBA手工执行alter system checkpoint的命令;
数据库正常shutdown (immediate,transcational,normal)。
2、增量检查点
说白了,就是
CKPT每3秒一次的检查DBWn写进度并在控制文件中记录检查点位置(checkpoint position)和更新heartbeat(心跳)信息
以及
CKPT定期触发DBWn去写checkpoint queue中的脏数据
这两项操作合一起被称为增量检查点。-->可能这块描述的过于笼统,大家继续往下看:-)
我们都知道:
被修改过的数据块,在oracle中都被统称为脏数据块(dirty buffer)。
所有的脏块被一个链表串起来,称做检查点队列(checkpoint queue)。
在buffer cache(缓冲区)中,每一个块都有一个buffer header简称BH,
在BH中有一个ckptq项, 此项目中记录了指向检查点队列上一个块和下一个块的指针。
如果某一个块不在检查点队列中,他的ckptq项为空.通过ckptq项oracle将所有的脏块串成了一个双向链表。这个双向链表就是检查点队列了。
Oracle 从8i开始引入了检查点队列(checkpoint queue)的概念,用于记录数据库里面当前所有的dirty buffer的信息,这些dirty buffer的信息按被修改的时间先后存放在checkpoint queue 里面(当块首次被更改时,块会立即被加进检查点队列),所涉及的条目主要包含
RBA (Redo Block Address,重做日志里面,用于标识事务期间,数据块在重做日志里面发生更改的编号) 数据块发生改变时在重做日志里面会发生相应的编号更改记录
一个脏块第一次被更新的时候产生的重做日志记录在重做日志文件中所对应的位置
和数据块的数据文件号和块号。
(checkpoint queue:1,RBA,2,数据块文件号,3,块号)
不论数据块(buffer)更改几次,它在checkpoint queue里面的位置始终保持不变,checkpoint queue也只会记录它最早的RBA(这个最早的RBA其实就是Low RBA,也就是数据块第一次被修改时所对应的RBA),从而保证最早更改的数据块能够尽快从内存写入数据文件。DBWR每到一定的时机,就会被触发(DBWn并不是只有当检查点发生的时候才写,它大约有10几种条件触发写操作),沿着检查点队列的顺序刷新脏块,同时CKPT进程,会监控
着检查点队列的长度,当检查点队列的长度达到一定限制时(具体有几个参数来确定checkpoing queue的长度,下面会提到比如log_checkpoint_timeout,fast_start_mttr_target等),CKPT会通知DBWR写脏块。CKPT会根据几个参数的设置和I/O的速度以及繁忙程度,计算出来一个Target rba(目标rba),DBWn会沿着检查点队列,按照dirty buffer的Low RBA 顺序将所有Target rba之前对应的脏块从内存写入数据磁盘文件。当CKPT通知完DBWn Target 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进程的检查点位置更新和心跳,所以说CKPT每3秒钟查看一下DBWn沿检查点队列写到了哪里,并且将这个位置设置为检查点位置(checkpont position)。也就是说检查点位置之前的块,都是已被DBWn刷新到磁盘上的块。因此我们可以理解为,CKPT进程每3秒会根据DBWn写的进度设置并记录一个检查点位置,也就是说这个检查点位置就是由DBWn的在往Target RBA写过程中的进度决定的(如果没有dirty buffer产生,那么就不会更新检查点位置信息)。因此CKPT每3秒会将检查点位置对应的数据块的rba (low cache rba-表示Instance Recovery时开始恢复的日志条目)更新和记录到控制文件的CHECKPOINT PROGRESS RECORDS区域,当然同时被记录进控制文件的还有heartbeat等其他信息。DBWn将检查点队列里面的dirty buffer写入到数据文件后,检查点的位置也要相应地往后移。
检查点位置(checkpoint position)实际上就可以直接理解为是一个rba,他指向着重做日志文件中的某条重做记录。在此检查点位置前的重做记录,其对应的buffer cache中的dirty buffer 已经被写进了数据文件,在此位置后的重做记录,所对应数据脏块有可能还在内存中。如果发生了实例崩溃,只需要在日志文件中找到检查点位置(low cache rba),从此处开始应用所有的重做日志文件,就完成了前滚操作。实例崩溃后,再次启动数据库,oracle会到控制文件中读取low cache rba,这就是检查点位置。从此处开始应用重做日志,应用到on disk rba 的位置。on disk rba是磁盘中重做日志文件的最后一条重做记录的rba。如果某条重做记录的rba高于on disk rba,那说明此重做记录还没有被写进日志文件中,崩溃发生时,他是不可能被恢复的。on disk rba是oracle前滚操作的终点。比这个更高的rba,都应该还驻留在log buffer中。还没有被LGWR写入日志文件。所以是不能被用于恢复的。
在DBWn写dirty buffer这个检查点过程中,Oracle也可以继续产生dirty buffer,DBWn也不是一次要把所有dirty buffer全部写到磁盘(不同于完全检查点的地方),这样就提高了检查点的效率,使得数据库要做恢复的时候从这个最新位置开始做恢复,而不是从数据文件中的checkpoint scn(上一个完全检查点位置) 开始做恢复,这样将缩短恢复时间。