温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Oracle检查点是什么

发布时间:2021-11-10 10:30:00 来源:亿速云 阅读:137 作者:iii 栏目:关系型数据库

本篇内容主要讲解“Oracle检查点是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Oracle检查点是什么”吧!

1.检查点概念--chkpoint 

检查点是一个数据库事件,存在的意义在于减少崩溃恢复crash recovery时间.
检查点事件由后台进程CKPT触发,当检查点发生时,CKPT通知DBWR进程将脏数据库dirtybuffer写出到数据文件上,更新数据文件头及控制文件上的检查点信息。
数据文件头的SCN是CHECKPOINT SCN.

checkpoint相关概念术语

在说明checkpoint工作原理之前我们先了解一些相关的术语。

RBA(Redo Byte Address), Low RBA(LRBA), High RBA(HRBA)

RBA就是重做日志块(redo log block)的地址,相当与数据文件中的ROWID,通过这个地址来定位重做日志块。RBA由三个部分组成:

  1. 日志文件序列号(4字节)——根据这个找到对应的日志文件地址。

  2. 日志文件块编号(4字节)——根据这个找到对应日志条目所在的日志文件块。

  3. 重做日志记录在日志块中的起始偏移字节数(2字节)——找到对应的日志条目。

通常使用RBA的形式有:

LRBA 数据缓存(buffer cache)中一个脏块第一次被更新的时候产生的重做日志记录在重做日志文件中所对应的位置就称为LRBA。 HRBA 数据缓存(buffer cache)中一个脏块最近一次被更新的时候产生的重做日志记录在重做日志文件中所对应的位置就称为HRBA。 checkpoint RBA 当一个checkpoint事件发生的时候,checkpoint进程会记录下当时所写的重做日志块的地址即RBA,此时记录的RBA被称为checkpoint RBA。从上一个checkpoint RBA到当前的checkpoint RBA之间的日志所保护的buffer cache中的脏块接下来将会被写入到数据文件当中去。

1、关于checkpoint的概述

checkpoint是oracle在数据库一致性关闭、实例恢复和oracle基本操作中不可缺少的机制,包含以下相关的含义:

                   A、检查点的位置(checkpoint position)为一种数据结构,在redo流中记录的SCN号是在进行数据库实例恢复起始位置。

检查点的位置由在数据缓冲池中存在的最老的脏数据位置决定,检查点的位置相当于一个指向redo流的指针,并且检查点的信息存储在控制文件和数据文件的头中。

   B、将数据缓冲区中修改后的脏数据写入到磁盘中。

2、checkpoint的目的

A、当实例恢复或者介质恢复时,减少恢复所需要的时间

B、确保在数据缓冲区中的脏数据已经写入到磁盘当中

C、确保在进行数据库一致性关闭的时候所有提交的数据都写入到磁盘当中

3、什么时候数据库启动checkpoint

CKPT进程负责将checkpoint的信息写入到数据文件头中和控制文件中,包括以下几种类型的检查点

A、thread checkpoint(线程检查点或者数据库检查点)

数据库将所有在数据缓冲区内由redo修改过的数据写入到磁盘中在某些动作之前,这个线程检查点在所有的实例中的集合称之为数据库检查点(database checkpoint),线程检查点发生在下列情况下:

——数据库一致性关闭的时候

——ALTER SYSTEM CHECKPOINT语句的时候

——在线日志切换的时候

——ALTER DATABASE BEGIN BACKUP语句的时候

B、tablespace and data file checkpoint(表和数据文件检查点)

数据库将所有在数据缓冲区内由redo修改过的数据写入到磁盘中在具体动作之前,表空间的检查点是数据文件检查点的集合,每个数据文件都在这个表空间之内,此种检查点发生在以下情况:

——将一个表空间设置为只读的方式

——将一个表空间设置为offline

——数据文件大小变化的时候

——执行ALTER TABLESPACE BEGIN BACKUP的时候

C、incremental checkpoint(增量检查点)

增量检查点是线程检查点的一种,是为了避免在线日志切换的时候需要写入大量的脏数据到磁盘中,DBWn每三秒检查一次看是否有数据是否要写入到磁盘当中,当DBWn进程需要将脏数据写入到磁盘中时,从而推进检查点的位置,导致CKPT进程将检查点位置信息写入到控制文件中,但是不会写入到数据头文件中。

D、其他的检查点包括实例和介质恢复检查点、检查点当schema对象被dropped和truncated的时候

4、相关进程CKPT

CKPT进程的全称为checkpoint process,负责:

A、更新控制文件和数据头文件中的检查点信息

B、通知DBWn进程将脏数据写入磁盘中

检查点信息包括:

A、检查点位置

B、SCN

C、在线日志文件中开始恢复的位置

CKPT进程不负责将脏数据写入到磁盘中,不负责将redo缓冲区的数据写入到在线日志文件中

DBWn进程负责将脏数据存盘,LGWR进程负责将redo缓冲区中的书籍存盘



检查点工作原理:
在数据库中,进行数据修改时,需要先将数据读和内存中buffer cache,修改数据同时,ORACLE会记录重做redo信息用于恢复,有了重做日志信息存在,ORACLE不需要在事务提交时commit立刻将变化的数据写回磁盘,因为立刻写效率会低。重做信息存在也为数据崩溃后,数据可以恢复。如断电,内存中修改过未写入数据文件的数据丢失,下一次数据库启动时,可以通过重做日志进行事务重演(不管是否提交),即前滚。将数据库恢复至崩溃前状态,然后数据库可以打开提供使用,之后ORACLE将未提交的事务回滚。
检查点存在是为了缩短上述数据恢复的时间。
当检查点发生时,此时的SCN称为checkpoint scn,ORACLE会通知DBWR,把修改过的数据,即此checkpoint scn之前的脏数据dirty data从buffer cache写入磁盘,写入完成后,CKPT进程会相应更新控制文件和数据文件头,记录此检查点信息,标识变更。
检查点完成后,此检查点之前修改过后 数据都已经写出到数据文件,重做日志中的相应重做记录对于实例恢复已经无用(物理恢复有用)。
######################################################################

2.增量检查点概念 incremental checkpoint 及CKPTQ,FILEQ

检查点队列,checkpoint queue,CKPTQ;

在数据库内部,每个脏数据块会被记录到检查点队列,按LRBA(LOW RBA 第一次修改数据块对应的redo block address,后面修改的RBA称为HRBA)顺序排列,如果一个数据块多次修改,该数据块在检查点队列上顺序不变化。
非脏块的buffer header中的CKPTQ信息为空。
执行增量检查点时,DBWR从检查点队列按照LOW RBA顺序写出,先修改的数据可以被按优先顺序写出,实例检查点因此可以不被增进。
同时CKPT进程阶段性使用轻量级控制文件更新协议将当前最低RBA写入控制文件,CKPT在进行轻量级更新时,不改写控制文件中数据文件中检查点信息以及数据文件头信息,只记录控制文件检查点SCN,controlfile checkpointed at scn 并根据增量检查点写出增进RBA信息。
通过增量检查点,数据库可以将全部写出改为增量渐进写出,从而极大减少对于数据库性能的影响,而检查点队列进一步将RBA和检查点关联起来,从而可以通过检查点确定恢复的起点。

与CKPTQ相关的是:文件检查点队列 file queue  FILEQ与对象队列Obj-Q 

文件检查点提高了表空间检查点TABLESPACE CHECKPOINT的性能,每个dirty buffer同时链接到CKPTQ和FILEQ,CKPTQ包含实例所有需要执行检查点的BUFFER,FILEQ包含属于特定文件需要执行检查点的BUFFER,每个文件都包含一个文件队列,在执行表空间检查点请求时使用FILEQ。--表空间OFFLINE会触发表空间检查点。

3.CKPT进程在增量检查点中的作用:

CKPT进程监控着检查点队列的长度,当检查点队列长度达到一定限制时,CKPT会通知DBWR写脏块
CKPT会根据参数的设置和I/O的速度以及繁忙程度,计算出来一个Target rba(目标rba),DBWR会沿着检查点队列,将所有Target rba之前的脏块刷新到磁盘.当CKPT通知完DBWR Target rba后,CKPT的任务就结束了.并不会等待DBWR写完所有的Target rba之前的脏块.

通知DBWR写脏块,这是CKPT的任务之一,CKPT另一个任务,就是每3秒,检测一次DBWR的写进度.
检查点队列最前面的块被称为检查点位置.DBWR是沿着检查点队列写脏块的,CKPT每3秒钟查看一下DBWR沿检查点队列写到了哪里,并且将这个位置设置为检查点位置.也就是说检查点位置之前的块,都是已被DBWR刷新到磁盘上的块.
这个3秒一次检查DBWR进度的工作,也是CKPT的一个重要的任务.CKPT每3秒一次将检查点位置记录进控制文件,当然同时被记录进控制文件的还有'心跳'等其他信息.

CKPT每3秒一次的工作和CKPT定期触发DBWR,这两项操作合一起被称为--增量检查点.

4.dbwr 写CKPTQ上脏块的方式:

在检查点队列中,脏块根据按LRBA顺序排列,DBWR每到一定的时机,被触发。
硬件能力、脏块数、Redo数三个指标,是DBWR是否写脏块的依据。
DBWR什么时候(多久)判断一次这三个值标:3s
也就是:DBWR 3秒醒来,依据三个指标判断是否触发------“增量检查点写”

5.fast_start_mttr_target与增量检查点

一、关于FAST_START_MTTR_TARGET概念:  --此段百度哈哈

是一个加快实例恢复的参数,我们可以根据服务级别来定义一个合理的、可接受的值,该值的单位为秒。比如设定为60s,即2分钟。
假定该值处于合理的情况之下,则一旦实例崩溃,在60s以内实例应当能够被恢复。合理即是该值不能太大,也不能太小。太大则实例恢复所需的时间较长,太小则导致大量数据的及时写入,增加了系统的I/O。
影响实例恢复时间长短的主要因素即是从最近检查点位置到联机重做日志尾部之间的距离。距离越长则所需要的cache recovery 和undo、redo的时间越长。所以如何有效的缩短最近检查点位置与联机重做日志尾部之间的距离,这正是FAST_START_MTTR_TARGET的目的。

关于检查点的触发条件有很多,比如日志切换、数据库shutdown、开始结束备份表空间等。检查点的分类也很多,比如完全检查点、部分检查点、增量检查点等。
FAST_START_MTTR_TARGET的值实际上也是触发检查点的一个触发条件。当内存中产生的dirty buffer所需的恢复时间(estimated_mttr)如果到达FAST_START_MTTR_TARGET的指定时间,则检查点进程被触发。检查点进程一旦被触发,将通知DBWn进程将按检查点队列顺序将脏数据写入到数据文件,从而缩短了最后检查点位置与联机重做日志间的距离,减少了实例恢复所需的时间。

二、FAST_START_MTTR_TARGET参数的设置

9i之后(包括9i):fast_start_mttr_target:以实例恢复时间为单位(硬件能力、脏块数、Redo数)
10G之后,fast_start_mttr_target默认值为0,即开启自调节检查点:self tune checkpoint ,自调节检查点的受影响因素有:硬件能力、脏块数、Redo数
自调节检查点对应隐含参数:_disable_selftune_checkpointing:
_disable_selftune_checkpointing          Disable self-tune checkpointing             FALSE       
SYS@ bys3>show parameter statistics_level  --此参数为typical 或者all,再加上FAST_START_MTTR_TARGET 设置为非零值就启用MTTR Advisory

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
statistics_level                     string      TYPICAL
SYS@ bys3>show parameter mttr
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
fast_start_mttr_target               integer     0
从alert日志中数据库启动时的信息可以发现:
[oracle@bys3 ~]$ cat alert_bys3.log |grep MTTR
MTTR advisory is disabled because FAST_START_MTTR_TARGET is not set

显式的设置alter system set FAST_START_MTTR_TARGET=0会关闭自动调节,重启数据库在alter日志中可以发现:
MTTR advisory is disabled because FAST_START_MTTR_TARGET is not set

当FAST_START_MTTR_TARGET显示设为非零
SYS@ bys3>alter system set fast_start_mttr_target=25;
即: statistics_level参数为typical 或者all,再加上FAST_START_MTTR_TARGET 设置为非零值就启用MTTR Advisory
此时alert日志中不会有MTTR信息--因为已经正常启动MTTR Advisory

三、关于启动MTTR Advisory时v$instance_recovery;视图的使用: --未开启MTTR Advisory时此视图内容为空。

SYS@ bys3>select mttr_target_for_estimate ,dirty_limit,estd_cache_writes ,estd_cache_write_factor ,estd_total_writes ,estd_total_write_factor  from v$mttr_target_advice;
MTTR_TARGET_FOR_ESTIMATE DIRTY_LIMIT ESTD_CACHE_WRITES ESTD_CACHE_WRITE_FACTOR ESTD_TOTAL_WRITES ESTD_TOTAL_WRITE_FACTOR
------------------------ ----------- ----------------- ----------------------- ----------------- -----------------------
                      18        1067                57                       1               806                       1
                      17        1000                57                       1               806                       1
                      19        1268                57                       1               806                       1
                      20        1507                57                       1               806                       1
SYS@ bys3>select  target_mttr,estimated_mttr from v$instance_recovery; 
TARGET_MTTR ESTIMATED_MTTR
----------- --------------
         20             12
--mttr_target_for_estimate有一个值为的最接近设定的目标时间20,以及由系统计算出的的target_mttr时间20
--同时也给出了几组不同的mttr_target值及dirty_limit,cache_write,io 等来供选择,设定合适的mttr值




检查点(Checkpoint)优化及故障排除指南 (文档 ID 1526118.1)

Oracle检查点是什么类型:状态:上次主更新:上次更新:语言:BULLETINPUBLISHED2015-6-232016-12-7English简体中文???

Oracle检查点是什么

适用于:

Oracle Database - Enterprise Edition
本文档所含信息适用于所有平台

用途

本文档旨在使数据库管理员更好地了解增量检查点(Checkpoint),并对检查点(Checkpoint)优化所用的下列四个初始化参数进行了描述:
           -  FAST_START_MTTR_TARGET 
           -  LOG_CHECKPOINT_INTERVAL 
           -  LOG_CHECKPOINT_TIMEOUT 
           -  LOG_CHECKPOINTS_TO_ALERT 
此外,本文档还介绍了如何解释和处理检查点错误:ALERT.LOG 文件中报告的“Checkpoint not Complete(检查点未完成)”和“Cannot Allocate New Log(无法分配新日志)”。

详细信息

目录:
 

1.  什么是检查点?
2. 检查点和性能
3. 与增量检查点相关的参数
4. Redo(重做)日志和检查点
5. 了解检查点错误消息(“Cannot allocate new log”和“Checkpoint not complete”)
6. Oracle 版本信息
7. 使用 Statspack 确定检查点问题
  
 

检查点优化和错误处理


1.  什么是检查点?

检查点是一种将内存中的已修改数据块与磁盘上的数据文件进行同步的数据库事件。通过Checkpoint Oracle 确保了被 transaction 修改过数据可以被同步至磁盘。Oracle transaction 提交的时候不会将已修改数据块同步写入磁盘上。

检查点有两个用途:(1) 确保数据一致性,和 (2) 实现更快的数据库恢复。如何更快地恢复?由于直至检查点生成时所有的数据库更改均已记录在数据文件中,因此无需再应用先于检查点的 redo 日志条目。检查点必须确保高速缓存中所有已修改的缓冲数据均已切实写入到相应的数据文件中,以避免在发生崩溃(实例或磁盘故障)时可能会出现的数据丢失。
 

Oracle 只有在特定条件下才会将脏缓存写入磁盘:

  - shadow process 需要扫描的数据块个数超过 db_block_buffers 参数的四分之一。
  - 每三秒钟。
  - 生成一个检查点时。

检查点通过五种类型的事件来实现:

  - 每次切换 redo 日志文件时。
  - 达到 LOG_CHECKPOINT_TIMEOUT 的延迟时。
  - 当前 redo 日志文件中已存在了大小为 (LOG_CHECKPOINT_INTERVAL* OS块的大小(bytes))的数据。
  - 直接由 ALTER SYSTEM SWITCH LOGFILE 命令实现。
  - 直接使用 ALTER SYSTEM CHECKPOINT 命令实现。
 

在检查点期间会发生以下操作:
 -  DBWR 将缓冲区缓存中所有已修改的数据库块写回到数据文件中,
 -  检查点进程 (ckpt) 更新所有数据文件的文件头,以反映上一个检查点发生的时间 (SCN)


2. 检查点和性能

检查点的优化常常会使数据库管理员左右为难。频繁的检查点会实现更快的数据库恢复,但也会导致数据库性能降低。那么,DBA 如何解决这一问题呢?

根据数据库中的数据文件数量,检查点将会是一种高度占用资源的操作,因为所有数据文件头在检查点期间都会被冻结。关于检查点的频率设置,需要对性能进行权衡。检查点频率越高,就能在数据库崩溃后更快地实现恢复。这也是为什么一些不太能忍受意外系统停机的客户现场常常会选择此选项的原因。但是,在很多情况下,频繁的检查点可能会导致性能降低,这使得上述观点并不能完全站稳脚跟。 我们假设数据库已启动,且有 95% 的时间处于运行状态,剩下 5% 未运行时间是由于出现偶发的实例崩溃或硬件故障,需要进行数据库恢复。对于大多数的客户现场而言,优化 95% 的性能相比于极少的 5% 停机时间要更具意义。

本文档假设性能是您的首要考虑事项,并由此给出相应的建议。因此,您的目标是通过优化尽量减少检查点的频率。

优化检查点涉及到下面四个关键初始化参数:

           -  FAST_START_MTTR_TARGET 
           -  LOG_CHECKPOINT_INTERVAL 
           -  LOG_CHECKPOINT_TIMEOUT 
           -  LOG_CHECKPOINTS_TO_ALERT

下面将详细讨论这些参数。

同时,还针对alert日志中出现的“checkpoint not complete”消息给出了处理建议,这些消息说明redo 日志和检查点需要优化。


3. 与增量检查点相关的参数
注意:日志文件切换将始终覆盖由以下参数引起的检查点。

  • FAST_START_MTTR_TARGET

自 Oracle 9i 以来,FAST_START_MTTR_TARGET 参数已成为优化增量检查点目标的首选方法。通过 FAST_START_MTTR_TARGET,您可以指定数据库执行单实例的崩溃恢复所要花费的秒数。基于内部统计信息,增量检查点会自动调整检查点目标,以满足 FAST_START_MTTR_TARGET 的要求。
V$INSTANCE_RECOVERY.ESTIMATED_MTTR 显示当前预计的平均恢复时间 (MTTR)(以秒为单位)。即使未指定 FAST_START_MTTR_TARGET,也同样会显示此值。
V$INSTANCE_RECOVERY.TARGET_MTTR 显示由系统强制执行的有效 MTTR 目标(以秒为单位)。
V$MTTR_TARGET_ADVICE 显示在当前的 MTTR 设置下由当前的工作负载产生的 I/O 数量,以及在其他 MTTR 设置下将由当前的工作负载产生的预计 I/O 数量。此视图可帮助用户在运行时性能和设置 FAST_START_MTTR_TARGET 以实现快速恢复之间进行权衡。

  • LOG_CHECKPOINT_INTERVAL

LOG_CHECKPOINT_INTERVAL 参数指定增量检查点目标应滞后于当前日志尾的最大 redo 块数量。
如果指定了 FAST_START_MTTR_TARGET,就不应设置 LOG_CHECKPOINT_INTERVAL 或将其设置为 0。在大多数 Unix 系统上,操作系统块大小都是 512 字节。
也 就是说,将 LOG_CHECKPOINT_INTERVAL 的值设置为 10,000 就意味着增量检查点目标相对于当前日志尾的滞后不得超过 5,120,000 (5M) 字节。以此计算,如果 redo 日志的大小为 20M,则会对每个日志产生 4 个检查点。

LOG_CHECKPOINT_INTERVAL 会影响检查点的发生时间,这意味着应特别注意此参数的设置,保持其随 redo 日志文件的大小变化而更新。检查点的频率是影响数据库从意外故障中恢复所需时间的因素之一。检查点之间的间隔越长,则在发生系统崩溃时,数据库恢复所需的 时间就越长。检查点间隔越短意味着数据库的恢复速度越快,但是代价是检查点操作会消耗更多的资源。

此参数还会影响在恢复的前滚阶段期间完成数据库恢复操作所需的时间。实际的恢复时间取决于此时间,以及其他因素,例如故障类型(实例或系统崩溃、介质故障等)以及需要应用的归档 redo 日志数量。

  • LOG_CHECKPOINT_TIMEOUT

LOG_CHECKPOINT_TIMEOUT 参数指定增量检查点目标应滞后于当前日志尾的最长秒数。
换句话说,它指定缓冲区缓存中的脏缓存可以保持脏状态的时间。
检查点频率影响数据库从意外故障中恢复所需的时间。检查点之间的间隔越长,数据库恢复所需的时间就越多。

Oracle 建议使用 LOG_CHECKPOINT_INTERVAL 而不是 LOG_CHECKPOINT_TIMEOUT 来控制检查点间隔,后者会每“n”秒启动一次检查点,而不管事务频率。这可能会导致在事务量变化的情况下出现不必要的检查点。只要可能,就必须避免不必要的检查点,以实现最佳性能。

许多人会有这样一种误解:将 LOG_CHECKPOINT_TIMEOUT 设置为给定值之后,系统就会按该间隔启动日志切换,从而启用用于stand-by数据库配置的恢复窗口。日志切换会引起检查点,但检查点并不会引起日志切换。引起日志切换的唯一方式是使用 ALTER SYSTEM SWITCH LOGFILE 进行手动操作或重新调节 redo 日志大小,以引起更为频繁的切换。这由操作系统块而非时间间隔控制。
在线 redo 日志的大小对性能和恢复至关重要。
有关 redo 日志和检查点的信息,请参考以下其他部分。

  • LOG_CHECKPOINTS_TO_ALERT

通过 LOG_CHECKPOINTS_TO_ALERT,您可以将检查点记录到alert日志中。

这样做有助于确定检查点是否按所需频率发生。
在 Oracle9i 之前,此参数为静态参数。
Oracle 通常建议将此参数设置为 TRUE,因为开销很小,可以忽略不计,但alert日志中的信息可能会非常有用。

有关上述实例参数会如何影响检查点的更多详细信息,请参阅 Note:76713.1


4. Redo 日志和检查点

每次切换日志时都会发生一次检查点。如果上一个检查点已在进行中,由日志切换引起的检查点将覆盖当前检查点。

此时就需要大小合适的 redo 日志,以避免因频繁的日志切换而引起不必要的检查点。另外,增量检查点目标和日志尾之间的间隔也会受“最小在线日志文件大小的 90%”设置所限制。这样可确保在大多数情况下,日志切换不必等待检查点。因此,日志文件大小应配置得足够大。一个好的办法是,最多每二十分钟切换一次日志。日志文件过小会增加检查点活动并降低性能。Oracle 建议用户将所有在线日志文件设置为同一大小,且每个线程至少拥有两个日志组。若要监视日志切换发生的速度,以及随后的检查点发生的速度,alert日志是一个很有价值的工具。
  
以下是通过alert日志发现日志切换过于频繁的示例:
 

Fri May 16 17:15:43 1997 
Thread 1 advanced to log sequence 1272 
  Current log# 3 seq# 1272 mem# 0: /prod1/oradata/logs/redologs03.log 
Thread 1 advanced to log sequence 1273 
  Current log# 1 seq# 1273 mem# 0: /prod1/oradata/logs/redologs01.log 
Fri May 16 17:17:25 1997 
Thread 1 advanced to log sequence 1274 
  Current log# 2 seq# 1274 mem# 0: /prod1/oradata/logs/redologs02.log 
Thread 1 advanced to log sequence 1275 
  Current log# 3 seq# 1275 mem# 0: /prod1/oradata/logs/redologs03.log 
Fri May 16 17:20:51 1997 
Thread 1 advanced to log sequence 1276 
  Current log# 1 seq# 1276 mem# 0: /prod1/oradata/logs/redologs01.log 
 

如果 redo 日志每 3 分钟切换一次,您就会察觉到性能降低。这表明 redo 日志不够大,不能有效地处理该事务负载。

有关如何估计 redo 日志文件的适当大小的详细信息,请参阅 Note:1038851.6 。有关如何重新调节在线 redo 日志文件大小的示例,请参阅 Note:1035935.6 。


5. 了解检查点错误消息(“Cannot allocate new log”和“Checkpoint not complete”)

有时,您可以在 alert.log 文件中看到以下相应消息:

  Thread 1 advanced to log sequence 248 
    Current log# 2 seq# 248 mem# 0: /prod1/oradata/logs/redologs02.log 
  Thread 1 cannot allocate new log, sequence 249 
  Checkpoint not complete 
 

此信息表明 Oracle 希望重新使用某个 redo 日志文件,但当前的检查点位置仍位于该日志中。在这种情况下,Oracle 必须等到检查点位置通过该日志。由于增量检查点目标相对于当前日志尾的滞后绝不会超过最小日志文件大小的 90% 以上,因此,如果 DBWR 写入速度过慢,或者在日志全满之前发生日志切换,或者日志文件过小,就会遇到这种情况。在数据库等待检查点时,redo 生成过程会停止,直到完成日志切换。

6. Oracle 版本信息

在 Oracle8i 中,初始化参数 FAST_START_IO_TARGET 会使增量检查点自动调整其目标,从而使恢复所需的数据块数量不多于 FAST_START_IO_TARGET 设置的值。自 Oracle 9i 开始,已弃用此参数,取而代之的是参数 FAST_START_MTTR_TARGET。

7. 使用 Statspack 确定检查点问题

您可以每 15 分钟左右收集一次 Statspack 快照,这些快照报告将收集有关在该时间段已开始的检查点数量、已完成的检查点数量及检查点发生时写入的数据库缓冲数量的有用信息。此外,还包含关于 redo 活动的统计信息。通过收集和比较这些快照报告,您可以完整地了解不同时期的检查点性能。

Statspack 报告中另一个值得关注的内容是等待事件,下面的等待事件明确指出了 redo 日志吞吐量和检查点的问题:

log file switch (checkpoint incomplete) 
log file switch (archiving needed) 
log file switch/archive 
log file switch (clearing log file) 
log file switch completion 
log switch/archive 
log file sync

 

如果上述等待事件中的一个或多个频繁地出现,且相关数值较大,那您就需要采取行动了,例如添加更多的在线 redo 日志文件,或增加其大小和/或修改检查点参数。

参考

NOTE:76713.1 - 8i Parameters that Influence Checkpoints
NOTE:1038851.6 - How to Estimate Size of Redo Logs



11G中FAST_START_MTTR_TARGET参数

SQL> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

SQL> col name for a20
SQL> col value for a30
SQL> select name,value from v$spparameter where name like 'fast_start_mt%';

NAME                 VALUE
-------------------- ------------------------------
fast_start_mttr_targ
et

alert.log中信息 
Successful open of redo thread 2
MTTR advisory is disabled because FAST_START_MTTR_TARGET is not set
Sat Jul 13 13:27:28 2013
SMON: enabling cache recovery
ARC3: Archival started
ARC0: STARTING ARCH PROCESSES COMPLETE

概念说明

一、关于FAST_START_MTTR_TARGET参数

        是一个加快实例恢复的参数,我们可以根据服务级别来定义一个合理的、可接受的值,该值的单位为秒。比如设定为60s,即1分钟。

    假定该值处于合理的情况之下,则一旦实例崩溃,在60s以内实例应当能够被恢复。合理即是该值不能太大,也不能太小。太大则实例恢

    复所需的时间较长,太小则导致大量数据的及时写入,增加了系统的I/O。

        影响实例恢复时间长短的主要因素即是从最近检查点位置到联机重做日志尾部之间的距离。距离越长则所需要的cache recovery 和undo、

    redo的时间越长。所以如何有效的缩短最近检查点位置与联机重做日志尾部之间的距离,这正是FAST_START_MTTR_TARGET的目的。

        关于检查点的触发条件有很多,比如日志切换、数据库shutdown、开始结束备份表空间等。检查点的分类也很多,比如完全检查点、部

    分检查点、增量检查点等。

        FAST_START_MTTR_TARGET的值实际上也是触发检查点的一个触发条件。当内存中产生的dirty buffer所需的恢复时间(estimated_mttr)

    如果到达FAST_START_MTTR_TARGET的指定时间,则检查点进程被触发。检查点进程一旦被触发,将通知DBWn进程将按检查点队列顺序将脏数

    据写入到数据文件,从而缩短了最后检查点位置与联机重做日志间的距离,减少了实例恢复所需的时间。

二、两个重要的视图

        v$instacne_recovery

        v$mttr_target_advice

三、设定FAST_START_MTTR_TARGET

        根据实际需要来设定FAST_START_MTTR_TARGET的值,这个值的设定需要考虑到可接受的实例的恢复时间、可承受的I/O吞吐量等等。

        假定我们将该值设定为

            SQL> alter system set fast_start_mttr_target = 30 ;

        在事务频繁的时间段来考察视图v$instacne_recovery提供的值

一、关于FAST_START_MTTR_TARGET参数

        是一个加快实例恢复的参数,我们可以根据服务级别来定义一个合理的、可接受的值,该值的单位为秒。比如设定为60s,即1分钟。

    假定该值处于合理的情况之下,则一旦实例崩溃,在60s以内实例应当能够被恢复。合理即是该值不能太大,也不能太小。太大则实例恢

    复所需的时间较长,太小则导致大量数据的及时写入,增加了系统的I/O。

        影响实例恢复时间长短的主要因素即是从最近检查点位置到联机重做日志尾部之间的距离。距离越长则所需要的cache recovery 和undo、

    redo的时间越长。所以如何有效的缩短最近检查点位置与联机重做日志尾部之间的距离,这正是FAST_START_MTTR_TARGET的目的。

        关于检查点的触发条件有很多,比如日志切换、数据库shutdown、开始结束备份表空间等。检查点的分类也很多,比如完全检查点、部

    分检查点、增量检查点等。

        FAST_START_MTTR_TARGET的值实际上也是触发检查点的一个触发条件。当内存中产生的dirty buffer所需的恢复时间(estimated_mttr)

    如果到达FAST_START_MTTR_TARGET的指定时间,则检查点进程被触发。检查点进程一旦被触发,将通知DBWn进程将按检查点队列顺序将脏数

    据写入到数据文件,从而缩短了最后检查点位置与联机重做日志间的距离,减少了实例恢复所需的时间。

        关于实例的恢复以及检查的具体分类描述等,请参考:

             Oracle 实例恢复

             Oracle实例和Oracle数据库(Oracle体系结构)            

二、FAST_START_MTTR_TARGET = 0的质疑

        很多文章描述了FAST_START_MTTR_TARGET = 0,即为未设置,表示启用自动检查点功能,下面是来自Oracle的官方文档中的一段,

    原文的链接为: Fast-Start Fault Recovery

        Fast-start checkpointing refers to the periodic writes by the database writer (DBWn) processes for the purpose of writing changed data blocks from the Oracle buffer cache to disk and advancing the thread-checkpoint. Setting the database parameter FAST_START_MTTR_TARGET to a value greater than zero enables the fast-start checkpointing feature. Fast-start checkpointing should always be enabled for the following reasons:

        It reduces the time required for cache recovery, and makes instance recovery time-bounded and predictable. This is accomplished by limiting the number of dirty buffers (data blocks which have changes in memory that still need to be written to disk) and the number of redo records (changes in the database) generated between the most recent redo record and the last checkpoint.

        Fast-Start checkpointing eliminates bulk writes and corresponding I/O spikes that occur traditionally with interval- based checkpoints, providing a smoother, more consistent I/O pattern that is more predictable and easier to manage. If the system is not  already near or at its maximum I/O capacity, fast-start checkpointing will have a negligible impact on performance. Although fast-start checkpointing results in increased write activity, there is little reduction in database throughout, provided the system has sufficient I/O capacity.

        从第一段中粗体标记的描述来看,当设定一个大于0的值给FAST_START_MTTR_TARGET,则自动调整检查点功能别启用。即fast-start

    checkpointing,更准确的说应该是快速启动检查点功能

        再看下面的这段描述,这段来自Oracle 10g OCP workshop I 14-17 英文版教程(Edition 3.1 December 2008)

        Explicit setting of the FAST_START_MTTR_TARGET parameter to 0 disables automatic checkpoint tuning.Explicit setting of the FAST_START_MTTR_TARGET parameter to a value other than 0 also enables the Redo Log Advisor.

        从上面的描述可以看出,如果将FAST_START_MTTR_TARGET设置为将关闭检查点自动调整功能。

三、设定FAST_START_MTTR_TARGET

        根据实际需要来设定FAST_START_MTTR_TARGET的值,这个值的设定需要考虑到可接受的实例的恢复时间、可承受的I/O吞吐量等等。

        假定我们将该值设定为

            SQL> alter system set fast_start_mttr_target = 30 ;

        在事务频繁的时间段来考察视图v$instacne_recovery提供的值

        SQL> desc v$instance_recovery;   --查看v$instance_recovery视图的结构

         Name                                      Null?    Type

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

         RECOVERY_ESTIMATED_IOS                             NUMBER

         ACTUAL_REDO_BLKS                                   NUMBER

         TARGET_REDO_BLKS                                   NUMBER

         LOG_FILE_SIZE_REDO_BLKS                            NUMBER

         LOG_CHKPT_TIMEOUT_REDO_BLKS                        NUMBER

         LOG_CHKPT_INTERVAL_REDO_BLKS                       NUMBER

         FAST_START_IO_TARGET_REDO_BLKS                     NUMBER

         TARGET_MTTR                                        NUMBER

         ESTIMATED_MTTR                                     NUMBER

         CKPT_BLOCK_WRITES                                  NUMBER

         OPTIMAL_LOGFILE_SIZE                               NUMBER

         ESTD_CLUSTER_AVAILABLE_TIME                        NUMBER

         WRITES_MTTR                                        NUMBER

         WRITES_LOGFILE_SIZE                                NUMBER

         WRITES_LOG_CHECKPOINT_SETTINGS                     NUMBER

         WRITES_OTHER_SETTINGS                              NUMBER

         WRITES_AUTOTUNE                                    NUMBER

         WRITES_FULL_THREAD_CKPT                            NUMBER

        两个字段:

            TARGET_MTTR         -->参照fast_start_mttr_target参数中设定的值计算出来的一个值

            ESTIMATED_MTTR      -->系统根据dirty buffer 中计算出来的值

        可能出现的情况

            1.TARGET_MTTR > ESTIMATED_MTTR  --大量的事务将导致这种情况的出现

            2.TARGET_MTTR < ESTIMATED_MTTR  --数据库刚刚启动时,几乎没有事务时会出现这种情况

SQL> select recovery_estimated_ios,actual_redo_blks ,target_redo_blks ,

  2  target_mttr,estimated_mttr

  3  from v$instance_recovery;

RECOVERY_ESTIMATED_IOS ACTUAL_REDO_BLKS TARGET_REDO_BLKS TARGET_MTTR ESTIMATED_MTTR

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

                    55              147              707         33             27

        可以在负载的情况下根据TARGET_MTTR来值通过v$mttr_target_advice调整该参数

四、启用MTTR Advisory

        需要设置两个参数

            STATISTICS_LEVEL         -->置为typical 或者all

            FAST_START_MTTR_TARGET   -->置为非零值

        SQL> show parameter mttr;    --目标mttr_time设定为30 s

        NAME                                 TYPE        VALUE

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

        fast_start_mttr_target               integer     30

        SQL> select  target_mttr,estimated_mttr from v$instance_recovery;   --系统计算出来的mttr为33

        TARGET_MTTR ESTIMATED_MTTR

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

                 33             27     

        SQL> select mttr_target_for_estimate tar_est,dirty_limit,estd_cache_writes est_c_w,

          2  estd_cache_write_factor est_c_w_f,estd_total_writes est_t_w,estd_total_write_factor est_t_w_f

          3  from v$mttr_target_advice;

           TAR_EST DIRTY_LIMIT    EST_C_W  EST_C_W_F    EST_T_W  EST_T_W_F

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

                60        5028       3762      .7376       3762      .7376

                34        1000       5100          1       5100          1

                68        6248       3762      .7376       3762      .7376

                52        3808       3762      .7376       3762      .7376

                45        2735       3845      .7539       3845      .7539

        --mttr_target_for_estimate有一个值为的最接近设定的目标时间30,以及由系统计算出的的target_mttr时间33

        --同时也给出了几组不同的mttr_target值及dirty_limit,cache_write,io 等来供DBA来选择设定合适的mttr

五、两个重要的视图

        v$instacne_recovery

        v$mttr_target_advice



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

1、完全检查点

在Oracle8i之前,数据库的发生的检查点都是完全检查点。完全检查点会将数据缓冲区里面所有的脏数据块写入相应的数据文件中,同时将最新的checkpoint scn更新到所有的数据文件头部及控制文件。保证数据库的处于一致的状态。需要注意的是,完 全检查点产生的时候,CKPT并不是把当前完全检查点发生那一时刻的SCN更新到控制文件和数据文件头,而是将这个触发检查点时刻DBWn当前刚写完 dirty buffer对应的SCN更新到控制文件和数据文件头,也就是说,更新控制文件和数据文件头的SCN是滞后于完全检查点的发生那一时刻的SCN的,这个从恢复的原理也很容易理解,因为检查点发生的时候要写入dirty buffer还没有写入,自然不能立即更新成当前的SCN了。需 要注意的是, 在oracle8之前,由于没有chekpoint  queue,也没有增量检查点的概念,发生完全检查点时,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,重做日志里面用于标识事务期间数据块在重做日志里面发生更改的编号)和数据块的数据文件号和块号。

不 论数据块(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(上一个完全检查点位置) 开始做恢复,这样将缩短恢复时间。

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

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

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

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

fast_start_mttr_target

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

log_checkpoint_timeout

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

log_checkpoint_interval

该参数是表示检查点位置和重做日志末尾的重做日志块的数量,以OS块表示。

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建议不再使用。



什么是增量检查点?
最近对增量检查点和全局检查点有些疑惑,查看了很多的资料感觉都写得非常复杂不容易理解。下面贴出一些自己的心得,如果有错误的地方希望得到指正。
                                    
1,什么是检查点
   检查点是数据库事件,它是指当前数据库dbwr进程将脏块从db buffer写到数据文件的进度,减少实例崩溃后,实例恢复的时间,是实例恢复的起点。
2,检查点的分类
  全局检查点:通常是dba手动生成 alter system checkpoint   或者正常关闭数据库的时候会自动产生。

  增量检查点:这个比较复杂可以从dbwr写的条件说起
dbwr写的条件
   1,检查点发生的时候
   2,脏块达到三分之一
   3,没有空闲的块
   4,timeout occurs
   5,rac ping request is made
   6,表空间的脱机,只读,热备份
   7,表的drop和truncate

一,  从上面可以看出,dbwr写的时候并不只是检查点发生的时候,也就是说即使检查点没有发生dbwr也可能在写脏块。 那么数据库如果只是记录了全局检查点,实例崩溃后,很多dbwr已经写到数据文件中的脏块也会被应用日志。增加了实例恢复的时间。                   

二,通过增量检查点 :oracle在db buffer中有个检查点队列也叫脏队列,ckpt进程会每三秒去读去dbwr写的进展,并把这个点记录到控制文件中,但是不会记录到数据文件头,也就是说它记录的是dbwr实时的写入情况。这样当实例崩溃后,需要进行实例恢复,数据库就可以从控制文件中读取这个增量检查点作为实例恢复的起点,减少实例恢复的时间。
 
两个概念 :
1,CKPT每3秒一次将检查点位置记录进控制文件,当然同时被记录进控制文件的 还有'心跳'等其他信息.CKPT每3秒一次的工作和CKPT定期触发DBWR,这两项操作合一起被称为--增量检查
2,增量检查点并不会去更新数据文件头,以及控制文件中数据库SCN以及数据文件条目的SCN信息,而只是每3秒由CKPT进程去更新控制文件中的low cache rba信息,也就是检查点的位置。

   被修改过的块,在oracle中都被统称为脏块.所有的脏块被一个链表串起来,称做检查点队列.在buffer  

cache中,每一个块都有一个buffer header 简称BH,在BH中有一个ckptq项,此项目中记录了指向检查点队

列上一个块和下一个块的指针.如果某一个块不在检查点队列中,他的ckptq项为空.通过ckptq项oracle将

所有的脏块串成了一个双向链表.这个双向链表就是检查点队列了.

1,只有脏块才会在检查点队列中,非脏块的ckptq为空.

2,当块首次被更改时,块会立即被加进检查点队列.如果检查点队列中的脏块再次被修改,并不会改变其在

检查点队列中的位置.

3,检查点队列中脏块的排列顺序:根据第2点,所有脏块按照首次被更改的时间的顺序排列.更准确点说:按

照块的lrba排列.

**什么是rba?lrba?hrba?

  rba就是重做块地址,比如说,用户发出了一条update命令,更新了块A,块A现在变成了脏块,oracle会为他

生成一条重做记录.这条重做记录在重做日志文件中的位置就是rba(redo block address).过了一会儿,假

如:块A依然还是脏块,此时.用户又发出一条更新块A的命令,这又会生成一条重做记录.第一条更新命令对

应的重做记录的rba被称为块A的lrba(low rba),第二条更新命令对应的rba,被称为hrba(high rba).

其实,按照lrba来排列,就是按照块首次被修改的顺序来排列.

  下面说说DBWR写脏块的方式,有了检查点队列之后,脏块按照首次变脏的时间顺序排列,DBWR每到一定的

时机,就会被触发,沿着检查点队列的顺序刷新脏块,具体在oracle中有几个参数用来确定检查点队列的长

度.另有一个CKPT进程,会监控着检查点队列的长度,当检查点队列的长度达到一定限制时,CKPT会通知DBWR

写脏块.CKPT会根据参数的设置和I/O的速度以及繁忙程度,计算出来一个Target rba(目标rba),DBWR会沿

着检查点队列,将所有Target rba之前的脏块刷新到磁盘.当CKPT通知完DBWR Target rba后,CKPT的任务就

结束了.他并不会等待DBWR写完所有的Target rba之前的脏块.通知DBWR写脏块,这是CKPT的任务之一,CKPT

另有一个任务,就是每3秒,检测一次DBWR的写进度.检查点队列最前面的块被称为检查点位置.DBWR是沿着

检查点队列写脏块的,CKPT每3秒钟查看一下DBWR沿检查点队列写到了哪里,并且将这个位置设置为检查点

位置.也就是说检查点位置之前的块,都是已被DBWR刷新到磁盘上的块.这个3秒一次检查DBWR进度的工作,

也是CKPT的一个重要的任务.CKPT每3秒一次将检查点位置记录进控制文件,当然同时被记录进控制文件的

还有'心跳'等其他信息.CKPT每3秒一次的工作和CKPT定期触发DBWR,这两项操作合一起被称为--增量检查

点.

画思维导图太费事,直接手打。
   

磁盘块在buffer中对应的buffers被修改后称为脏块,修改为脏块时不同步写入数据文件,而同步写到log buffer。

当buffer里有太多脏块时或其他原因,会有多种方式触发DBWR把脏块写到数据文件,腾出buffer空间,每种方式可能按不同的优先顺序写脏块,也就是按不同的链来写,其中一种是按lrba的顺序写。

先静态的解释一些名词,再讨论增量检查点的过程。

RBA(redo buffer address)脏块指向的redo buffer内存物理地址,lrba是指buffers第一次被修改时的rba,也就是这个buffers成为脏块时的rba,以后再脏多少次,他成为脏块的时候间不变,即lrba不会变。脏块最近一次被脏的rba称为hrba,两个rba之间的rba没有特定名称,他们这个脏块被事务修改的全部重做日志记录。所有脏块都有lrba和hrba,如果只脏过一次,两个rba相同。

CKPTQ。将所有脏块的lrba链起来就是CKPTQ检查点队列。(不知道buffer真的有这个队列的独立物理结构,还是所有脏块lrba信息在逻辑上向下指,在概念上形成CKPTQ。)

CKPT有多种词性,指一个动作,如进行CKPT,这次检查点;指一个进程,如CKPT进程;指逻辑上的一个时间点,检查点位置。

LRBA。每个脏块里有个LRBA信息,控制文件中也有个LRBA,准确的讲叫 low cache rba,他是ckpt进程从某一个脏块里读取过来的。

On disk RBA。先记着他指向log file里最新的(最后的)一条重做日志条目,他也是ckpt进程从某一个脏块里读取过来的。

增量检查点工作过程,和在实例恢复中的作用

只是串行化的图出重做日志条目,不必区分这些条目是否是current logfile。

一个脏块对应一个事务,但不一定对应一个重做日志条目,因为脏块脏一次产生一条重做日志条目。

 Oracle检查点是什么

1.CKPT进程发现CKPTQ太长(多长算长,oracle里有些参数可以控制),打算通知DBWR让他刷出一些脏块,缩短CKPTQ,从low cache rba到target rba是CKPT根据CKPTQ长度和系统I/0繁忙程序计算出来的值。通知后立即返回,不等DBWR写完,即异步通知。

2.由于写前协议,DBWR写脏块前都通知LGWR先把脏块写到重做日志文件。

3.DBWR按照CKPTQ从上到下的顺序将脏块写入数据文件(图中从上到下是时间上越来越新)。

如果是完全检查点,DBWR按照dirty list写此时的checkpoint SCN之前的脏数据

4.在DBWR写的过程中,CKPT会每隔3秒来检查一次DBWR的写进度,并把进度信息(就是哪一个脏块)写到控制文件中,叫做low cache rba,这每隔3秒一次的动作叫心跳,他与low cache rba配套,比如从控制文件中dump出这样的信息,表示第793694908次检查DBWR时,他写到0x5.15119.0这个位置。

low cache rba:(0x5.15119.0) on disk rba:(0x5.15314.0)

on disk scn: 0x0000.0008ea68 10/20/2012 17:15:34

resetlogs scn: 0x0000.0006ce7b 03/30/2012 11:15:03

heartbeat: 793694908 mount id: 1363550103

可以这样说,DBWR缩短了CKPTQ的长度,low cache rba是CKPT记录的DBWR的写进度。

每隔3秒具体写的什么

为了减少频繁增量检查点的性能影响,CKPT进行的是轻量级更新,他并不会改写控制文件中数据文件的检查点信息,以及数据文件头信息,而只是在控制文件中记录这个检查点的SCN(Controlfile Checkpointed at scn),以及DBWR此时写到的脏块的RBA信息。

5. 估计on disk rba是LGWR写日志文件时值到控制文件中的。

6.当他写完时(target rba的位置),target rba 和low cache rba相同,并把这一次检查点的lrba记录到控制文件中

7.控制文件中的 low cache rba指向的重做日志位置一定在on disk rba的下面(图中是从下往上写,越上面越新)。如果在他上面,就会出现脏块写入了数据文件而没写入重做日志文件,

这两个rba之间的所有重做日志条目就是恢复时需要恢复的条目,称为前滚。

8。提交过的事务,他的log buffer一定在log file里,但log file里也有没提交过的条目。这一脏块没有提交,他被写入了数据文件和重做日志文件,恢复时他也被恢复到buffer里,通过undo回滚可以去除这没提交的数据,这不在讨论范围内。


Oracle 检查点的类型

 CKPT负责把检查点写入控制文件和数据文件头。检查点有以下类型:Thread checkpoints其为 数据库 检查点,在以下情况下会出现这种检查点: 一致性关闭数据库;ALTER SYSTERM CHECKPOINT语句;online redo log file的切换;ALTER DATABASE BEGIN BACKUP语句;Tablespace and data file checkpoints 把某表空间内所有数据文件的在SGA中的脏数据块刷新到磁盘中,在一下情况下会出现这种检查点:使得某表空间read-only或offline normal;收缩一个数据文件;ALTER DATABASE BEGIN BACKUP语句;Incremental checkpoints(增量备份) DBWn每三秒钟就会刷新一次SGA中的脏数据块到物理文件中,而CKPT每三秒中就会发出一个检查点,把检查点的信息写入控制文件,但是不会更新数据文件头的信息。其他的检查点其他的检查点包括,实例恢复的检查点,删除或truncate对象时触发的检查点。  




 OCP知识点讲解 之 检查点队列与增量检查点 

  检查点的主要目的是以对数据库的日常操作影响最小的方式刷新脏块。脏块不断的产生,如何将脏块刷新到磁盘中去呢?在8i之前,Oracle定期的锁住所有的修改操作,刷新Buffer cache中的所有脏块,这种刷新脏块的方式被称为完全检查点,这极大的影响了效率,从9i之后只有当关闭数据库时才会发生完全检查点。

     从8i开始,Oracle增加了增量检查点的概念,增量检查点的主要宗旨就是定期的刷新一部分脏块。将脏块一次刷新完是不合理的,因为脏块不断产生,没有穷尽。像完全检查点那样停止用户所有的修改操作,将脏块刷新完再继续,这绝对会极大的影响性能。所有增量检查点的一次刷新部分块是脏块问题的最好解决办法。那么,每次刷新时,都刷新那些块呢?根据统计研究,根据块变脏的顺序,每次刷新那些最早脏的块,这种方式最为合理。为了实现这一点,Oracle在Buffer cache中又建立了一个链表,就是检查点队列。每个块在它变脏时,会被链接到检查点队列的末尾。就好像排队一样,9:00来的人站在第一位,9:05来的人排第二位,以后每来一个人都站在队伍的末尾,这个队伍就是按来到的时间顺序排列的一个队列。检查点队列就是这样,块在变脏时会被链到末尾。因此检查点队列是按块变脏的时间顺序,将块排成了一个队列。

Oracle检查点是什么

     如上图,检查点队列中的每一节点,都指向一个脏块。检查点队列每个节点中的信息其实非常少,就是记录对应块在Buffer cache中的地址,脏块对应的重做记录在日志文件中的位置,另外还有前一个节点、后一个节点的地址。检查点队列还有LRU、脏LRU,这些都是双向链表。双向链表就是在节点中记录前、后两个节点的地址。

     检查点队列头部的块是最早变脏的,因此,Oracle会定期唤醒DBWn从检查点队列头开始,沿着检查点队列的顺序,刷新脏块。在刷新脏块的同时,仍可以不断的有新的脏块被链接到检查点队列的尾部。这个定期唤醒DBWn刷新脏块的操作,Oracle就称为增量检查点。

Oracle检查点是什么

     如上图,1、2、3号节点所指向的脏块已经被刷新为干净块。同时,又有两个块变脏,它们被链接到了检查点队列的末尾,它们是9号、10号节点。

     检查点队列的头,又被称为检查点位置,Checkpoint postion,这些名称我们不必从字面上去理解。总之,检查点位置就是检查点队列头。检查点队列头节点(也就是检查点位置)的信息,Oracle会频繁的将它记录到控制文件中,而且会很频繁的记录。一般是每隔三秒,有一个专门的进程CKPT,会将检查点位置记录进控制文件。

Oracle检查点是什么

     如上图,当前的检查点位置是检查点队列的1号节点。又一个三秒到了,CKPT进程启动,将新的检查点位置记入控制文件:

Oracle检查点是什么

     新的检查点位置是4号节点,它对应当前变脏时间最早的脏块。1、2、3号节点已经从检查点队列中摘除了。因为它们对应的脏块已经不脏了。一般来说,控制文件中的检查点位置之后的块都是脏块。但是有时也例外,因检查点位置每三秒才会更新一次,就像上图,1、2、3号节点对应的脏块已经被刷新过了,但是由于三秒间隔没到,检查点位置还是指向1号节点。只有当三秒到后,检查点位置才会被更新到4号节点上。

     关于检查点队列、检查点位置我们先说到这里,在全面的介绍什么是增量检查点之前,我们先说一下检查点队列的一个重要作用。

     让我们先来总结一下用户修改块时,Oracle内部都发生了什么:

     1.如果块不在Buffer cache,将块读入Buffer cache

     2.先生成重做记录,并记入日志缓存,在用户提交时写到日志文件中

     3.在Buffer cache中修改块

     4.在Buffer cache中设置块的脏标志位,标志块变成脏块,同时在检查点队列末尾增加一个新节点,记录这个新脏块的信息,信息包括:脏块在Buffer cache中的位置,在步骤2时生成的与此脏块对应的重做记录位置。

     5.用户提交后,将相应的重做记录从重做缓存写入日志文件。

     我现在将日志补充到上面的图中:

Oracle检查点是什么

     就像上图,检查点队列的每个节点,都保存有脏块的地址和脏块对应的重做记录的编号。脏块在Buffer cache中的位置是随机的,用户不一定修改那个块。但重做记录是顺序生成的,就和检查点队列的排列顺序一样。因为,它们都是当块被修改而变脏时产生的。块A先被修改,块A的重做记录就排在前面,块B后被修改,块B对应的重做记录会被排在块A对应的重做记录的后面。和它们在检查点中的顺序是一样。每当数据库因异外而当机,比如异常死机、断电等等,Buffer cache中有许多脏块没来的及写到磁盘上。以图为例,比如说现在断电了,现在磁盘上还有7个脏块,它们里面有用户修改过的数据,Oracle已经将反馈信息“你的修改完成”发送给用户,用户也以为他们的修改完成了,将为一直保存到数据库中。但是,断然的断电,令这几个脏块中的数据丢失了,它们没来得及写到磁盘上。

     Oracle如何解决这个问题呢?很简单,当数据库重新启动时,Oracle只需从控制文件中读出检查点位置,检查点位置中记录有重做记录编号,根据此编号,Oracle可以很快的定位到日志文件中的重做记录n,它读出重做记录n中的重做数据,将用户的修改操作重现到数据库。接着,Oracle读取重做记录n+1中的重做数据,重现用户修改,这个过程将沿着日志流的顺序,一直进行下去,直挡最后一条重做记录,在上图的例子中,最后一条重做记录是第n+6条。这个过程完成后,用户所有的修改又都被重现了,一点都不会丢失。只要你的日志文件是完整,日志流是完整的,就一点信息都不会丢失。

     有人可能会有一个问题,重做记录在生成后,也是先被送进重做缓存,再由重做缓存写往日志文件。这样的机制下,一定会有某些重做记录在没来的及写到日志文件中时,数据库突然当机,而造成这些重做记录丢失。这样,这些重做记录所对应的脏块,将得不到恢复。用户还是会丢失一些数据。

     这种情况的确会发生,但丢失的都是没用的信息。为什么这么说的。Oracle会在用户每次发出提交命令时,将事务所修改脏块对应的重做记录写进日志文件,只有当这个操作完成时,用户才会收到“提交完成”,这样的信息,对于一个完整的事务,当用户看到提交完成后,也就意味着所对应的重做记录一定被写到了日志文件中,即使发生异常死机,它也是绝对可以恢复。而当用户没有提交,或没来得及提交,数据库就崩溃了,那么事务就是不完整的,这个事务必须被回滚,它根本用不着恢复。对于这样不完整的事务,它对应的重做记录有可能丢失,但这无所谓了,因为不完整的事务根本不需要恢复。也就是说,只有用户的事务提交了,用户的修改一定不会丢失。不过这还有一个前提,就是日志文件千万不能损坏,DBA所要做的就是要保证日志文件不能损坏。DBA可以使用RAID1这样的磁盘镜像技术,或者多元备份日志文件,等等,这个我们在前面章节中已经讲过了的。

     我们上面所讲到的这种恢复,是自动进行的,并且不需要DBA参与,它被称之为实例恢复。

     检查点队列与增量检查点的作用我们已经说的差不多了,它们的主要目的就是让DBWn沿检查点队列的顺序刷新脏块。还有,就是实例恢复。

     下面我们来讨论一下增量检查点的设置。

     这里所说的检查点设置,主要指增量检查点频繁的设置。注意增量检查点只是一个名词,不必按字面的意义去理解它。增量检查点发生时,Oracle会唤醒DBWn沿着检查点队列写脏块,这就是增量检查点。那么到底多长时间一次发生一次增量检查点呢?这个增量检查点的频率是非常重要的,它基本上控制着DBWn多长时间去刷新一次脏块。DBWn活动的太频繁,会影响数据库的整体性能,如果DBWn活动太不频繁,又会使脏块挤压太多,这同样也会影响性能。而且,如果出现异常崩溃,需要实例恢复,脏块越多,实例恢复越慢。。在9i之前DBA主要靠间隔时间等方式来设置增量检查点的频率,比如可以让Oracle每10分钟发生一次增量检查点。如果这个数字设置不合适,对数据库性能的影响是很大的。而且有可能造成实例恢复时间过长。在9i之后,特别是到了10g中,检查点已经相当的智能化了,很少会成为I/O问题的原凶。9i中设置fast_start_mttr_target参数为你所期望的实例恢复时间,系统将自动控制增量检查点的频率。比如,你希望实例恢复可以在5分钟内完成,你可以将此参数设置为300,也就是300称。

     如果此参数设置的值超出了硬件实际的限制,比如你将它设置为60,你期望无论在任何情况下,数据库都可以在1分钟内完成实例恢复,但根据数据库的脏块生成速度、存储设备的写性能,1分钟内根本无法完成实例恢复。这时候Oracle会自动设置合适的fast_start_mttr_target参数值,我们可以在参数文件中看到修正后的参数值,也可以在V$instance_recovery视图中的Target_mttr列中看到实际的值。例如:

     (举个例子)

     我们不能将这个值设置的太小,因为实例恢复必竞只是偶然现象。如果为了让实例恢复尽快完成,而设置fast_start_mttr_target为很小的值,那么DBWn将活动的很频繁,这会造成性能问题的。 为了避免用户设置不合理的增量检查点频率,在10G中,如果将fast_start_mttr_target设置为0,Oracle将根据产生脏块的速度、存贮硬件的性能自动调节检查点的频率,尽量使检查点频率不成为I/O问题的原凶。

     检查点的主要任务就是催促DBWn刷新脏块,如果DBWn刷新脏块时的等待事件太多,就说明脏块太多、存储设备的写速度太慢,或者就是增量检查点的频率太高了,或太低了。DBWn写脏块的等待事件是Db file parallel write。如果你的增量检查点频率很低,你发现了此事件,在排除了存储设备写性能的问题后,你应该将增量检查点频率设置的高一些。反之,如果你的增量检查点频率本身很高,出现了Db file parallel write事件,这说明检查点频率太高了。

     除它之外,还有一个和DBWn、增量检查眯有关的等待事件,它是Write complete waits事件,当前台进程要修改DBWn正要成批写的块中的若干个块时,就会有此等待事件,这个事件是前台进程再等待DBWn写完成。这个等待事太多,说明了存储设备写性能有问题,或者增量检查点太频率了。

     我们可以V$instance_recovery中看到有关检查点的很多信息:

     Estimated_mttr列如果太大,说明检查点不够频繁,同时也说明脏块产生的太多。同时在V$sysstat资料视图中,还有两个资料background checkpoints started、background checkpoints completed,前面的一个是后台进程检查点开始次数,后一个是后台进程检查点完成次数。后台进程检查点的意义,其实就是增量检查点。只有增量检查点是由后台进程触发的。如果你用Alter system checkpoing命令让系统完成完全检查点,这叫做前台检查点与增量检查点无关,是不会被记入这两个资料了。如果这两个值经常相差一些,比如检查点的开始次数比完成次数大的不至1,这说明有太多次检查点开始,但没有及时完成。这说明检查点太频繁或检查点完成的太慢。

     (举例,大量的产生脏块、日志文件比较小5MB,日志文件频率的切换而触发检查点,同时查看一下等待事件)

     检查点的问题大多数情况下其实都是DBWn写I/O的问题, DBWn写脏块的等待事件是Db file parallel write,还有Write complete waits等待事件,是当前台进程要修改DBWn正要成批写的块中的若干个块时,就会有此等待事件,这个事件是前台进程再等待DBWn写完成。这个等待事太多,也说明了DBWn有问题。

     注意,对于数据文件的I/O问题,除了等待事件外,我们还可以用上几节讲过了V$filestat视图帮助确定问题。)



在 Oracle 的官方文档中介绍 Oracle 的 Checkpoint 有:
(1)Thread Checkpoint;
(2)Tablespace and datafile checkpoint;
(3)Incremental checkpoint。
对 于后两种 checkpoint,大家都有一个比较清晰的认识。 但是对于 Thread checkpoint 和 database checkpoint 之间的关系以及他们在单节点和RAC数据库之间的不同可能存在一些误区。 下面将通过一些例子来讲解一下 Thread checkpoint,以及在单节点和 RAC 中 Thread checkpoint 的不同。

一 单节点数据库(或者是RAC database中,只保留一个节点):

*为了便于观察checkpoint的,设置log_checkpoints_to_alert,让checkpoint的信息打印到alert log中:

SQL> show parameter log_checkpoints_to_alert

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
log_checkpoints_to_alert             boolean     TRUE


1) 对数据库做"alter system switch logfile":sys@R11203> select file#, CHECKPOINT_CHANGE# from v$datafile;

    FILE#         CHECKPOINT_CHANGE#
---------- --------------------------
        1             12717430780764
        2             12717430780764
        3             12717430780764
        4             12717430780764   <<<<<<<<<< 未switch之前

sys@R11203> alter system switch logfile;

System altered.

sys@R11203> select file#, CHECKPOINT_CHANGE# from v$datafile;

    FILE#         CHECKPOINT_CHANGE#
---------- --------------------------
        1             12717430780764
        2             12717430780764
        3             12717430780764
        4             12717430780764  <<<<<<<<<<<<< switch之后立即查看,v$datafile对应的checkpoint_change#并没有变化。


2)检查一下数据库的alert log:

Tue Jan 19 16:01:02 2016  
Beginning log switch checkpoint up to RBA [0x5a.2.10], SCN: 12717430780990    <<<<<<<<<<<<<<<  开始做log switch的checkpoint 到SCN12717430780990,但是并没有看到checkpoint结束。

3) 过了大约几分钟后,再次检查 alert log 以及 V$datafile

Tue Jan 19 16:05:58 2016   <<<<<<<<<<<<<<<<<< 16:05 已经结束checkpoint
Completed checkpoint up to RBA [0x5a.2.10], SCN: 12717430780990   sys@R11203> select file#, CHECKPOINT_CHANGE# from v$datafile;

    FILE#         CHECKPOINT_CHANGE#
---------- --------------------------
        1             12717430780990
        2             12717430780990
        3             12717430780990
        4             12717430780990 <<<<<<<< v$datafile 中的checkpoint check# 已经更改到新的SCN:12717430780990

二 RAC数据库:

1) 对数据库做"alter system switch logfile":

SQL> select INST_ID,INSTANCE_NAME,STATUS from gv$instance;

  INST_ID INSTANCE_NAME    STATUS
---------- ---------------- ------------
        1 ora11g1          OPEN
        2 ora11g2          OPEN

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile_header;

    FILE# CHECKPOINT_CHANGE#
---------- ------------------
        1           11583337
        2           11583337
        3           11583337
        4           11583337
        5           11583337
        6           11583337

6 rows selected.

SQL> alter system switch logfile;

System altered.

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile_header;

    FILE# CHECKPOINT_CHANGE#
---------- ------------------
        1           11583337
        2           11583337
        3           11583337
        4           11583337
        5           11583337
        6           11583337  <<<<<<<<<<  checkpoint_change# 并没有改变。

6 rows selected.

2) 观察此节点的alert log:

Wed Jan 20 07:10:16 2016
Beginning log switch checkpoint up to RBA [0x22f.2.10], SCN: 11583841 <<<<<<<<< 开始 log switch的checkpoint。
Thread 1 advanced to log sequence 559 (LGWR switch)
 Current log# 1 seq# 559 mem# 0: +DATA1/ora11g/onlinelog/group_1.257.827893181
Wed Jan 20 07:10:16 2016
Completed checkpoint up to RBA [0x22f.2.10], SCN: 11583841   <<<<<<<<<<  log switch的checkpoint已经完成。

3) 重新观察一下v$datafile:

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile_header;

    FILE# CHECKPOINT_CHANGE#
---------- ------------------
        1           11583337
        2           11583337
        3           11583337
        4           11583337
        5           11583337
        6           11583337  <<<<<<<<<<<< checkpoint_change# 还是没有改变。

6 rows selected.

4) 执行"alter system checkpoint"

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile_header;

    FILE# CHECKPOINT_CHANGE#
---------- ------------------
        1           11583337
        2           11583337
        3           11583337
        4           11583337
        5           11583337
        6           11583337

6 rows selected.

SQL> alter system checkpoint;

System altered.

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile_header;

    FILE# CHECKPOINT_CHANGE#
---------- ------------------
        1           11583983
        2           11583983
        3           11583983
        4           11583983
        5           11583983
        6           11583983 <<<<<<<<<< 变成: 11583983

6 rows selected.

5) 观察此节点的alert log:

Wed Jan 20 07:14:21 2016
Beginning global checkpoint up to RBA [0x231.3.10], SCN: 11583983   <<<<<<<<<<  Global checkpoint到 11583983。
Completed checkpoint up to RBA [0x231.3.10], SCN: 11583983

6) 那么如果在RAC中做log switch,每次thread checkpoint的记录在哪里可以查询到呢?

SQL> select INSTANCE_NUMBER,INSTANCE_NAME,THREAD#,STATUS from gv$instance;

INSTANCE_NUMBER INSTANCE_NAME       THREAD# STATUS
--------------- ---------------- ---------- ------------
             1 ora11g1                   1 OPEN     <<<<<<<<<<<<<<<<<<<<   节点1的thead号为: 1
             2 ora11g2                   2 OPEN

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile;

    FILE# CHECKPOINT_CHANGE#
---------- ------------------
        1           11616270
        2           11616270
        3           11616270
        4           11616270
        5           11616270
        6           11616270

6 rows selected.

SQL> alter system switch logfile;

System altered.

7)在alert log中:

Thu Jan 21 02:22:52 2016
Beginning log switch checkpoint up to RBA [0x23a.2.10], SCN: 11621392
Thread 1 advanced to log sequence 570 (LGWR switch)
 Current log# 2 seq# 570 mem# 0: +DATA1/ora11g/onlinelog/group_2.258.827893183
Thu Jan 21 02:22:53 2016
Archived Log entry 358 added for thread 1 sequence 569 ID 0xfbc6d574 dest 1:
Thu Jan 21 02:22:55 2016
Completed checkpoint up to RBA [0x23a.2.10], SCN: 11621392   <<<<<<<<<<<<<  Thread checkpoint 到 11621392已经完成。

SQL> select FILE#,CHECKPOINT_CHANGE# from v$datafile;

    FILE# CHECKPOINT_CHANGE#
---------- ------------------
        1           11616270
        2           11616270
        3           11616270
        4           11616270
        5           11616270
        6           11616270 <<<<<<<<<< v$datafile中的checkpoint change#照例没有改变。

6 rows selected.

8) 查看v$thread:

SQL> select THREAD#,CHECKPOINT_CHANGE# from v$thread;

  THREAD# CHECKPOINT_CHANGE#
---------- ------------------
        1           11621392   <<<<<<<<<<<<<<<<  Thread 1 checkpoint 到 11621392 (和alert log中的描述一致)
        2           11619485

总结一下:

1. 对于单节点数据库,由于只有一个thread,所以由log switch发起的对当前thread的checkpoint,实质上就是整个数据库的checkpoint,所以log switch会导致v$datafile (v$datafile_header)中的checkpoint_change#改变。 但是必须要等checkpoint完成以后才会变成最新的值。

2. 对于RAC(2个节点以上)的数据库,由于至少存在2个或者以上的thread,所以对单一thread的 log switch并不会触发v$datafile (v$datafile_header)的checkpoint_change#的修改。原因是:只对其中一个thread(log)cover块的checkpoint,只会触发在此节点上脏块的写回. 但是由于多于2个节点,所以其他的节点可能存在在此checkpoint SCN之前的脏块,所以对于数据文件(或者是数据库)来说,这并不是一个完整的database级的checkpoint。 在RAC中,只有所有节点间的全局检查点(global checkpoint)会导致v$datafile中的checkpoint_change#的变化,比如"alter system checkpoint"。

 3. 在RAC中,对于thread的checkpoint_change#,可以通过v$thread来查询。



什么是checkpoint

在数据库系统中,写日志和写数据文件是数据库中IO消耗最大的两种操作,在这两种操作中写数据文件属于分散写,写日志文件是顺序写,因此为了保证数据库的性能,通常数据库都是保证在提交(commit)完成之前要先保证日志都被写入到日志文件中,而脏数据块着保存在数据缓存(buffer cache)中再不定期的分批写入到数据文件中。也就是说日志写入和提交操作是同步的,而数据写入和提交操作是不同步的。这样就存在一个问题,当一个数据库崩溃的时候并不能保证缓存里面的脏数据全部写入到数据文件中,这样在实例启动的时候就要使用日志文件进行恢复操作,将数据库恢复到崩溃之前的状态,保证数据的一致性。检查点是这个过程中的重要机制,通过它来确定,恢复时哪些重做日志应该被扫描并应用于恢复。

一般所说的checkpoint是一个数据库事件(event),checkpoint事件由checkpoint进程(LGWR/CKPT进程)发出,当checkpoint事件发生时DBWn会将脏块写入到磁盘中,同时数据文件和控制文件的文件头也会被更新以记录checkpoint信息。


checkpoint的作用

checkpoint主要2个作用:

  1. 保证数据库的一致性,这是指将脏数据写入到硬盘,保证内存和硬盘上的数据是一样的;

  2. 缩短实例恢复的时间,实例恢复要把实例异常关闭前没有写出到硬盘的脏数据通过日志进行恢复。如果脏块过多,实例恢复的时间也会很长,检查点的发生可以减少脏块的数量,从而提高实例恢复的时间。

通俗的说checkpoint就像word的自动保存一样。


检查点分类

  • 完全检查点(Normal checkpoint)

  • 增量检查点(Incremental checkpoint)


checkpoint相关概念术语

在说明checkpoint工作原理之前我们先了解一些相关的术语。


RBA(Redo Byte Address), Low RBA(LRBA), High RBA(HRBA)

RBA就是重做日志块(redo log block)的地址,相当与数据文件中的ROWID,通过这个地址来定位重做日志块。RBA由三个部分组成:

  1. 日志文件序列号(4字节)——根据这个找到对应的日志文件地址。

  2. 日志文件块编号(4字节)——根据这个找到对应日志条目所在的日志文件块。

  3. 重做日志记录在日志块中的起始偏移字节数(2字节)——找到对应的日志条目。

通常使用RBA的形式有:

LRBA 数据缓存(buffer cache)中一个脏块第一次被更新的时候产生的重做日志记录在重做日志文件中所对应的位置就称为LRBA。 HRBA 数据缓存(buffer cache)中一个脏块最近一次被更新的时候产生的重做日志记录在重做日志文件中所对应的位置就称为HRBA。 checkpoint RBA 当一个checkpoint事件发生的时候,checkpoint进程会记录下当时所写的重做日志块的地址即RBA,此时记录的RBA被称为checkpoint RBA。从上一个checkpoint RBA到当前的checkpoint RBA之间的日志所保护的buffer cache中的脏块接下来将会被写入到数据文件当中去。


Buffer checkpoint Queues (BCQ)

Oracle将所有在数据缓存中被修改的脏块按照LRBA顺序的组成一个checkpoint队列,这个队列主要记录了buffer cache第一次发生变化的时间顺序,然后有DBWn进程根据checkpoint队列顺序将脏块写入到数据文件中,这样保证了先发生变更的buffer能先被写入到数据文件中。BCQ的引入是为了支持增量checkpoint的。


Active checkpoint Queue (ACQ)

ACQ中包含了所有活动的checkpoint请求。每次有新checkpoint请求是都会在ACQ中增加一条记录,ACQ记录中包含了相应的checkpoint RBA。checkpoint完成以后相应的记录将被移出队列。


完全检查点 (normal checkpoint)


完全检查点工作过程

一个checkpoint操作可以分成三个不同的阶段:

  • 第一阶段,checkpoint进程开始一个checkpoint事件,并记录下checkpoint RBA,这个通常是当前的RBA。

  • 第二阶段,checkpoint进程通知DBWn进程将所有checkpoint RBA之前的buffer cache里面的脏块写入磁盘。

  • 确定脏块都被写入磁盘以后进入到第三阶段,checkpoint进程将checkpoint信息(SCN)写入/更新数据文件和控制文件中。

更新SCN的操作由CKPT进程完成,在Oracle 8.0之后CKPT进程默认是被启用的,如果CKPT进程没有启用的话那相应的操作将由LGWR进程完成。


什么时候发生normal checkpoint

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

  • 日志切换,通过ALTER SYSTEM SWITCH LOGFILE。

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

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

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

  • SHUTDOWN命令发出时。

特别注意:

  1. 日志切换会导致checkpoint事件发生,但是checkpoint发生却不会导致日志切换。

  2. 日志切换触发的是normal checkpoint,而不是大家所说的增量checkpoint,只不过log switch checkpoint的优先级非常低,当一个log switch checkpoint发生的时候它并不会立即的通知DBWn进程去写数据文件,但是当有其它原因导致checkpoint或者是写入数据文件的RBA超过log switch checkpoint的checkpoint RBA的时候,这次的log switch checkpoint将会被标记成完成状态,同时更新控制文件和数据文件头。我们随后可以做个实验验证这个说法。


checkpoint和SCN有什么关系?

在Oracle中SCN相当于它的时钟,在现实生活中我们用时钟来记录和衡量我们的时间,而Oracle就是用SCN来记录和衡量整个Oracle系统的更改。

Oracle中checkpoint是在一个特定的“时间点”发生的,衡量这个“时间点”用的就是SCN,因此当一个checkpoint发生时SCN会被写入文件头中以记录这个checkpoint。


增量checkpoint


增量checkpoint工作过程

因为每次完全的checkpoint都需要把buffer cache所有的脏块都写入到数据文件中,这样就是产生一个很大的IO消耗,频繁的完全checkpoint操作很对系统的性能有很大的影响,为此Oracle引入的增量checkpoint的概念,buffer cache中的脏块将会按照BCQ队列的顺序持续不断的被写入到磁盘当中,同时CKPT进程将会每3秒中检查DBWn的写入进度并将相应的RBA信息记录到控制文件中。(关于CKPT进程每3秒进行修改控制文件的测试: http://blog.csdn.net/changyanmanman/article/details/7362528 )

有了增量checkpoint之后在进行实例恢复的时候就不需要再从崩溃前的那个完全checkpoint开始应用重做日志了,只需要从控制文件中记录的RBA开始进行恢复操作,这样能节省恢复的时间。


发生增量checkpoint的先决条件

  • 恢复需求设定 (FAST_START_IO_TARGET/FAST_START_MTTR_TARGET)

  • LOG_checkpoint_INTERVAL参数值

  • LOG_checkpoint_TIMEOUT参数值

  • 最小的日志文件大小

  • buffer cache中的脏块的数量


增量checkpoint的特点

  • 增量checkpoint是一个持续活动的checkpoint。

  • 没有checkpoint RBA,因为这个checkpoint是一直都在进行的,所以不存在normal checkpoint里面涉及的checkpoint RBA的概念。

  • checkpoint advanced in memory only

  • 增量checkpoint所完成的RBA信息被记录在控制文件中。

  • 增量checkpoint可以减少实例恢复时间。


增量checkpoint相关参数设置

log_checkpoint_interval 设定两次checkpoint之间重做日志块(重做日志块和系统数据块是一样的)数,当重做日志块数量达到设定值的时候将触发checkpoint。 log_checkpoint_timeout 设定两次checkpoint之间的间隔时间,当超时值达到时增量checkpoint将被触发。Oracle建议不用这个参数来控制,因为事务(transaction)大小不是按时间等量分布的。将此值设置成0时将禁用此项设置。 fast_start_io_target 因为log_checkpoint_interval主要看的时候重做日志块的数量,并不能反应buffer cache中脏数据块的修改,因此Oracle又引入了这个参数来实现当脏数据块达到一定数量的时候触发checkpoint,不过此参数实际上控制的是恢复时所需IO的数量。 fast_start_mttr_target

  • 此参数是在9i中引入用来代替前面的三个参数的,它定义了数据块崩溃后所需要的实例恢复的时间,Oracle在实际上内在的解释成两个参数:fast_start_io_target和log_checkpoint_interval.如果这两个参数没有显式的指定,计算值将生效.。

  • fast_start_mttr_target可以设定的最大值是3600,即一个小时。它的最小值没有设限,但是并不是说可以设置一个任意小的值,这个值会受最小dirty buffer(最小为1000)的限制,同时还会受初始化时间以及文件打开时间的限制。

  • 在设置此参数的时候要综合考虑系统的IO,容量以及CPU等信息,要在系统性能和故障恢复时间之间做好平衡。

  • 将此参数设置成0时将禁用 fast-start checkpointing,这样能见效系统负载但同时会增加系统的恢复时间。

  • 如果fast_start_io_target or log_checkpoint_interval被指定,他们会自动覆盖由fast_start_mttr_target参数计算出来的值。

在10g中,数据库能根据各种系统参数的设置值来自动调整检查点的执行频率,以获得最好的恢复时间以及系统的正常运行影响最小。通过自动checkpoint调整,Orach能在系统低IO操作的时候将脏块写入到数据文件中,因此即时DBA没有设置checkpoint相关的参数值或是设置了一个不合理的值的时候系统还是能获得一个很合理的系统恢复时间。

10g中的增量checkpoint更能体现它持续活动的特点,在10g中,增量checkpoint不是在某一个特定的条件下触发,而是由数据库根据系统参数设置自动触发。


与完全checkpoint的区别

  • 完全checkpoint会将checkpoint的信息写入到控制文件以及数据文件头中

  • 增量checkpoint只会将RBA信息写入到控制文件中。


查看系统的checkpoint动作

我们可以通过将LOG_checkpointS_TO_ALERT设置成TRUE来打开checkpoint的trace,这样就可以跟踪checkpoint的操作了。

ALTER SYSTEM SET LOG_checkpointS_TO_ALERT=TRUE;

这设置以后系统的checkpoint将会被记录alert_$SID.log文件中。

在V$DATAFILE_HEADER里面也保存了发生完全checkpoint的时候一些相关信息,包括checkpoint发生时间、对应SCN已经checkpoint的次数。

select file# NO, status, tablespace_name, name, dbms_flashback.get_system_change_number CUR_SCN,
  to_char(resetlogs_time, 'YYYY-MM-DD HH24:MI:SS') RST_DT,resetlogs_change# RST_SCN,
  to_char(checkpoint_time, 'YYYY-MM-DD HH24:MI:SS') CKPT_DT,checkpoint_change# CKPT_SCN, checkpoint_count CKPT_CNT
from v$datafile_header;
 
/**
NO  STATUS  TABLESPACE_NAME  CUR_SCN  RST_DT              RST_SCN  CKPT_DT             CKPT_SCN  CKPT_CNT
--- ------- ---------------- -------- ------------------- -------- ------------------- --------- ---------
1   ONLINE  SYSTEM           533541   2008-01-12 16:51:53 446075   2008-08-04 22:03:58 532354    65
2   ONLINE  UNDOTBS1         533541   2008-01-12 16:51:53 446075   2008-08-04 22:03:58 532354    28
3   ONLINE  SYSAUX           533541   2008-01-12 16:51:53 446075   2008-08-04 22:03:58 532354    65
4   ONLINE  USERS            533541   2008-01-12 16:51:53 446075   2008-08-04 22:03:58 532354    64
5   ONLINE  EXAMPLE          533541   2008-01-12 16:51:53 446075   2008-08-04 22:03:58 532354    24
*/


完全检查点

-- 我们先执行一个
ALTER SYSTEM checkpoint;
 
-- 下面是alert文件中的数据结果
Mon Aug  4 22:22:08 2008
Beginning global checkpoint up to RBA [x8.c9d4.10], SCN: 533714
Completed checkpoint up to RBA [x8.c9d4.10], SCN: 533714
-- 我们能看到完全checkpoint发生的SCN 533714
 
-- 下面我们再对照下V$DATAFILE_HEADER中的结果
NO  STATUS  TABLESPACE_NAME  CUR_SCN  RST_DT              RST_SCN CKPT_DT             CKPT_SCN  CKPT_CNT
--- ------- ---------------- -------- ------------------- -------- ------------------- --------- ---------
1   ONLINE  SYSTEM           533790   2008-01-12 16:51:53 446075   2008-08-04 22:22:08 533714    66
2   ONLINE  UNDOTBS1         533790   2008-01-12 16:51:53 446075   2008-08-04 22:22:08 533714    29
3   ONLINE  SYSAUX           533790   2008-01-12 16:51:53 446075   2008-08-04 22:22:08 533714    66
4   ONLINE  USERS            533790   2008-01-12 16:51:53 446075   2008-08-04 22:22:08 533714    65
5   ONLINE  EXAMPLE          533790   2008-01-12 16:51:53 446075   2008-08-04 22:22:08 533714    25
 
-- 看到了么,checkpoint时间和checkpoint的SCN已经被记录到数据文件头中了。


日志切换时的检查点

-- 我们先做一次日志切换
ALTER SYSTEM SWITCH LOGFILE;
 
-- 然后看看alert里面的记录
Mon Aug  4 22:31:39 2008
Beginning log switch checkpoint up to RBA [x9.2.10], SCN: 534450
Thread 1 advanced to log sequence 9
  Current log# 2 seq# 9 mem# 0: /u/app/oracle/oradata/orcl/redo02.log
Mon Aug  4 22:35:58 2008
Completed checkpoint up to RBA [x9.2.10], SCN: 534450
 
-- 我们能看到checkpoint是在过了一段时间(这里是4分钟)之后才完成的
 
-- 接着我们来看下V$DATAFILE_HEADER中的结果
NO  STATUS  TABLESPACE_NAME  CUR_SCN  RST_DT              RST_SCN CKPT_DT             CKPT_SCN  CKPT_CNT
--- ------- ---------------- -------- ------------------- -------- ------------------- --------- ---------
1   ONLINE  SYSTEM           534770   2008-01-12 16:51:53 446075   2008-08-04 22:31:44 534450    67
2   ONLINE  UNDOTBS1         534770   2008-01-12 16:51:53 446075   2008-08-04 22:31:44 534450    30
3   ONLINE  SYSAUX           534770   2008-01-12 16:51:53 446075   2008-08-04 22:31:44 534450    67
4   ONLINE  USERS            534770   2008-01-12 16:51:53 446075   2008-08-04 22:31:44 534450    66
5   ONLINE  EXAMPLE          534770   2008-01-12 16:51:53 446075   2008-08-04 22:31:44 534450    26
 
-- 在这里我们能发现下V$DATAFILE_HEADER里面记录的SCN和日志切换发生的checkpoint的SCN是一样的,
-- 这就证明了日志切换是会更新数据文件头的,同时日志切换的checkpoint是一个级别比较低的操作,
-- 它不会立即完成,这也是出于性能上考虑的。


增量checkpoint查看

当前所知只有在LOG_checkpoint_TIMEOUT设置了非0值之后触发的增量checkpoint会在alert文件中有记录,其他条件触发的增量checkpoint都不会记录在alert文件中。

-- 下面是当LOG_checkpoint_TIMEOUT设置为1800s的时候所产生的增量checkpoint记录
Sun Aug  3 19:08:56 2008
Incremental checkpoint up to RBA [0x8.e17.0], current log tail at RBA [0x8.1056.0]
Sun Aug  3 19:39:00 2008
Incremental checkpoint up to RBA [0x8.1be0.0], current log tail at RBA [0x8.1c6e.0]
Sun Aug  3 20:09:04 2008
Incremental checkpoint up to RBA [0x8.2af5.0], current log tail at RBA [0x8.2b6a.0]
Sun Aug  3 20:39:07 2008
Incremental checkpoint up to RBA [0x8.3798.0], current log tail at RBA [0x8.3851.0]
Sun Aug  3 21:09:10 2008
Incremental checkpoint up to RBA [0x8.47b9.0], current log tail at RBA [0x8.48bb.0]
Sun Aug  3 21:39:14 2008
Incremental checkpoint up to RBA [0x8.548d.0], current log tail at RBA [0x8.5522.0]
Mon Aug  4 21:05:18 2008


查看fast_start_mttr_target

通过查看V$INSTANCE_RECOVERY动态性能视图可以查看一些MTTR相关的信息。

SELECT TARGET_MTTR,ESTIMATED_MTTR,CKPT_BLOCK_WRITES,CKPT_BLOCK_WRITES FROM V$INSTANCE_RECOVERY

TARGET_MTTR 用户设置的参数FAST_START_MTTR_TARGET的值. ESTIMATED_MTTR 根据目前脏块数目和日志块数目,评估的现在进行恢复所需要的时间. CKPT_BLOCK_WRITES 检查点写完的块数目. CKPT_BLOCK_WRITES 额外的因为检查点引起的数据库写入操作 (因为不必要的检查点的产生,设置一个非常小的系统恢复时间将会对性能产生负面影响,为了帮助管理员监测这个参数设置较小时对数据库的影响,这个视图显示了这个列)


相关视图


V$视图

V$DATAFILE_HEADER 查看数据文件的完全checkpoint信息。 V$INSTANCE_RECOVERY 查看fast_start_mttr_target设置以及系统MTTR相关信息。


X$视图

X$BH 用于查看脏块的LRBA和HRBA(There is also a recovery RBA which is used to record the progress of partial block recovery by PMON.) 。 X$TARGETRBA 查看增量checkpoint RBA,target RBA和on-disk RBA。 X$KCCCP 这里面也有增量checkpoint RBA,target RBA的信息。 X$KCCRT 完全checkpoint(full thread checkpoint)RBA信息。


补充说明

写完这篇文章之后又看了写在itpub上的讨论,更新下观点。( http://www.itpub.net/viewthread.php?tid=1053847 )

关于增量checkpoint和完全的checkpoint的区别这方面的争论里来不少,特别是对于日志切换到底是增量还是完全的争论更是如此,但是其实翻遍Oracle的文档就没有发现有提到增量checkpoint(incremental checkpoint)或是完全checkpoint(full checkpoint)这两个概念。

我的观点是根本就没有必要可以的区分是增量还是完全,真正要理解的是不同情况下的checkpoint都会有些什么样的行为,然后根据这些行为来对数据库进行配置,设置相应的参数,制定相应的备份/恢复策略,就此而已。
下面列出写常见的checkpoint行为:

  1. 类似于alter system checkpoint这样的语句所产生的,先记录下当前的scn,然后推动DBWn进程去写脏数据,当写到所记录的scn时候检查点结束,然后ckpt进程将记录的scn写入到控制文件和数据文件头。

  2. 设置参数log_checkpoint_timeout之后产生的,在超时值达到的时候,ckpt进程记录当时DBWn写脏数据的进度,也就是写到那个scn了,此时检查点信息只记录到控制文件中,同时如果设置了LOG_checkpointS_TO_ALERT的话我们会在alert中得到这样的信息:Sun Aug  3 19:08:56 2008
    Incremental checkpoint up to RBA [0x8.e17.0], current log tail at RBA [0x8.1056.0]

  3. ckpt进程每3s起来一次记录checkpoint的进度到控制文件中,这种情况跟上面的类似,只不过在alert里面是看不到的,而且也不是每次唤醒都会写控制文件的,而是有就记,没有就拉倒。

  4. 类似于alter system switch logfile所产生的,先记录下发出命令时刻的scn,ckpt进程不会推动DBWn去写脏数据,而是让DBWn按照自己的状态去写脏数据,等到写到记录的scn时,chpt进程再去更新控制文件和数据文件头。这种情况在alert也能看到信息:Mon Aug  4 22:31:39 2008
    Beginning log switch checkpoint up to RBA [0x9.2.10], SCN: 534450
    Thread 1 advanced to log sequence 9
      Current log# 2 seq# 9 mem# 0: /u/app/oracle/oradata/orcl/redo02.log
    Mon Aug  4 22:35:58 2008
    Completed checkpoint up to RBA [0x9.2.10], SCN: 534450


参考文档

  • Metalink: Automatic checkpoint Tuning

  • Metalink: checkpoint Tuning and Troubleshooting Guide

  • Metalink: 8i Parameters that Influence checkpoints

  • 《Oracle 9i&10G编程艺术》

  • 《checkpointing in Oracle》
    /files/Checkpointing_in_Oracle.pdf

  • Redo Byte Address (RBA)
    http://www.ixora.com.au/notes/rba.htm ]

  • 关于fast_start_io_target,log_checkpoint_interval,log_checkpoint_time的一点看法
    http://www.itpub.net/148219.html

  • Oracle 9i新特性研究系列之七
    http://oracle.chinaitlab.com/serial/18638.html

  • checkpoint说明
    http://airlgc.blog.51cto.com/161810/26175

  • Oracle checkpoint
    http://www.adp-gmbh.ch/ora/concepts/checkpoint.html


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


1、 完全检查点

在Oracle8i之前,数据库的发生的检查点都是完全检查点,完全检查点会将数据缓冲区里面所有的脏数据块写入相应的数据文件中,并且同步数据文件头和控制文件,保证数据库的一致。完全检查点在8i之后只有在下列两种情况下才会发生:

(1、)DBA手工执行alter system checkpoint的命令;

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

由于完全检查点会将所有的脏数据库块写入,巨大的IO往往会影响到数据库的性能。因此Oracle从8i开始引入了增量检查点的概念。


2、 增量检查点
Oracle从8i开始引入了检查点队列这么一种概念,用于记录数据库里面当前所有的脏数据块的信息,DBWR 根据这个队列而将脏数据块写入到数据文件中。检查点队列按时间先后记录着数据库里面脏数据块的信息,里面的条目包含RBA(Redo Block Address,重做日志里面用于标识检查点期间数据块在重做日志里面第一次发生更改的编号)和数据块的数据文件号和块号。在检查点期间不论数据块更改几次,它在检查点队列里面的位置始终保持不变,检查点队列也只会记录它最早的RBA,从而保证最早更改的数据块能够尽快写入。当DBWR将检查点队列里面的脏数据块写入到数据文件后,检查点的位置也要相应地往后移。

先看一下checkpoint queue(检查点队列)的概念,检查点发生后,触发DBWn进程,ckpt获取发生检查点时对应的scn,通知DBWn要写到这个scn为止,DBWR与dirty buffer(脏数据缓冲区)是根据数据块被首次更改的时间顺序写出的,也就是说,数据块被更改后会进入一个检查点队列,DBWR进程就根据队列的顺序批量的写入到数据文件中,写到哪个数据块时,那个数据块的首次变化的scn就是当前所有数据文件block的最新scn,但是由于无法适时地的将dbwr进度记录下来,所以oracle选择了一些策略,其中就包括ckpt进程的检查点和心跳。

  检查点发生后,ckpt进程检查checkpoint queue是否过长,如果是,则触发dbwr,将一部分脏块写入数据文件,从而缩短checkpoint queue。

  checkpoint发生时,一方面通知dbwr进行下一批次的写操作,另一方面,oracle采用了一个心跳的概念,以3秒的频率将dbwr写的进度反应到控制文件中,也就是把dbwr刚写完的对应的数据块的scn写入数据文件头和控制文件,这就是检查点scn。这个3秒和增量检查点不是一个概念,3秒只是在控制文件中,ckpt进程去更新dbwr写到哪里了。这个对于ckpt进程来说叫做heartbeat(心跳)我们可以理解为每间隔3秒不停的检查并记录dbwr的进度。

检查点发生之后数据库的文件、控制处于一致状态含义 是不需要 进行介质恢复,只表示数据文件头一致但是并不表示数据文件内容一致,因为 数据文件内容可能在没有发生检查点的 其它情况下dbwr 写数 据文件,这样数据文件内容就不一致,若掉电需要进行崩溃恢复。

CKPT进程每三秒会在控制文件中记录检查点的位置,以表示Instance Recovery时开始恢复的日志条目,这个概念称为检查点的“心跳”(heartbeat)。检查点位置发生变更后,Oracle里面通过4个参数用于控制检查点位置和最后的重做日志条目之间的距离。在这里面需要指出的是,多数人会将这4个参数看作控制增量检查点发生的时间。事实上这是错误的,这4个参数是用于控制检查点队列里面的条目数量,而不是控制检查点的发生。

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

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

v$instance_recovery.estimated_mttr 显示当前估计需要恢复的秒数。这个值会 显示即使 FAST_START_MTTR_TARGET 没有被指定。 

v$instance_recovery.target_mttr 表明在短时间内 MTTR 的目标。 

v$mttr_target_advice显示这个当前 显示这个当前 MTTR 设置的 工作量产生I/O 数量和其他 I/O 。 这个视图帮助用户评定在优化和恢复之前的平衡

(3)、log_checkpoint_timeout
该参数用于表示检查点位置和重做日志文件末尾之间的时间间隔,以秒为单位,默认情况下是1800秒。

(4)、log_checkpoint_interval
该参数是表示检查点位置和重做日志末尾的重做日志块的数量,以OS块表示。

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

oracle 9i instance recovery
1. 增量检查点
在checkpoint queue的基础上实现了增量检查点,每3秒发生一次checkpoint heartbeat,记录dbwr上次写成功的最大RBA(redo block address)。这样的话做instance recovery的时候就从这个rba开始,而不是从上次checkpoint scn开始,大大节省了恢复时间。
 
2. twice scan of redo log
在应用redo之前,redo将会被操作两次,第一次去扫描哪些redo record需要被应用,因为9i在redo里添加了dbwr写数据块的信息,所以dbwr发生前的日志将不会被应用。第二步就是选出需要被应用的日志然后开始rollforward。
 
3. rollforward
在做instance recovery时必须先定位到redo log 然后应用所有日志到datafile,这时候包括了committed和uncommitted的数据。当做完rollward,数据库就可以open了。
 
4. rollback
因 为rollforward产生了uncommitted数据,所以必须回滚这些数据。这将由smon和on-demand rollback来实现。smon将会扫描undo segment header去标志所有活动事务为dead,然后会逐渐去回滚这些事务。另外on-demand rollback提供了前台进程进行rollback,当前台进程企图获得被dead事务占用row lock,这时候前台进程将会去undo segment取得before image去回滚这个块,至于其他被这个dead事务lock的块就等待smon去回滚。
 
另外,如果 在数据库打开的过程中process crash导致transaction dead,resource不能被释放的情况,这时候如果另一个进程需要这些resource,那么这个进程将会等待直到pmon清理dead process释放出resource。

如果数据库Crash,重新启动,很久远以前的未提交事务并不在Redo的恢复序列中。
但是未提交事务一定在回滚段事务表上存在,并且State=10,为活动事务。这就够了。

数据库启动之后,这些事务会被SMON逐个标记为Dead(不可能再活过来了),然后由SMON慢慢去回滚这些事务;也存在另外一种情况,后来的进程会去读这些未提交数据,发现Dead事务未提交,则主动进行回滚。

1. 一个数据块发生更新,必然写回滚
2. 回滚段的block变化也记录在redo中

一份未提交的数据必定在回滚中有相应的前镜像,任何正常的恢复都一定会把这些变化重新构建出来。


想像一下

1. update事务1更新了block 1
2. 回滚段1记录了block1的前镜像
3. checkpoint
4. update事务2更新了block2
5. 回滚段2记录了block2的前镜像
6. instance crash

现在重启数据库

1. 根据redo重新构建block2
2. 根据redo重新构建回滚段2
3. database open
4. SMON用回滚段2的数据回滚block2,SMON用回滚段1的数据回滚block1

最后一步也可能是
在另外一个select检索到block1或者block2的时候,发现这两个block的数据都是未提交的,此时再回滚block1和block2。

所以,只要有相应的回滚数据存在,无论什么时候oracle都可以找到一致的数据,oracle只需要知道这个事务是提交了的还是没提交了的,而这点在block header ITL中有记录。

  http://spaces.msn.com/roujiaweize/blog/cns!9745F14B4AEB3B72!328.entry




oracle之检查点(Checkpoint)

检查点是一个数据库事件,它把修改的数据从高速缓存写入磁盘,并更新控制文件和数据文件。


检查点分为三类
1)局部检查点:单个实例执行数据库所有数据文件的一个检查点操作,属于此实例的全部脏缓存区写入数据文件。
触发命令:
svmrgrl>alter system checkpoint local;
这条命令显示的触发一个局部检查点。


2)全局检查点:所有实例(对应并行数据服务器)执行数据库所有数据文件的一个检查点操作,属于此实例的全部脏缓存区写入数据文件。
触发命令
svrmgrl>alter system checkpoint global;
这条命令显示的触发一个全局检查点。


3)文件检查点:所有实例需要执行数据文件集的一个检查点操作,如使用热备份命令alter tablespace USERS begin backup,或表空间脱机命令alter tablespace USERS offline,将执行属于USERS表空间的所有数据文件的一个检查点操作。


检查点处理步骤:
1)获取实例状态队列:实例状态队列是在实例状态转变时获得,ORACLE获得此队列以保证检查点执行期间,数据库处于打开状态;
2)获取当前检查点信息:获取检查点记录信息的结构,此结构包括当前检查点时间、活动线程、进行检查点处理的当前线程、日志文件中恢复截止点的地址信息;
3)缓存区标识:标识所有脏缓存区,当检查点找到一个脏缓存区就将其标识为需进行刷新,标识的脏缓存区由系统进程DBWR进行写操作,将脏缓存区的内容写入数据文件;
4)脏缓存区刷新:DBWR进程将所有脏缓存区写入磁盘后,设置一标志,标识已完成脏缓存区至磁盘的写入操作。系统进程LGWR与CKPT进程将继续进行检查,直至DBWR进程结束为止;
5)更新控制文件与数据文件
注:控制文件与数据文件头包含检查点结构信息。
在两种情况下,文件头中的检查点信息(获取当前检查点信息时)将不做更新:
1)数据文件不处于热备份方式,此时ORACLE将不知道操作系统将何时读文件头,而备份拷贝在拷贝开始时必须具有检查点SCN;
ORACLE在数据文件头中保留一个检查点的记数器,在正常操作中保证使用数据文件的当前版本,在恢复时防止恢复数据文件的错误版本;即使在热备份方式下,计数器依然是递增的;每个数据文件的检查点计数器,也保留在控制文件相对应数据文件项中。
2)检查SCN小于文件头中的检查点SCN的时候,这表明由检查点产生的改动已经写到磁盘上,在执行全局检查点的处理过程中,如果一个热备份快速检查点在更新文件头时,则可能发生此种情况。应该注意的是,ORACLE是在实际进行检查点处理的大量工作之前捕获检查SCN的,并且很有可能被一条象热备份命令alter tablespace USERS begin backup进行快速检查点处理时的命令打断。
ORACLE在进行数据文件更新之前,将验证其数据一致性,当验证完成,即更新数据文件头以反映当前检查点的情况;未经验证的数据文件与写入时出现错误的数据文件都被忽略;如果日志文件被覆盖,则这个文件可能需要进行介质恢复,在这种情况下,ORACLE系统进程DBWR将此数据文件脱机。
检 查点算法描述:
脏缓存区用一个新队列链接,称为检查点队列。对缓存区的每一个改动,都有一个与其相关的重做值。检查点队列包含脏的日志缓存区,这些缓存区按照它们在日志文件中的位置排序,即在检查点队列中,缓存区按照它们的低重做值进行排序。需要注意的是,由于缓存区是依照第一次变脏的次序链接到队列中的,所以,如果在缓存区写出之前对它有另外的改动,链接不能进行相应变更,缓存区一旦被链接到检查点队列,它就停留在此位置,直到将它被写出为止。
ORACLE系统进程DBWR在响应检查点请求时,按照这个队列的低重做值的升序写出缓存区。每个检查点请求指定一个重做值,一旦DBWR写出的缓存区重做值等于或大雨检查点的重做值,检查点处理即完成,并将记录到控制文件与数据文件。
由于检查点队列上的缓存区按照低重做值进行排序,而DBWR也按照低重做值顺序写出检查点缓存区,故可能有多个检查点请求处于活动状态,当DBWR写出缓存区时,检查位于检查点队列前端的缓存区重做值与检查点重做值的一致性,如果重做值小于检查点队列前缓存区的低重做值的所有检查点请求,即可表示处理完成。当存在未完成的活动检查点请求时,DBWR继续写出检查点缓存区。
算法特点:
1)DBWR能确切的知道为满足检查点请求需要写那些缓存区;
2)在每次进行检查点写时保证指向完成最早的(具有最低重做值的)检查点;
3)根据检查点重做值可以区别多个检查点请求,然后按照它们的顺序完成处理。

1.检查点(Checkpoint)的本质

许多文档把Checkpint描述得非常复杂,为我们正确理解检查点带来了障碍,结果现在检查点变成了一个非常复杂的问题。实际上,检查点只是一个数据库事件,它存在的根本意义在于减少崩溃恢复(Crash Recovery)时间

当修改数据时,需要首先将数据读入内存中(Buffer Cache),修改数据的同时,Oracle会记录重做信息(Redo)用于恢复。因为有了重做信息的存在,Oracle不需要在提交时立即将变化的数据写回磁盘(立即写的效率会很低),重做(Redo)的存在也正是为了在数据库崩溃之后,数据就可以恢复。

最常见的情况,数据库可以因为断电而Crash,那么内存中修改过的、尚未写入文件的数据将会丢失。在下一次数据库启动之后,Oracle可以通过重做日志(Redo)进行事务重演,也就是进行前滚,将数据库恢复到崩溃之前的状态,然后数据库可以打开提供使用,之后Oracle可以将未提交的数据进行回滚。

在这个过程中,通常大家最关心的是数据库要经历多久才能打开。也就是需要读取多少重做日志才能完成前滚。当然用户希望这个时间越短越好,Oracle也正是通过各种手段在不断优化这个过程,缩短恢复时间。

检查点的存在就是为了缩短这个恢复时间。

当检查点发生时(此时的SCN被称为CheckPoint SCN),Oracle会通知DBWR进程,把修改过的数据,也就是Checkpoint SCN之前的脏数据(Dirty Data)从Buffer Cache写入磁盘,当写入完成之后,CKPT进程更新控制文件和数据文件头,记录检查点信息,标识变更。

Oracle SCN的相关知识可以参考我的另外一篇文章: DBA入门之认识Oracle SCN(System Change Number)

Checkpoint SCN可以从数据库中查询得到:

SQL> select file#,CHECKPOINT_CHANGE#,to_char(CHECKPOINT_TIME,'yyyy-mm-dd hh34:mi:ss') cpt from v$datafile;

FILE# CHECKPOINT_CHANGE# CPT

---------- ------------------ -------------------
1 913306 2011-11-16 16:06:06

2 913306 2011-11-16 16:06:06

3 913306 2011-11-16 16:06:06

4 913306 2011-11-16 16:06:06

SQL> select dbid,CHECKPOINT_CHANGE# from v$database;

DBID CHECKPOINT_CHANGE#

---------- ------------------
1294662348 913306

在检查点完成之后,此检查点之前修改过的数据都已经写回磁盘,重做日志文件中的相应重做记录对于崩溃/实例恢复不再有用。

下图标记了3个日志组,假定在T1时间点,数据库完成并记录了最后一次检查点,在T2时刻数据库Crash。那么在下次数据库启动时,T1时间点之前的Redo不再需要进行恢复,Oracle需要重新应用的就是时间点T1至T2之间数据库生成的重做日志(Redo)。

上图可以很轻易地看出来,检查点的频率对于数据库的恢复时间具有极大的影响,如果检查点的频率高,那么恢复时需要应用的重做日志就相对得少,检查时间就可以缩短。然而,需要注意的是,数据库内部操作的相对性极强,国语平凡的检查点同样会带来性能问题,尤其是更新频繁的数据库。所以数据库的优化是一个系统工程,不能草率。

更进一步可以知道,如果Oracle可以在性能允许的情况下,使得检查点的SCN主键逼近Redo的最新更新,那么最终可以获得一个最佳平衡点,使得Oracle可以最大化地减少恢复时间。

为了实现这个目标,Oracle在不同版本中一直在改进检查点的算法。

2.常规检查点与增量检查点

为了区分,在Oracle8之前,Oracle实时的检查点通常被称为常规检查点(Conventional Checkpoint),这类检查点按一定的条件出发(log_checkpoint_interval、log_checkpoint_timeout参数设置及log switch等条件出发)。

从Oracle 8开始,Oracle引入了增量检查点(Inctrmental Checkpoint)的概念。

和以前的版本相比,在新版本中,Oracle主要引入了检查点队列(Checkpoinnt Queue)机制,在数据库内部,每一个脏数据块都会被移动到检查点队列,按照Low RBA的顺序(第一次对比数据块修改对应的Redo Byte Address)来排列,如果一个数据块进行过多次修改,该数据库在检查点队列上的顺序并不会发生变化。

当执行检查点时,DBWR从检查点队列按照Low RBA的顺序写出,实例检查点因此可以不断增进、阶段性的,CKPT进程使用非常轻量级的控制文件更新协议,将当前的最低RBA写入控制文件。

因为增量检查点可以连续地进行,因此检查点RBA可以比常规检查点更接近数据库的最后状态,从而在数据库的实例恢复中可以极大地减少恢复时间。

而且,通过增量检查点,DBWR可以持续进行写出,从而避免了常规检查点出发的峰值写入对于I/O的国度征用,通过下图可以清楚地看到这一改进的意义。

在数据库中,增量检查点是通过Fast-Start Checkpointing特性来实现的,从Oracle 8i开始,这一特性包含了Oracle企业版的Fast-Start Fault Recovery组件之中,通过查询v$option视图,了解这一特性:

SQL>select*from v$version where rownum<2;

BANNER

----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4. – Prod

SQL> col parameter for a30

SQL> col value for a20

SQL>select*from V$optionwhere Parameter='Fast-Start Fault Recovery';

PARAMETER VALUE

------------------------------ --------------------
Fast-Start Fault Recovery TRUE

该组件包含3个主要特性,可以加快系统在故障后的恢复,提高系统的可用性。

Fast-Start Checkpointing;

Fast-Start On-Demand Rollback;

Fast-Start Parallel Rollback;

Fast-Start Checkpointing 特性在Oracle 8i中主要通过参数FAST_START_IO_TARGET来实现,在Oracle 9i中,Fast-Start Checkpointing主要通过参数FAST_START_MTTR_TARGET来实现。

3.FAST_START_MTTR_TARGET

FAST_START_MTTR_TARGET参数从Oracle 9i开始被引入,该参数定义数据库进行Crash恢复的时间,单位是秒,取值范围是在0~3600秒之间。

在Oracle 9i中,Oracle推荐设置这个参数代替FAST_START_IO_TARGE、LOG_CHECKPOINT_TIMEROUT及LOG_CHECKPOINT_INSTERVAL参数。

缺省情况下,在Oracle 9i中,FAST_START_IO_TARGET和LOG_CHECKPOINT_INTERVAL参数已经被设置为0.

SQL> show parameter fast_start_io

NAME TYPE VALUE

------------------------------------ ----------- ------------------------------
fast_start_io_target integer 

SQL> show parameter interval

NAME TYPE VALUE

------------------------------------ ----------- ------------------------------
log_checkpoint_interval integer 

在Oracle 9i R2开始,Oracle引入了一个新的视图提供MTTR建议:

SQL> select * from v$mttr_target_advice;

MTTR_TARGET_FOR_ESTIMATE ADVICE_STATUS DIRTY_LIMIT ESTD_CACHE_WRITES ESTD_CACHE_WRITE_FACTOR ESTD_TOTAL_WRITES ESTD_TOTAL_WRITE_FACTOR ESTD_TOTAL_IOS ESTD_TOTAL_IO_FACTOR

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

该视图评估在不同FAST_START_MATTR_TARGET设置下,系统需要执行的I/O次数等操作。用户可以根据数据库的建议,对FAST_START_MTTR_TARGET进行相应调整。

这个建议信息的手机收到Oracle 9i新引入的初始化参数statistics_level的控制,当该参数设置为Typical或ALL时,MTTR建议信息被手机:

SQL> show parameter statistics_level

NAME TYPE VALUE

------------------------------------ ----------- ------------------------------
statistics_level string TYPICAL

也可以通过v$statistics_level视图来查询MTTR_Advice的当前设置:

SQL> select * from v$statistics_level where STATISTICS_NAME='MTTR Advice';

STATISTICS_NAME DESCRIPTION SESSION_STATUS SYSTEM_STATUS ACTIVATION_LEVEL STATISTICS_VIEW_NAME SESSION_SETTABLE

---------------------------------------------------------------- -------------------------------------------------------------------------------- -------------- ------------- ---------------- ---------------------------------------------------------------- ----------------
MTTR Advice Predicts the impact of different MTTR settings on number of physical I/Os ENABLED ENABLED TYPICAL V$MTTR_TARGET_ADVICE NO

数据库当前的实例恢复状态可以通过视图v$instance_recovery查询得到:

SQL> select * from v$instance_recovery;

RECOVERY_ESTIMATED_IOS 53

ACTUAL_REDO_BLKS 376

TARGET_REDO_BLKS 184320

LOG_FILE_SIZE_REDO_BLKS 184320

LOG_CHKPT_TIMEOUT_REDO_BLKS

LOG_CHKPT_INTERVAL_REDO_BLKS

FAST_START_IO_TARGET_REDO_BLKS

TARGET_MTTR 

ESTIMATED_MTTR 18

CKPT_BLOCK_WRITES 27

OPTIMAL_LOGFILE_SIZE

ESTD_CLUSTER_AVAILABLE_TIME

WRITES_MTTR 

WRITES_LOGFILE_SIZE 

WRITES_LOG_CHECKPOINT_SETTINGS 

WRITES_OTHER_SETTINGS 

WRITES_AUTOTUNE 104

WRITES_FULL_THREAD_CKPT 

从v$instance_recovery视图,可以看到当前数据库估计的平均恢复时间(MTTR)参数:ESTIMATED_MTTR。

ESTIMATED_MTTR的估算值是基于Dirty Buffer 的数据量和日志块数量得出的,这个参数值告诉我们,如果此时数据库本亏,那么进行实例恢复将会需要的时间。

在V$instance_revovery视图中,TARGET_MTTR代表的是期望的恢复时间,通常改参数应该等于FAST_START_MTTR_TARGET参数设置值(但是如果FAST_START_MTTR_TARGET参数定义的值极大或极小,TARGET_MEER可能不等于FAST_START_MTTR_TARGET的设置)。

当ESTIMATED_MTTR接近或超过FAST_START_MTTR_TARGET参数设置(v$instance_recovery TARGET_MTTR)时,系统就会促发检查点,执行写出之后,系统恢复信息将会重新计算:

View Code

RECOVERY_ESTIMATED_IOS 24

ACTUAL_REDO_BLKS 43

TARGET_REDO_BLKS 184320

LOG_FILE_SIZE_REDO_BLKS 184320

LOG_CHKPT_TIMEOUT_REDO_BLKS

LOG_CHKPT_INTERVAL_REDO_BLKS

FAST_START_IO_TARGET_REDO_BLKS

TARGET_MTTR 

ESTIMATED_MTTR 18

CKPT_BLOCK_WRITES 73

OPTIMAL_LOGFILE_SIZE

ESTD_CLUSTER_AVAILABLE_TIME

WRITES_MTTR 

WRITES_LOGFILE_SIZE 

WRITES_LOG_CHECKPOINT_SETTINGS 

WRITES_OTHER_SETTINGS 

WRITES_AUTOTUNE 183

WRITES_FULL_THREAD_CKPT 

在繁忙的系统中,可能会观察到ESTIMATED_MTTR>TARGET_MTTR,这可能是因为DBWR正忙于写出,甚或出现Checkpoint不能及时完成的情况。

4. Oracle 10g自动检查点调整

从Oracle 10g开始,数据库可以实现自动调整的检查点,使用自动调整的检查点,Oracle数据库可以利用系统的低I/O负载时段写出内存中的脏数据,从而提高数据库的效率。因此,即使数据库管理员设置了不合理的检查点相关参数,Oracle仍然能够通过自动调整将数据库的Crash Recovery时间控制在合理的范围之内。

当FAST_START_MTTR_TARGET参数未设置,自动检查点调整生效。

通常,如果必须严格控制实例或节点恢复时间,那么可以设置FAST_START_MTTR_TARGET为期望时间值;如果恢复时间不严格控制,那么可以不设置FAST_START_MTTR_TARGET参数,从而启用Oracle 10g的自动调整特性。

当取消FAST_START_MTTR_TARGET参数设置之后:

SQL> show parameter fast_start_mttr

NAME TYPE VALUE

------------------------------------ ----------- ------------------------------
fast_start_mttr_target integer 

在启动数据库的时候,可以从alter文件中看到如下信息:

View Code

Thu Nov 17 20:27:23 2011

MTTR advisory is disabled because FAST_START_MTTR_TARGET is not set

检查v$instance_recovery视图,可以发现Oracle 10g的改变:

View Code

SQL> select * from v$instance_recovery;

RECOVERY_ESTIMATED_IOS 53

ACTUAL_REDO_BLKS 376

TARGET_REDO_BLKS 184320

LOG_FILE_SIZE_REDO_BLKS 184320

LOG_CHKPT_TIMEOUT_REDO_BLKS

LOG_CHKPT_INTERVAL_REDO_BLKS

FAST_START_IO_TARGET_REDO_BLKS

TARGET_MTTR 

ESTIMATED_MTTR 18

CKPT_BLOCK_WRITES 27

OPTIMAL_LOGFILE_SIZE

ESTD_CLUSTER_AVAILABLE_TIME

WRITES_MTTR 

WRITES_LOGFILE_SIZE 

WRITES_LOG_CHECKPOINT_SETTINGS 

WRITES_OTHER_SETTINGS 

WRITES_AUTOTUNE 104

WRITES_FULL_THREAD_CKPT 

在以上视图中,WRITES_AUTOTUNE字段数据就是指由于自动调整检查点执行的写出次数,而CK_BLOCK_WRITES指的则是由于检查点写出的Block的数量。

关于检查点的机制问题,我们侧重介绍了原理,至于具体的算法实现,不需要去追究过多,只要明白了这个原理性的规则,理解Oracle就会变成轻松的事情。

Oracle的算法改进是一种优化,对于数据库的调整优化也不外如此,借鉴Oracle的优化对于理解和优化Oracle数据库都具有极大的好处。

5.从控制文件获取检查点信息

在控制文件的转储中,可以看到关于检查点进程进度的记录:

View Code

***************************************************************************

CHECKPOINT PROGRESS RECORDS

***************************************************************************

(size = 8180, compat size = 8180, section max = 11, section in-use = 0,

last-recid= 0, old-recno = 0, last-recno = 0)

(extent = 1, blkno = 2, numrecs = 11)

THREAD #1 - status:0x2 flags:0x0 dirty:34

low cache rba:(0x23.19d5.0) on disk rba:(0x23.1a68.0)

on disk scn: 0x0000.000d847d 11/14/2011 15:25:37

resetlogs scn: 0x0000.0006ce7b 11/10/2011 22:40:23

heartbeat: 767211774 mount id: 1294947385

THREAD #2 - status:0x0 flags:0x0 dirty:0

low cache rba:(0x0.0.0) on disk rba:(0x0.0.0)

这里的low cache rba(Revovery block address)指在Cache中,最低的RBA地址,在实例恢复或者崩溃恢复中,需要从这里开始恢复。

On disk rba是磁盘上的最高的重做值,在进行恢复时应用重做至少要达到这个值。

除了检查点队列(CKPTQ)之外,数据库中还存在另外一个队列和检查点有关,这就是文件检查点队列(FILE QUEUE),通常称为FILEQ,文件检查点的引入提供了表空间相关的检查点的性能。每个Dirty  Buffer同时链接到这两个队列,CKPTQ包含实例所有需要执行检查点的Buffer,FILEQ包含属于特定文件需要执行的检查点Buffer,每个文件都包含一个文件队列,在执行表空间检查点请求时需要使用FILEQ,通常当对表空间执行Offline等操作时会触发表空间检查点。CKPTQ和FILEQ都是双向链表,每个队列中都记录了两个地址信息,分别是前一块和下一块Buffer的地址信息。注意只有Dirty Buffer才会包含CKPTQ信息,否则为NULL,信息类似"ckptq:[NULL]fileq:[NULL]"。

检查点(checkpoint)的工作机制

检查点是一个数据库事件,它把修改数据从高速缓存写入磁盘,并更新控制文件和数据文件,总结起来如下:检查点分为三类:1)局部检查点:单个实例执行数据库所有数据文件的一个检查点操作,属于此实例的全部脏缓存区写入数据文件。触发命令:svmrgrl>alter  system checkpoint local;这条命令显示的触发一个局部检查点。2)全局检查点:所有实例(对应并行数据服务器)执行数据库所有所有数据文件的一个检查点操作,属于此实例的全部脏缓存区写入数据文件。触发命令svrmgrl>alter system checkpoint global;这条命令显示的触发一个全局检查点。3)文件检查点:所有实例需要执行数据文件集的一个检查点操作,如使用热备份命令alter   tablespace USERS begin backup,或表空间脱机命令alter tablespace USERS offline,将执行属于USERS表空间的所有数据文件的一个检查点操作。检查点处理步骤:1)获取实例状态队列:实例状态队列是在实例状态转变时获得,ORACLE获得此队列以保证检查点执行期间,数据库处于打开状态;2)获取当前检查点信息:获取检查点记录信息的结构,此结构包括当前检查点时间、活动线程、进行检查点处理的当前线程、日志文件中恢复截止点的地址信息;3)缓存区标识:当数据在buffer cache中做了修改之后会自动被为脏缓冲区,加入到Checkpoint Queue的脏缓冲区队列。

4)脏缓存区刷新:当检查点发生时,会到CKPTQ中的脏缓冲区队列找到到目前为止最大的LRBA,并通知DBWR进程将所有脏缓存区写入磁盘,完成之后设置一标志,标识已完成脏缓存区至磁盘的写入操作,以便刷新脏缓冲队列(此时DML可以继续进行)。系统进程LGWR与CKPT进程将继续进行检查,直至DBWR进程结束为止;

5)更新控制文件与数据文件。注:控制文件与数据文件头包含检查点结构信息。在两种情况下,文件头中的检查点信息(获取当前检查点信息时)将不做更新:1)数据文件不处于热备份方式,此时ORACLE将不知道操作系统将何时读文件头,而备份拷贝在拷贝开始时必须具有检查点SCN;ORACLE在数据文件头中保留一个检查点的记数器,在正常操作中保证使用数据文件的当前版本,在恢复时防止恢复数据文件的错误版本;即使在热备份方式下,计数器依然是递增的;每个数据文件的检查点计数器,也保留在控制文件相对应数据文件项中。2)检查SCN小于文件头中的检查点SCN的时候,这表明由检查点产生的改动已经写到磁盘上,在执行全局检查点的处理过程中,如果一个热备份快速检查点在更新文件头时,则可能发生此种情况。应该注意的是,ORACLE是在实际进行检查点处理的大量工作之前捕获检查SCN的,并且很有可能被一条象热备份命令 alter tablespace USERS begin backup进行快速检查点处理时的命令打断。ORACLE在进行数据文件更新之前,将验证其数据一致性,当验证完成,即更新数据文件头以反映当前检查点的情况;未经验证的数据文件与写入时出现错误的数据文件都被忽略;如果日志文件被覆盖,则这个文件可能需要进行介质恢复,在这种情况下,ORACLE系统进程DBWR将此数据文件脱机。检查点算法描述:脏缓存区用一个新队列链接,称为检查点队列。对缓存区的每一个改动,都有一个与其相关的重做值。检查点队列包含脏的日志缓存区,这些缓存区按照它们在日志文件中的位置排序,即在检查点队列中,缓存区按照它们的LRBA进行排序。需要注算法特点:3)根据检查点重做值可以区别多个检查点请求,然后按照它们的顺序完成处理。1)DBWR能确切的知道为满足检查点请求需要写那些缓存区;2)在每次进行检查点写时保证指向完成最早的(具有最低重做值的)检查点;意的是,由于缓存区是依照第一次变脏的次序链接到队列中的,所以,如果在缓存区写出之前对它有另外的改动,链接不能进行相应变更,缓存区一旦被链接到检查点队列,它就停留在此位置,直到将它被写出为止。ORACLE系统进程DBWR在响应检查点请求时,按照这个队列的LRBA的升序写出缓存区。每个检查点请求指定一个重做值,一旦DBWR写出的缓存区重做值等于或大雨检查点的重做值,检查点处理即完成,并将记录到控制文件与数据文件。由于检查点队列上的缓存区按照低重做值进行排序,而DBWR也按照低重做值顺序写出检查点缓存区,故可能有多个检查点请求处于活动状态,当DBWR写出缓存区时,检查位于检查点队列前端的缓存区重做值与检查点重做值的一致性,如果重做值小于检查点队列前缓存区的低重做值的所有检查点请求,即可表示处理完成。当存在未完成的活动检查点请求时,DBWR继续写出检查点缓存区。



增量检查点如何更新控制文件

原文:http://www.askmaclean.com/archives/incremental-checkpoint-update-controlfile.html

Know more about checkpoint

checkpoint 分成很多种 full 、file、thread、parallel query、 object 、incremental 、logfile switch

每一种checkpoint 都有其自身的特性,例如Incremental Checkpoint会要求ckpt 每3s 更新一次controlfile 但是不更新datafile header, 而FULL CHECKPOINT要求立即完成(同步的) 且会同时更新 controlfile 和 datafile header。

Incremental Checkpoint会要求ckpt 每3s 更新一次controlfile
>>我想问的时:如何查看此时控制文件中更新的SCN?除了DUMP控制文件,有没有命令查询?

我希望通过以下演示说明该问题:

SQL> select * from v$version; BANNER ---------------------------------------------------------------- Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi PL/SQL Release 10.2.0.5.0 - Production CORE    10.2.0.5.0      Production TNS for Linux: Version 10.2.0.5.0 - Production NLSRTL Version 10.2.0.5.0 - Production SQL> oradebug setmypid; Statement processed. SQL> oradebug dump controlf 4; Statement processed. SQL> oradebug tracefile_name ; /s01/admin/G10R25/udump/g10r25_ora_4660.trc 另开一个窗口等待6s在做一次controlf DUMP  SQL>  exec dbms_lock.sleep(6); oradebug setmypid; oradebug dump controlf 4; oradebug tracefile_name ;  PL/SQL procedure successfully completed. SQL> Statement processed. SQL> Statement processed. SQL> /s01/admin/G10R25/udump/g10r25_ora_4663.trc

比较以上获得的2个前后有6s间隔的CONTROLFILE DUMP 文件:

[oracle@vrh8 udump]$ diff /s01/admin/G10R25/udump/g10r25_ora_4660.trc /s01/admin/G10R25/udump/g10r25_ora_4663.trc 1c1 < /s01/admin/G10R25/udump/g10r25_ora_4660.trc --- > /s01/admin/G10R25/udump/g10r25_ora_4663.trc 13c13 < Unix process pid: 4660, image: oracle@vrh8.oracle.com (TNS V1-V3) --- > Unix process pid: 4663, image: oracle@vrh8.oracle.com (TNS V1-V3) 15,18c15,19 < *** ACTION NAME:() 2012-07-22 07:59:08.215 < *** MODULE NAME:(sqlplus@vrh8.oracle.com (TNS V1-V3)) 2012-07-22 07:59:08.215 < *** SERVICE NAME:(SYS$USERS) 2012-07-22 07:59:08.215 < *** SESSION ID:(159.7) 2012-07-22 07:59:08.215 --- > *** 2012-07-22 07:59:31.779 > *** ACTION NAME:() 2012-07-22 07:59:31.779 > *** MODULE NAME:(sqlplus@vrh8.oracle.com (TNS V1-V3)) 2012-07-22 07:59:31.779 > *** SERVICE NAME:(SYS$USERS) 2012-07-22 07:59:31.779 > *** SESSION ID:(159.9) 2012-07-22 07:59:31.779 96,98c97,99 < THREAD #1 - status:0x2 flags:0x0 dirty:56 < low cache rba:(0x1a.3.0) on disk rba:(0x1a.121.0) < on disk scn: 0x0000.013fe7a8 07/22/2012 07:59:02 --- > THREAD #1 - status:0x2 flags:0x0 dirty:57 > low cache rba:(0x1a.3.0) on disk rba:(0x1a.148.0) > on disk scn: 0x0000.013fe7c2 07/22/2012 07:59:27 100,101c101,102 < heartbeat: 789262462 mount id: 2675014163 < Flashback log tail log# 15 thread# 1 seq 229 block 274 byte 0 --- > heartbeat: 789262470 mount id: 2675014163 > Flashback log tail log# 15 thread# 1 seq 229 block 275 byte 0 2490c2491 <   V$RMAN_STATUS: recid=140734752341296, stamp=140734752341288 --- >   V$RMAN_STATUS: recid=140733792718464, stamp=140733792718456 2501c2502 <   V$RMAN_STATUS: recid=140734752341296, stamp=140734752341288 --- >   V$RMAN_STATUS: recid=140733792718464, stamp=140733792718456 2511c2512 <   V$RMAN_STATUS: recid=140734752341296, stamp=140734752341288 --- >   V$RMAN_STATUS: recid=140733792718464, stamp=140733792718456 2521c2522 <   V$RMAN_STATUS: recid=140734752341296, stamp=140734752341288 --- >   V$RMAN_STATUS: recid=140733792718464, stamp=140733792718456 2531c2532 <   V$RMAN_STATUS: recid=140734752341296, stamp=140734752341288 --- >   V$RMAN_STATUS: recid=140733792718464, stamp=140733792718456

排除部分V$RMAN_STATUS记录存在差异外,最主要的差别在于: CHECKPOINT PROGRESS RECORDS 这是因为 ckpt 每3s一次对controlfile做heartbeat 更新 CHECKPOINT PROGRESS RECORDS。

第一次 controlf dump:

***************************************************************************
CHECKPOINT PROGRESS RECORDS
***************************************************************************
(size = 8180, compat size = 8180, section max = 11, section in-use = 0,
last-recid= 0, old-recno = 0, last-recno = 0)
(extent = 1, blkno = 2, numrecs = 11)
THREAD #1 – status:0×2 flags:0×0 dirty:56
low cache rba:(0x1a.3.0) on disk rba:(0x1a.121.0)
on disk scn: 0×0000.013fe7a8 07/22/2012 07:59:02
resetlogs scn: 0×0000.01394f1a 07/19/2012 07:27:21
heartbeat: 789262462 mount id: 2675014163
Flashback log tail log# 15 thread# 1 seq 229 block 274 byte 0
THREAD #2 – status:0×0 flags:0×0 dirty:0
low cache rba:(0×0.0.0) on disk rba:(0×0.0.0)
on disk scn: 0×0000.00000000 01/01/1988 00:00:00
resetlogs scn: 0×0000.00000000 01/01/1988 00:00:00
heartbeat: 0 mount id: 0
Flashback log tail log# 0 thread# 0 seq 0 block 0 byte 0

第二次 controlf dump:

***************************************************************************
CHECKPOINT PROGRESS RECORDS
***************************************************************************
(size = 8180, compat size = 8180, section max = 11, section in-use = 0,
last-recid= 0, old-recno = 0, last-recno = 0)
(extent = 1, blkno = 2, numrecs = 11)
THREAD #1 – status:0×2 flags:0×0 dirty:57
low cache rba:(0x1a.3.0) on disk rba:(0x1a.148.0)
on disk scn: 0×0000.013fe7c2 07/22/2012 07:59:27
resetlogs scn: 0×0000.01394f1a 07/19/2012 07:27:21
heartbeat: 789262470 mount id: 2675014163
Flashback log tail log# 15 thread# 1 seq 229 block 275 byte 0
THREAD #2 – status:0×0 flags:0×0 dirty:0
low cache rba:(0×0.0.0) on disk rba:(0×0.0.0)
on disk scn: 0×0000.00000000 01/01/1988 00:00:00
resetlogs scn: 0×0000.00000000 01/01/1988 00:00:00

差异在于:
on disk rba
on disk scn
heartbeat
Flashback log tail log#

即实际CKPT每3s更新heartbeat控制文件一次,更新的内容是 on disk rba、on disk scn、heartbeat 如果启用了闪回日志的话那么还有Flashback log , 而并不更新数据库当前的SCN(CURRENT SCN)。

如果你想查看ckpt每3s更新的 on disk scn的话可以参考 内部视图X$KCCCP–[K]ernel [C]ache [C]ontrolfile management [c]heckpoint [p]rogress  X$KCCCP Checkpoint Progress Records:

SQL> desc x$kcccp; Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ADDR                                               RAW(8)
 INDX                                               NUMBER
 INST_ID                                            NUMBER
 CPTNO                                              NUMBER
 CPSTA                                              NUMBER
 CPFLG                                              NUMBER
 CPDRT                                              NUMBER
 CPRDB                                              NUMBER
 CPLRBA_SEQ                                         NUMBER
 CPLRBA_BNO                                         NUMBER
 CPLRBA_BOF                                         NUMBER
 CPODR_SEQ                                          NUMBER
 CPODR_BNO                                          NUMBER
 CPODR_BOF                                          NUMBER
 CPODS                                              VARCHAR2(16)
 CPODT                                              VARCHAR2(20)
 CPODT_I                                            NUMBER
 CPHBT                                              NUMBER
 CPRLS                                              VARCHAR2(16)
 CPRLC                                              NUMBER
 CPMID                                              NUMBER
 CPSDR_SEQ                                          NUMBER
 CPSDR_BNO                                          NUMBER
 CPSDR_ADB                                          NUMBER

其中cpods 为 ” on disk scn” ,cpodr_seq||cpodr_bno||cpodr_bof为”on disk rba”,CPHBT为heartbeat number:

SQL> select cpods "on disk scn",
           to_char(cpodr_seq, 'xxxxxx') || ',' ||
           to_char(cpodr_bno, 'xxxxxxxxx') || ',' ||
           to_char(cpodr_bof, 'xxxxxxxxx') "on disk rba",
           CPHBT "heartbeat number"
      from x$kcccp; on disk scn      on disk rba                    heartbeat number
---------------- ------------------------------ ----------------
20968609              1a,      240a,         0         789263152
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.
SQL> 
SQL> 
SQL> exec dbms_lock.sleep(3);
PL/SQL procedure successfully completed.
SQL> select cpods "on disk scn",
           to_char(cpodr_seq, 'xxxxxx') || ',' ||
           to_char(cpodr_bno, 'xxxxxxxxx') || ',' ||
           to_char(cpodr_bof, 'xxxxxxxxx') "on disk rba",
           CPHBT "heartbeat number"
      from x$kcccp; on disk scn      on disk rba                    heartbeat number
---------------- ------------------------------ ----------------
20968613              1a,      2410,         0         789263154
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.
SQL> 
SQL> exec dbms_lock.sleep(3);
PL/SQL procedure successfully completed.
SQL> select cpods "on disk scn",
  2         to_char(cpodr_seq, 'xxxxxx') || ',' ||
  3         to_char(cpodr_bno, 'xxxxxxxxx') || ',' ||
  4         to_char(cpodr_bof, 'xxxxxxxxx') "on disk rba",
  5         CPHBT "heartbeat number"
  6    from x$kcccp;
on disk scn      on disk rba                    heartbeat number
---------------- ------------------------------ ----------------
20968623              1a,      241e,         0         789263156
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.

到此,相信大家对“Oracle检查点是什么”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI