Oracle 进程之 增量检查点

来源:互联网 发布:为什么wifi网络不稳定 编辑:程序博客网 时间:2024/05/21 09:09
一、为什么要有检查点?
   被修改过的块,在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,这两项操作合一起被称为--增量检查

点。


下面的就是CKPT每3秒写进控制文件的信息
SQL> alter session set events 'immediate trace name controlf level 8';
会话已更改。
具体内容如下:
***************************************************************************
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:89
low cache rba 0x2ad.908.0)[检查点位置] on disk rba 0x2ad.d2f.0)[最后一条重做记录的rba]
on disk scn: 0x0000.00237745 03/02/2008 15:03:44[最后一条重做记录的scn]
resetlogs scn: 0x0000.0008297b 08/27/2007 09:51:58
heartbeat: 648318959[心跳] mount id: 1201288562
...
...
这里面的大多数信息可以通过x$kcccp中看到.
SQL> select CPDRT,CPLRBA_SEQ||'.'||CPLRBA_BNO||'.'||CPLRBA_BOF "Low
RBA",CPODR_SEQ||'.'||CPODR_BNO||'.'||CPODR_BOF "On disk RBA",CPODS,CPODT,CPHBT from x$kcccp;
     CPDRT Low RBA         On disk RBA     CPODS            CPODT                     CPHBT
---------- --------------- --------------- ---------------- -------------------- ----------
        35 686.124.0       686.220.0       2325376          03/02/2008 15:18:54   648319278
说明:
     CPDRT列是检查点队列中的脏块数目.
     CPODS列是on disk rba的scn
     CPODT列是on disk rba的时间戳
     CPHBT列是心跳


检查点位置是是个rba,他指向着重做日志文件中的某个重做记录.在此位置前的重做记录,其对应的信息已经被写进了数据文件,在此位置后的重做记录,所对应的是数据块,有可能还在内存中.如果发生了实例崩溃,只需要在日志文件中找到检查点位置,从此处开始应用所有的重做日志文件,就完成了前滚操作.实例崩溃后,再次启动数据库,oracle会到控制文件中读取low cache rba,这就是检查点位置.从此处开始应用重做信息,应用到on disk rba处.on disk rba是磁盘中重做日志文件的最后一条重做记录的rba.  如果某条命令的重做记录的rba高于on disk rba,那说明此重做记录还没有被写进日志文件中,崩溃发生时,他是不可能被恢复的.on disk rba是oracle前滚操作的终点.on disk 顾名思义 就是'在磁盘上'的意思.比这个更高的rba,都在log buffer中,还没有来的急被写进磁盘中的日志文件.所以是不能被用于恢复的.


下面假设一个实例恢复的例子:
Table表每行2000个字节,块大小8K,每块可容纳table3行,按如下发布7条更新命令:

Update table set name=low(name) where id=1; ------1RBA 692.2998.10
Update table set name=low(name) where id=2; ------1 RBA 692.3015.10
Update table set name=low(name) where id=4; ------2 RBA 692.3024.10
Update table set name=low(name) where id=7; ------3 RBA 692.3033.10
Update table set name=low(name) where id=3; ------1 RBA 692.3102.10
Update table set name=low(name) where id=10; ------4 RBA 692.3127.10
Update table set name=low(name) where id=13; ------5 RBA 692.3136.10

上面七条更新命令后,每块状态为:

1号块

2号块

3号块

4号块

5号块

Lrba692.2998.10Hrba692.3102.10Lrba692.3024.10Hrba692.3024.10Lrba692.3033.10Hrba692.3033.10Lrba692.3127.10Hrba692.3127.10Lrba692.3136.10Hrba692.3136.10

Lrba就是块首次变脏时的RBA,而Hrba,是最后一次改变块中信息,所对应的重做记录的RBA1号块外被修改两次,LrbaHrba不同。25号块只被修改一次,LrbaHrba相同。

相应的重做记录有:

RBA692.2998.10(第一条更新命令对应的重做记录)回滚段头重做信息回滚段块重做信息1号块第1行重做信息(下面的重做记录中省略具体的信息)RBA692.3015.10 (第二条更新命令对应的重做记录)RBA692.3024.10 (第三条更新命令对应的重做记录)RBA692.3033.10 (第四条更新命令对应的重做记录)RBA692.3102.10 (第五条更新命令对应的重做记录)RBA692.3127.10 (第六条更新命令对应的重做记录)RBA692.3136.10 (第七条更新命令对应的重做记录)


假如此时,1号块和2号块已经变得不脏,345号块仍是脏块,所有的脏块依Lrba顺序按列为检查点队列,其中检查点队列头(此处是3号块)的Lrba就是检查点位置,此处为692.3033.10。这个值被记录在控制文件中。如果发生了实例崩溃,Oracle将从控制文件中取出692.3033.10,到692号重做日志中,找到第3033块,从此处开始,应用所有的重做日志,直到重做日志文件的最未尾。而重做日志文件的最未尾重做记录的RBA,又叫On disk rba。从检查点位置处,应用重做记录到On disk rba处,这个过程就是前滚。

如下几个参数可以用来限制检查点队列的长度:


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废除了.


3,log_checkpoint_timeout


  该参数用于表示检查点位置和重做日志尾之间的时间间隔,以秒为单位,默认情况下是1800秒,这个参数实际上表示了脏块保持脏状态的最长时间.如果它被定为1800秒,没有脏块保持1800秒后,还是为脏.设log_checkpoint_timeout 为1800秒


0 0
原创粉丝点击