检查点 Checkpoint

Checkpoint

概要

Checkpoint是Oracle数据库不定期触发的一个事件,它将已修改的数据从高速缓存刷新到磁盘,并更新控制文件和数据文件头。

詳細説明

什么时候发生checkpoint?
我们知道了checkpoint会刷新脏数据,但什么时候会发生checkpoint呢?以下几种情况会触发checkpoint。
1.当发生日志组切换的时候
2.当符合LOG_CHECKPOINT_TIMEOUTLOG_CHECKPOINT_INTERVALFAST_START_IO_TARGET,FAST_START_MTTR_TARGET参数设置的时候
3.当运行ALTER SYSTEM SWITCH LOGFILE的时候
4.当运行ALTER SYSTEM CHECKPOINT的时候
5.当运行ALTER TABLESPACE ... BEGIN BACKUPALTER TABLESPACE ... END BACKUP的时候
6.当运行ALTER TABLESPACE ... OFFLINE以及ALTER TABLESPACE ... DATAFILE的时候;

完全检查点

在以前的版本里每次checkpoint时都会做一个full thread checkpoint,这样的话所有脏数据会被写到磁盘,巨大的i/o对系统性能带来很大影响。

增量检查点(incremental checkpoint)

为了解决这个问题,oracle8以后推出了incremental checkpoint的机制,oracle引入了checkpoint queue机制,每一个脏块会被移到检查点队列里面去,按照low rdb(第一次对此块修改对应的RBA(Redo Byte Address))来排列,靠近检查点队列尾端的数据块的low rba值是最小的,而且如果这些赃块被再次修改后它在检查点队列里的顺序也不会改变,这样就保证了越早修改的块越早写入磁盘。每隔3秒钟ckpt会去更新控制文件和数据文件,记录checkpoint执行的情况。

数据字典

完全检查点

10:38:32 SQL> desc X$KCCRT
 Name                                                                                Null?    Type
 ----------------------------------------------------------------------------------- -------- ---------------
 ADDR                                                                                         RAW(4)
 INDX                                                                                         NUMBER
 INST_ID                                                                                      NUMBER
 RTNUM                                                                                        NUMBER
 RTSTA                                                                                        NUMBER
 RTCKP_SCN                                                                                    VARCHAR2(16)
 RTCKP_TIM                                                                                    VARCHAR2(20)
 RTCKP_THR                                                                                    NUMBER
 RTCKP_RBA_SEQ                                                                                NUMBER
 RTCKP_RBA_BNO                                                                                NUMBER
 RTCKP_RBA_BOF                                                                                NUMBER
 RTCKP_ETB                                                                                    RAW(132)
 RTOTF                                                                                        NUMBER
 RTOTB                                                                                        NUMBER
 RTNLF                                                                                        NUMBER
 RTLFH                                                                                        NUMBER
 RTLFT                                                                                        NUMBER
 RTCLN                                                                                        NUMBER
 RTSEQ                                                                                        NUMBER
 RTENB                                                                                        VARCHAR2(16)
 RTETS                                                                                        VARCHAR2(20)
 RTDIS                                                                                        VARCHAR2(16)
 RTDIT                                                                                        VARCHAR2(20)
 RTLHP                                                                                        NUMBER
 RTSID                                                                                        VARCHAR2(16)
 RTOTS                                                                                        VARCHAR2(20)

select *
from X$KCCRT
where indx=0;

example 1

10:37:13 SQL> select *
10:37:21   2  from X$KCCRT
10:37:21   3  where indx=0;

ADDR           INDX    INST_ID      RTNUM      RTSTA RTCKP_SCN
-------- ---------- ---------- ---------- ---------- ------------------------------------------------
RTCKP_TIM                                                     RTCKP_THR RTCKP_RBA_SEQ RTCKP_RBA_BNO RTCKP_RBA_BOF
------------------------------------------------------------ ---------- ------------- ------------- -------------
RTCKP_ETB
------------------------------------------------------------------------------------------------------------------------------------------------------
     RTOTF      RTOTB      RTNLF      RTLFH      RTLFT      RTCLN      RTSEQ RTENB
---------- ---------- ---------- ---------- ---------- ---------- ---------- ------------------------------------------------
RTETS                                                        RTDIS
------------------------------------------------------------ ------------------------------------------------
RTDIT                                                             RTLHP RTSID
------------------------------------------------------------ ---------- ------------------------------------------------
RTOTS
------------------------------------------------------------
0796A870          0          1          1         15 463271
03/02/2008 20:00:13                                                   1            21             2         16
020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
         0          0          3          1          3          3         21 1
02/25/2008 19:58:50                                          0
                                                                     20 dbcamin
02/26/2008 10:51:02

Elapsed: 00:00:00.01

example 2

ADDR           INDX    INST_ID      RTNUM      RTSTA RTCKP_SCN        RTCKP_TIM   RTCKP_THR RTCKP_RBA_SEQ RTCKP_RBA_BNO RTCKP_RBA_BOF RTCKP_ETB         RTOTF      RTOTB         RTNLF      RTLFH      RTLFT      RTCLN      RTSEQ RTENB            RTETS    RTDIS                     RTDIT                     RTLHP RTSID            RTOTS
-------- ---------- ---------- ---------- ---------- ---------------- -------------------- ---------- ------------- ------------- ------------- ---------------- ---------- ----------  ---------- ---------- ---------- ---------- ---------- ---------------- --------------------   ---------------- -------------------- ---------- ---------------- --------------------
4084B228          0          1          1         15 720368521        06/25/2004 18:49:37         1           949             2     16 0600000000000000          2          0              3          1          3          1        949 1               05/16/2004 13:29:03  0               1389 tbdb2in1         06/12/2004 12:30:50

这里显示了上一次的完全检查点是在06/25/2004 18:49:37发生,所以我们推断06/25/2004 18:49:37发生了一次日志切换,再去操作系统上去看生产的归档,果然18:49有一个归档生产。
-rw-r- 1 oracle oinstall 83532800 Jun 25 18:49 1_948.dbf

增量检查点

10:40:00 SQL> desc X$KCCCP
 Name                                                                                Null?    Type
 ----------------------------------------------------------------------------------- -------- -----------------
 ADDR                                                                                         RAW(4)
 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

select *
from X$KCCCP
where indx=0;
example 1
10:38:20 SQL> select *
10:38:31   2  from X$KCCCP
10:38:31   3  where indx=0;

ADDR           INDX    INST_ID      CPTNO      CPSTA      CPFLG      CPDRT      CPRDB CPLRBA_SEQ CPLRBA_BNO CPLRBA_BOF  CPODR_SEQ  CPODR_BNO
-------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
 CPODR_BOF CPODS                                            CPODT                                                   CPODT_I      CPHBT
---------- ------------------------------------------------ ------------------------------------------------------------ ---------- ----------
CPRLS                                                 CPRLC      CPMID  CPSDR_SEQ  CPSDR_BNO  CPSDR_ADB
------------------------------------------------ ---------- ---------- ---------- ---------- ----------
0796D838          0          1          1          2          0         18         21         21      62034          0         21      62056
         0 488139                                           03/03/2008 10:37:54                                   648383874  647882020
1                                                 647639924  899090908          0          0          0

Elapsed: 00:00:00.00

example 2
ADDR           INDX    INST_ID      CPTNO      CPSTA      CPFLG      CPDRT      CPRDBCPLRBA_SEQ CPLRBA_BNO CPLRBA_BOF  CPODR_SEQ  CPODR_BNO  CPODR_BOF CPODSCPODT                   CPODT_I      CPHBT CPRLS                 CPRLC      CPMIDCPSDR_SEQ  CPSDR_BNO  CPSDR_ADB
-------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------------- -------------------- ---------- ---------- ---------------- ---------- ---------- ---------- ---------- ----------
4084B45C          0          1          1          2          0      10762      29753       949      76847          0        949     106814              0 721554970        06/25/2004 21:05:10   529794310  529036227 1                 526310932        1413781667        949              1          0

这里显示了low-rba,on-disk rba,checkpoint time等信息。

控制文件和数据文件的更新

每隔3秒钟ckpt会去更新控制文件和数据文件,记录checkpoint执行的情况。

这里应该是只更新控制文件,每3秒不是更新数据文件
说 记录 checkpoint 的执行情况,这个说法,没错,但不够详细,应该说,由于增量检查点和 checkpoint queue 的原理,ckpt 进程每次只是告诉 dbwr ,写dirty buffer将要一直写到最新这个位置,仅仅是告诉 dbwr 一个 checkpoint queue 中的结束点,而 ckpt 每3秒中,在控制文件中报告一下 dbwr 最新写入的位置。 这样使得,比如数据库要做恢复的时候(instance recovery)可以从这个最新位置开始做恢复,而不是从数据文件中的 checkpoint scn 开始做恢复,这样将缩短恢复时间,尤其是 instance crash 的情况下启动更快

另外要注意的是,检查点发生的时候,ckpt 去更新数据文件头和控制文件,并不是把当前检查点发生时候的 scn 更新进去,而是把上一次dbwr写入已经完成的检查点发生时候的 scn 更新进去 ,也就是说,更新控制文件和数据文件头 是 滞后于检查点的发生的,这个从恢复的原理也很容易理解,因为检查点发生的时候 dirty buffer还没有写入,自然不能立即更新成当前的 scn 了。

Reference

http://www.dedecms.com/web-art/shujuku/Oracle/20061007/37238.html

See Also

Checkpoint