1、什么是checkpoint
在数据库系统中,写日志和写数据文件是数据库中IO消耗最大的两种操作,
在这两种操作中写数据文件属于分散写,写日志文件是顺序写,
因此为了保证数据库的性能和数据一致性,通常数据库都是保证在提交(commit)
完成之前要先保证日志都被写入到日志文件中,
而脏数据块着保存在数据缓存(buffer cache)中再不定期的分批写入到数据文件中。
也就是说日志写入和提交操作是同步的,而数据写入和提交操作是不同步的。
这样就存在一个问题,当一个数据库崩溃的时候并不能保证缓存里面的脏数据全部写入到数据文件中,
这样在实例启动的时候就要使用日志文件进行恢复操作,将数据库恢复到崩溃之前的状态,保证数据的一致性。
检查点是这个过程中的重要机制,通过它来确定,恢复时哪些重做日志应该被扫描并应用于恢复。
一般所说的checkpoint是一个数据库事件(event),checkpoint事件由checkpoint进程(LGWR/CKPT进程)发出,
当checkpoint事件发生时DBWn会将脏块写入到磁盘中,同时数据文件和控制文件的文件头也会被更新以记录checkpoint信息。
2、checkpoint的作用
checkpoint主要2个作用:
2.1) 保证数据库的一致性,这是指将脏数据写入到硬盘,保证内存和硬盘上的数据是一样的;
2.2) 缩短实例恢复的时间,实例恢复要把实例异常关闭前没有写出到硬盘的脏数据通过日志进行恢复。
如果脏块过多,实例恢复的时间也会很长,检查点的发生可以减少脏块的数量,从而提高实例恢复的时间。
通俗的说checkpoint就像word的自动保存一样。
3、top检查点分类:
完全检查点(Normal checkpoint)
增量检查点(Incremental checkpoint)
4、 检查点队列 checkpoint queue
RBA(Redo Byte Address), Low RBA(LRBA), High RBA(HRBA)
RBA就是重做日志块(redo log block)的地址,相当与数据文件中的ROWID,通过这个地址来定位重做日志块。RBA由三个部分组成:
1.日志文件序列号(4字节)
2.日志文件块编号(4字节)
3.重做日志记录在日志块中的起始偏移字节数(2字节)
RBA A"Redo Block Address" (RBA) describes a physical location within aredo log file.
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的。
5、完全检查点 (normal checkpoint)
完全检查点工作过程
一个checkpoint操作可以分成三个不同的阶段:
第一阶段,checkpoint进程开始一个checkpoint事件,并记录下checkpoint RBA,这个通常是当前的RBA。
第二阶段,checkpoint进程通知DBWn进程将所有checkpoint RBA之前的buffer cache里面的脏块写入磁盘。
确定脏块都被写入磁盘以后进入到第三阶段,checkpoint进程将checkpoint信息(SCN)写入/更新数据文件和控制文件中。
什么时候发生normal checkpoint
下面这些操作将会触发checkpoint事件:
1 日志切换,通过ALTER SYSTEM SWITCH LOGFILE。
2 DBA发出checkpoint命令,通过ALTER SYSTEM checkpoint。
3 对数据文件进行热备时,针对该数据文件的checkpoint也会进行,
ALTER TABLESPACE TS_NAME BEGIN BACKUP/END BACKUP。
4 当运行ALTER TABLESPACE/DATAFILE READ ONLY的时候。
5 SHUTDOWN命令发出时。
特别注意:
1.日志切换会导致checkpoint事件发生,但是checkpoint发生却不会导致日志切换。
2.日志切换触发的是normal checkpoint,而不是大家所说的增量checkpoint,只不过log switch checkpoint的优先级非常低,
当一个log switch checkpoint发生的时候它并不会立即的通知DBWn进程去写数据文件,
但是当有其它原因导致checkpoint或者是写入数据文件的RBA超过log switch checkpoint的checkpoint RBA的时候,
这次的log switch checkpoint将会被标记成完成状态,同时更新控制文件和数据文件头。
6、增量checkpoint
top增量checkpoint工作过程
因为每次完全的checkpoint都需要把buffer cache所有的脏块都写入到数据文件中,这样就是产生一个很大的IO消耗,
频繁的完全checkpoint操作很对系统的性能有很大的影响,为此Oracle引入的增量checkpoint的概念,
buffer cache中的脏块将会按照BCQ队列的顺序持续不断的被写入到磁盘当中,同时CKPT进程将会每3秒中检查DBWn的写入进度并将相应的RBA信息记录到控制文件中。
有了增量checkpoint之后在进行实例恢复的时候就不需要再从崩溃前的那个完全checkpoint开始应用重做日志了,只需要从控制文件中记录的RBA开始进行恢复操作,
这样能节省恢复的时间。
增量检查点并不会去更新数据文件头,以及控制文件中数据库SCN以及数据文件条目的SCN信息,
而只是每3秒由CKPT进程去更新控制文件中的low cache rba信息,也就是检查点的位置。
与完全checkpoint的区别
1 完全checkpoint会将checkpoint的信息写入到控制文件以及数据文件头中
2 增量checkpoint只会将RBA信息写入到控制文件中。
7、 LOG_checkpointS_TO_ALERT
通过将LOG_checkpointS_TO_ALERT设置成TRUE来打开checkpoint的trace,这样就可以跟踪checkpoint的操作了。
ALTER SYSTEM SET LOG_checkpointS_TO_ALERT=TRUE;
这设置以后系统的checkpoint将会被记录alert_$SID.log文件中。
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;
ALTER SYSTEM checkpoint;
ALTER SYSTEMS WITCH LOGFILE;
select CPDRT,CPLRBA_SEQ||'.'||CPLRBA_BNO||'.'||CPLRBA_BOF "Low
RBA",CPODR_SEQ||'.'||CPODR_BNO||'.'||CPODR_BOF "On disk RBA",CPODT from x$kcccp;
CPDRT列是检查点队列中的脏块数目.
CPODS列是on disk rba的scn
CPODT列是on disk rba的时间戳
如果发生了实例崩溃,只需要在日志文件中找到检查点位置(low cache rba),从此处开始应用所有的重做日志文件,就完成了前滚操作。实例崩溃后,
再次启动数据库,oracle会到控制文件中读取low cache rba,这就是检查点位置。从此处开始应用重做日志,应用到on disk rba的位置。
on disk rba是磁盘中重做日志文件的最后一条重做记录的rba。
相关操作
select checkpoint_change# from v$database
alter system checkpoint
select dbms_flashback.get_system_change_number from dual;
select checkpoint_change# from v$datafile_header;
alter system switch logfile
select name,checkpoint_change# from v$datafile
select name,checkpoint_change# from v$datafile_header
select * from v$log;
alter system flush buffer_cache;
--实例恢复信息
select recovery_estimated_ios,actual_redo_blks ,target_redo_blks ,
target_mttr,estimated_mttr
from v$instance_recovery;