checkpoint queue和lruw链表在功能上的差异


以前一直存在的一个疑问:

为什么Oracle要搞出两个脏列表:一个Checkpoint Queue,一个Lruw

现在可以给出一个阶段性的回答:

两个链表设计的目的是不一样的,Checkpoint Queue按照数据块第一次被修改的先后时间排序(数据块只要变脏,肯定在这个链表上),Dbwr沿着Checkpoint Queue写脏数据,Oracle希望越早修改的块,会越早被写出。有利于减少恢复时间。但是有一点非常重要,这些块被写到磁盘后,1)是不会改变这个块在Lru链表里的位置的 2)这个块依然存在在内存里(很多人有误解,认为写出脏快后,这个块就不在内存里了)。而Lruw链表不是这个目的,它的设计只是为了腾出点空间来,让后面发生物理读的块或者需要构造CR的块可以在Buffer Cache里有地方,既然是为了腾出空间,那么就要有块被牺牲掉挪出空间来,一般是Tch小于2,CR块,全表扫描的块会被牺牲重用。在系统急需大量空闲块的时候,进程搜索LRU链表(包含Lru-Aux)过程中,如果发现了脏快(因为是从Lru冷端扫起,所以脏快的Tch也很小)那么就挪到Lruw链表上,然后再从Lruw写入到磁盘,最终这个Free的内存块就可以被挪到Lru-Aux上被重用了,当然这个块被写入磁盘后,需要把这个块从Checkpoint Queue摘除。一个块被修改变脏后,一定会进入到Checkpoint Queue队列,但是不会立即进入到Lruw队列,只有发生进程搜索LRU链表的时候,如果Tch数比较小,才会被放入Lruw链表然后被写入磁盘。并不象很多人认为的,Lru链表里就应是干净的块。其实Lru链表里的脏快应该是很多的,特别是如果你的脏块访问的比较频繁,Tch数比较高,是很难被刷到Lruw链表里的,它会一直呆在Lru连表里,当然这个脏块最终会从Checkpoint Queue写出变为干净的块,但是它在Lru链表里的位置不变,不会被刷出Buffer Cache。

上面的描述都做了简化,你可能说我描述有误。例如:Oracle从Lruw写脏快,比较详细的过程应该是,先扫描Lruw链表,然后把没有pin的数据块挪到Lruw-Aux上,然后以排他模式pin这个块,写入磁盘。我们只要能说明Checkpoint Queue和Lruw链表在设计目的上的差异就OK了。

相关内容