oracle学习笔记 检查点队列(checkpoint queue)

oracle学习笔记 检查点队列(checkpoint queue)

这节课讲一下oracle里面的一个难点也是一个重点叫检查点队列,
会讲到oracle里面内部的比较机理性的东西,对我们以后的学习非常有帮助。

大家可能听上去太理论了,
学oracle没有办法,有些基础的理论你还是要知道。

一)理论和原理

理论在各种字典中的解释有:

对自然界、人类社会的系统化的见解和主张。

可用于相对广泛的情况下的系统组织的知识,
尤其指一系列假设,已被接受的定理以及用于分析、预测或解释自然或专门现象行为的程序规则。

指导行为或帮助理解或判断的信条。

理论的英文

theory指”已经过试验及证实的理论, 作为解释大多数事实或现象等的总的原则”

hypothesis指”设想而未经证实的理论, 以后可能为人们认可, 或作为实验的指南”

这都是关于理论的解释

总的来说它是系统化的知识,是先辈在实践中的总结,对学习来说它是我们学习知识最有效的捷径。
但同时也要看到它是人们的总结,所以理论也可能存在疏漏。

另一个概念原理在字典中的解释:

指某一领域、部门或学科中认为具有普遍意义的基本定律或科学道理。

自然科学和社会科学中具有普遍意义的基本规律。
是在大量观察、实践的基础上,经过归纳、概括而得出的。既能指导实践,又必须经受实践的检验。
科学的原理以大量的实践为基础,故其正确性为能被实验所检验与确定,
从科学的原理出发,可以推衍出各种具体的定理、命题等,从而对进一步实践起指导作用。

原理是对规律的诠释。如:科学原理就是对自然规律的诠释

这些是人们对理论和原理在大方面的解释。

但毋庸置疑理论有正确的和错误的,
而原理是理论中最可信的一部分,也是理论中人们最愿意使用的部分。

使用理论这里说说使用原理就可以了!

现实的说对我们个体来讲那些抽象的理论未必有用,
有意义的都是我们从自身出发怎么来使用它们!

首先原理是人推论出来的,所以它不一定正确。
这点从历史的发展中的事件可以看出,
有的原理被使用了上千年,最终才发现它是错误的。
比较突出的理论如:地球处于宇宙的中心还是太阳处于宇宙的中心。

其次我们每个个体在实践中都在使用属于自己的原理。
人们觉的自己已经知道了原理自己就在使用它,实际情况并非如此。
不管自己知道或不知道,正确或不正确,以及是否存在人们公认的关于这方面的原理,
一个人在行动时使用的却是属于自己的原理。
就是说做每件事都会有很多截然相反的或不一样的原理,
你使用的可能并不是你认为正确的或你想使用的或者你使用的什么原理自己并不知道。

再者有时原理的正确性是因人而异的。
一个人使用它的结果可能是正确的,换个人就未必了。
所以最好不要简单套用别人的原理。

对计算机的应用,
也需要计算机理论,也需要计算机原理。
我们当然要学习它,因为它们是我们深入计算机的途径,
当然它们也是人们在使用计算机的实践中推论出来的。
我们接触到的计算机理论有对每个人都正确的原理,
当然也有些理论或原理并没有经过实践和时间的考验,正确与否还未确定,
这点在新出现的理论尤其明显,
很多正确性还有待考虑的情况下,已被广泛使用。

至于怎么处理和使用计算机知识中的原理,和其它方面的所有原理一样,
自己努力去选择吧!

不了解oracle的理论你只是对oracle一知半解,
很多知识只有知道了赋予它的理论才能理解,
这里就顾不了理论的正确性了,因为你不懂理论,你看不懂它!

这节课讲的内容非常重要一定要引起大家的重视

二)buffercache中的链

数据库实例有buffercache,
buffercache里面有很多buffer。

buffercache里面单独有一块内存区域用来记录,
有很多链是chain。

如:
LRU链least recent use最近最少使用,LRU上链的是干净块。

LRUW链Least Recently Used Write,也叫做dirty list,是脏数据块链表。

LRU链是将干净块将可用块给它串起来,
将来到从buffercache里面找可用块的时候就找LRU链。

同样的LRUW它链的是脏块给链起来,
将来我DBWR要将脏块写到磁盘上的时候就访问LRUW这个链。

我们之所以把块链起来,
就是为了组织和管理这些块,
为了将来从这个链上找相应的块。

不同的链有不同的功能。

oracle buffercache里面还有一种链叫检查点队列链,
checkpoint query链。
首先来讲它是个链一根链,
这个链上链的是buffer,链的是块。

LRU链的是干净的,
按照数据块访问的频率,
也就是说分数据块的冷热来链的。

buffercache里面还有一个CBC链cache buffer chain ,
CBC是按照地址链起来的。

检查点队列这个链,
首先来讲它链起来的是脏块,
也就是说我们的脏块不仅仅挂在LRUW链上,
还挂在检查点队列这个链上。

脏块挂在LRUW上是按照这个块的访问频率冷热顺序挂的,
这个块是个脏块但是它不怎么经常被访问就挂在这个链的冷端,
这个块是脏块它经常被访问那么就挂在LRUW的热端,
冷端的脏块会被率先写入到磁盘上成为干净块,
因为它是脏块,但是它不怎么经常被访问,
这时候DBWR会优先把它写到磁盘上,
一旦写到磁盘上它就是干净块了,成了干净块了它就挂在LRU上,
就可以被重复使用被覆盖。

这也符合我们buffercache的一个使用原理,
不怎么使用的块我们可以把它冲刷掉,
经常被访问的块我们希望尽量长时间的缓存在cache里面,
所以有LRU和LRUW它有各自的用途。

检查点队列它链的是脏块,
它按照这个块第一次脏的时间链起来的。

假设我现在有四个脏块。

第一个脏块是十点零一分的时候脏的,
第二个脏块是零二,
第三个脏块是零三,
第四个脏块是零四分脏的。

第一次脏的时间分别是:
01分02分03分04分

在05分的时候,
第一个脏块又被脏了一次。
在06分的时候,
第二个脏块又被脏了。
在07分的时候,
第四个脏块又被脏了。
在08分的时候,
第三个脏块被脏了。
这有可能!

检查点队列这个队列是按照块第一次脏的时间给它挂起来的。

第一个块第一次脏是01分,
挂在最上面。
第二个脏块挂在第二个位置,
第三个脏块挂在第三个位置,
第四个脏块挂在第四个位置,
这四个脏块按照这个块第一次脏的时间点给挂在链上的。

在05分的时候,
比如举例讲一号块在05分的时候被脏了又被脏了一次,
这个时候05分比最下面的04分的时间要晚,
这个块也不会挂在04分的后面,
因为我们是按照它第一次脏的时间点挂起来的。

所以要先记住,
第一个检查点队列上面对应的块是脏块,
第二个它是按照这个脏块第一次脏的时间点挂起来的。

先理解先记住这两个点,
记住以后我们看。

LRUW是按照冷热将脏块链起来,
它主要指导DBWR按照冷热哪些该写哪些不该写。

三)RBA和检查点队列

检查点队列按照这种方式链起来的意义。

检查点队列上面链的是脏块,
按照第一次脏的时间点给串起来的一系列脏块。

1)脏块中的RBA

在链上有一系列的块按顺序挂在上面,
还有logbuffer,redolog。

讲几个东西,
一个叫RBA,
一个叫LRBA,
一个叫HRBA。

RBA是redo block address,
是日志的地址,日志块的地址叫RBA。

假设我们对一个数据块进行修改,
会产生日志,
日志有一个地址就是RBA地址。

修改一个数据块会产生一个日志,
就有一个地址,这个地址叫RBA地址,
我就在这个数据块里面记一下这个RBA地址。
将来这个块要恢复的时候,
它知道它的改变都有哪个地址,
RBA就是日志地址。

先来看一下RBA的构成:
它由3部分组成,4byte+4byte+2byte,byte是指字节。
分别为 logfile sequence number ,logfile block number,byte offset into the block 。
即所在redo文件的序列号,所在日志文件中的块号,以及距离块开始位置的偏移量。
RBA也可以说是redo byte address。

对每个脏块来讲有LRBA和HRBA,
LRBA就是这个脏块第一次被脏的地址的那个日志地址。
这个块第一次被脏的地址,
它对应着logbuffer日志中的一个地址,
这个数据块被脏了很多次,
被脏了第二次第三次第四次第五次被脏的时候,
假设最近一次是第五次被脏,
它也对应着一个地址叫HRBA地址。

也就是说LRBA和HRBA分别记录着,
这个数据块最早一次脏所对应的日志中的地址,
和最近一次脏所对应的日志中的地址。

这两个地址在日志中的中间的地址,
是描述了这个块的脏的过程。

所以说记住数据块里面有两个地址LRBA跟HRBA。

2)LRBA地址在检查点队列中的作用

这个时候我们反过来说,
检查点队列里面的数据块,
是按照第一次脏链起来的,
其实也可以这么来说,
它们是按照这个数据块的LRBA地址链起来的。

日志我们这么来描述更确切些。

我们不看logbuffer和redolog,
日志其实就是一行行的串起来的,
所有的日志都是这么串起来的,
日志就是一行行的。

检查点队列上每个数据块记录的LRBA,
是这个数据块第一次被脏的地址,
一个数据块的LRBA,
对应着日志中的一行的地址。

目前就是检查点队列的第一个脏块所对应的LRBA地址是日志中的其中一行,
检查点队列的所链的所有的脏块,
就是检查点队列的所有的脏块,
它们所对应的日志都在第一个脏块所对应的日志地址以下。

检查点队列将所有的脏块链起来,
第一个块是最早脏的,
它第一次脏的对应的日志是日志中的一行,
第一个块下面所有的脏块它们被脏的所对应的日志,
都在日志中的第一个脏块第一次脏的日志以下。

因为它是最早被脏的,
最早脏的日志在日志中的一个地方,
而日志是按照时间顺序记录着buffercache的变化历程,
也就是下面所有的日志,
也就是检查点队列的后面所有的数据块,
它们的脏所对应的日志,
都在那条日志的下面。

四)检查点进程和检查点

我们知道有一个CKPT进程叫检查点进程

执行命令

[root@redhat4 ~]# ps -ef|grep ora

结果中有一个进程

oracle    6628     1  0 13:15 ?        00:00:00 ora_ckpt_jiagulun

就是检查点进程

这个进程分两块有两种工作方式

第一种工作方式叫完全检查点

当完全检查点发生的时候,
CKPT进程会触发DBWR,
将所有的脏块写到磁盘上这叫完全检查点。

第二种方式是增量检查点

是当增量检查点发生的时候,
CKPT进程会将第一个脏块的第一个log地址,
将检查点队列的第一个脏块的所对应的LRBA地址,
将这个日志地址记录到控制文件中。

完全检查点发生,
最经典的是关闭数据库的时候。

这时oracle会发生一个完全检查点,
这时候CKPT会触发DBWR将所有的脏缓冲区写到磁盘上,
这样数据库是相对的干净的关闭了。

数据库正常运行的时候只有正常关闭的时候才会发生完全检查点,
所以一般数据库正常运行期间完全检查点几乎不发生,
它就会发生增量检查点。
oracle每隔3秒钟会发生一次增量检查点。

增量检查点发生的时候CKPT进程会将检查点队列的最早脏的数据块所对应的LRBA地址记录到控制文件中。
增量检查点是每隔三秒钟发生一次。

讲课有两种先告诉作用再剖析原理,
另外一种先剖析原理再告诉作用恍然大悟的感觉。

当增量检查点发生的时候它还会做一件事情,
它会检查到检查点队列,
如果他发现检查点队列上面链的这些脏块太多了,
同时它发现系统的IO不是很忙,
它会结合这两个因素去触发DBWR去缩短检查点队列,
缩短检查点队列就是将队列的上半部分一些脏块写到磁盘上。

DBWR写的时候有两种情况,
第一种情况
根据LRUW链根据冷热去写;
第二种情况
如果说check point query检查点队列太长了以后,
检查点队列checkpoint进程触发的时候也会适当的触发DBWR去将检查点队列最早脏的哪些块。
队列上的一系列块,部分的写到磁盘上,
这时候检查点队列就缩短了。

这是增量检查点会做的两件事情,
增量检查点主要做的事情是记录检查点队列最早脏的块对应的LRBA地址。

五)on disk rba

还有一个 on disk rba

我们执行一个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;

执行结果

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;  2    3

     CPDRT Low RBA              On disk RBA          CPODS            CPODT                     CPHBT
---------- -------------------- -------------------- ---------------- -------------------- ----------
        87 5.21988.0            5.22444.0            527629           04/18/2017 13:58:38   911687624
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0

8 rows selected.

CPDRT列是检查点队列中的脏块数目;
CPODS列是on disk rba的scn ;
CPODT列是on disk rba的时间戳 ;
CPHBT列是心跳。

其中CPDRT列是检查点队列中脏块的数目,
就是目前我的buffercache里面有87个脏块。
Low RBA列是LRBA地址是检查点队列中最早脏的块的最早的日志地址。

On disk RBA列是一个地址

我们知道日志在logbuffer里面有,
redolog里面也有。

logbuffer里面记录着很多日志,
现在redolog中的一个日志状态是current就是最新的。

然后logbuffer有个LGWR进程,
它每隔三秒钟会把logbuffer中的日志写到redolog中的状态是current的日志文件中。
或者commit的时候往redolog中写,
总之LGWR会频繁的将logbuffer中的日志写到current里面去。

我们把current日志拿出来,
on disk rba是current日志的最后一条日志的地址。
就是我们目前数据库里面的所保存的最后一条日志的地址,
logbuffer里面的很多日志还没有写到current里面去,
但是logbuffer里面写进来的最后一条日志叫on disk rba。

目前数据库里面的current redolog里面的所记录的最新的rba地址叫on disk rba。

On disk RBA比Low RBA更新一些,
Low RBA在On disk RBA的后面。

目前数据库所产生的日志,
全部用串行的方式表示出来,
最新的一些在buffer里面,
较早的一些在redolog里面。

地址从redolog到logbuffer里面是越来越新,
在redolog中的最后一条地址就是on disk rba,
因为它是目前redolog里面最新的,
就是on disk rba是最新的。

上面就是查询结果中的5.22444.0地址为On disk RBA。

检查点队列中第一个脏块的最早的一个redo地址,
是比on disk rba在redolog中更早的一个地址,
我们的这个系统里面最早脏这个块对应的日志已经写到redolog里面去了。
这是我们实际的这个情况。

从结果看

     CPDRT Low RBA              On disk RBA          CPODS            CPODT                     CPHBT
---------- -------------------- -------------------- ---------------- -------------------- ----------
        87 5.21988.0            5.22444.0            527629           04/18/2017 13:58:38   911687624

目前有87个脏块

我们现在执行一条命令

alter system flush buffer_cache

将所有的脏块给清到磁盘上

SQL> alter system flush buffer_cache;

System altered.

然后再查一下rba

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;  2    3

     CPDRT Low RBA              On disk RBA          CPODS            CPODT                     CPHBT
---------- -------------------- -------------------- ---------------- -------------------- ----------
         0 4294967295.429496729 5.30959.0            533161           04/18/2017 14:32:48   911688308
           5.65535

         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0
         0 0.0.0                0.0.0                0                                              0

8 rows selected.

我们发现CPDRT的值就是脏块的数量为0了,
因为刚才已经把所有的脏块给清过来了。

清完了以后,
CPDRT为零说明脏块没了,检查点队列为空了。
Low RBA的值是4294967295.4294967295.65535也就是是无穷大了就是空了。
4294967295是4个字节数字所表示的最大值,
65535是2个字节数字所表示的最大的值。
这时LRBA的值的三节 4字节+4字节+2字节,
每节中的每个字节中的每一位都被填充了1,
得到它能表示的最大的值用来表示无穷大。


2017年5月5日
  文字:韵筝

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值