队列检查点和增量检查点
数据库在运行的过程中会不断地增加脏数据,如何将脏数据写入数据文件?
首先,第一种方式叫完全检查点,刷新buffer cache中的所有脏块,9i之后只有下面两种情况才会发生完全检查点:1、关闭数据库时;2、alter system checkpoint;然后,第二种方式叫增量检查点,这时就不得不提一下检查点队列了。检查点队列中的每一个节点,都指向一个脏块,包含三部份的信息:
1.对应脏块在buffer cache中的位置;
2.脏块对应的重做记录在日志文件中的位置;
3.前、后一个节点的地址;(双向链表)
DBWn进程是沿着检查点队列的顺序刷新脏块的,当然在刷新脏块的同时,检查点队列仍在不停地增大,后续脏块会链接到队列末尾。
检查点队列的头称为检查点位置:checkpoint position。每次DBWn进程更新完后,checkpoint position也会想应更新后移,CKPT进程每次完成检查点或者每隔三秒,会将checkpoint position记录进控制文件。
oracle在发生数据修改时,首先会在重做日志缓冲区(redo log buffer)生成重做条目,记录相应更改,当用户提交事务时,对应的重做信息就会由LGWR写入重做日志文件中,只有写入完成时,才会提示用户“修改已完成”。但此时缓存区的中数据是脏数据库,还没有完全写入磁盘中的datafile。所以当意外情况发生时,系统突然关闭会导致数据没有真正地修改,磁盘里还是旧的数据。这个时候数据库就会通过checkpoint来自动恢复。
重启数据库后,oracle会首先读取控制文件里的checkpoint position,然后对应到重做日志文件中的重做记录,重做日志文件就会自动从checkpoint position开始,根据重做记录中的重做数据,重现数据库的操作,一直进行到最后一条重做记录。这样只要重做文件日志是完整的,那么就不会有数据丢失。
但是,如果重做记录还存放在重做日志缓冲区中,并没有写入日志文件时发生的故障,则该记录将丢失。所以我们平时的操作如果没有提交,则该数据修改是无效的。没有提交的事务是不完整的,发生故障时会自动回退。
上述恢复是自动进行的,不需要DBA干涉,称为实例恢复。
介绍完检查点队列,下面说说增量检查点,所谓增量检查点,就是唤醒DBWn进程沿着检查点队列写脏块。做为DBA最主要的任务就是设置增量检查点。而我们所说的增量检查点的设置,其实就是设置增量检查点发生的频率而已,即DBWn的频率。
如果DBWn活动太频繁,则会影响数据库的整体性能;
如果DBWn活动太不频繁,则脏块堆积太多,也会影响数据库的整体性能;而且实例恢复所需要的时间会越长。
可以通过修改 fast_start_mttr_target 的值来设置DBWn的活动频率。如果设置不合理则会出现等待事件,DBWn写脏块的等待事件是db file parallel write。这个时候可能就需要调整增量检查点的频率了,如果太高则调底,如果太低则调高,当然不排除还有I/O性能方面的其它外因导致该等待事件。