检查点队列
Oracle实例崩溃,恢复呢?Oracle数据库提交了的数据块,只是保证了已经保存到了Redo buffer中。如果oracle数据库崩溃了,需要前滚数据库日志来重构buffer cache中的脏块,从而保证已提交的事物不会丢失。前滚哪些数据文件呢?起点和终点分别在哪里?
ORACLE 8i之前,采取暴力的形式恢复。直接读取几乎所有的redo log日志文件,来前滚日志。这样,能达到目的,但是非常耗时,用户感知极差。而8i之后的版本,oracle引入检查点队列,完美解决了这个问题。
一、检查点队列相关概念
1、检查点队列链
检查点队列是将Buffer cache中的脏块,按照buffer第一次脏的顺序连接起来。这里隐藏了一个意思:检查点队列的第一个脏块,是Buffer cache中的第一个脏块,它之前脏的所有的buffer,都已经保存到dbf中了。
2、RBA
每次PGA对buffer进行修改,都会生成日志。PGA会将这个日志的地址写到buffer中。这个地址就叫RBA。RBA就是日志地址。
3、LRBA
LRBA对应Buffer第一次被修改对应的日志地址。
4、HRBA
HRBA对应buffer最近一次被修改对应的日志地址。
5、ON DISK RBA
ON DISK RBA是目前数据库(REDO LOG)所保存的最后一条日志的地址。
检查点队列也就是按照LRBA地址链接起来的。
二、Check point(检查点)
Check point进程主要用来记录检查点。
1、完全检查点
当oracle数据库关闭时,需要调用完全检查点进程。当完全检查点发生的时候,这个进程会触发dbwrite将所有的脏块写到磁盘。
2、增量检查点
当增量检查点发生的时候 ,CKPT将检查点队列的第一个块所对应的LRBA日志地址和时间点(SCN)记录到控制文件中。增量检查点每3秒发生一次。当检查点队列过长时,也会触发DBWR写入磁盘,从最早的开始写起,从而减小检查点队列。
三、ORACLE实例崩溃恢复(前滚)
当数据库崩溃时,oracle将取ON DISK RBA和增量检查点之间的REDO LOG日志来前滚,构造脏块。为什么能实现呢?
1、回滚的要求:
所有用户已经提交的还没有保存到DBF中的buffer,都需要构造出来,才能保证数据的一致性。因为数据库要求所有已经提交的,都不允许丢失。
2、实现过程
所有已经提交了的数据,都肯定已经记录到了redo log中了。而redo log中会存在以下几种数据:
(1)已经提交,DBF中的数据和redo log中的一致(崩溃时,buffer是clean的)。
(2)已经提交,DBF中的数据和redo log不一致(崩溃时,buffer是dirty的)。
(3)未提交,DBF中的数据和redo log不一致(崩溃时,buffer是dirty的)。
以上三种buffer,第三种的,是用户没有提交的,不需要恢复。第一种是已经提交的,dbf也已经入库的,也不需要恢复。
第二种,是用户已经提交了,但是数据只在redo log中记录了,还没来得及写入dbf中,数据库就崩溃了,这种是需要恢复的。
数据库崩溃后,重启时,会检测到异常崩溃,就会开始跑redo log日志。介绍检查点队列的时候,已经提过,检查点队列的第一个脏块,是buffer cache中第一个脏块。意思是第一个脏块之前的脏块,都已经写入到DBF中了。所以,Oracle重启,跑日志时,取检查点队列的第一个脏块对应的RBA到ON DISK RBA之间的数据,来构造已经提交但是没有保存到DBF中的脏块。