+++++buffer cache 深度解析( 七 )


3.2.3 LRUW链表管理
从前面我们已经知道语句读取数据块到 cache的过程 。那么我们必然会产生另外一个疑问,就是当使用DML等语句修改了 cache里的内存数据块以后的过程是怎样的?实际上,为了能够最有效、安全的完成将内存数据块写入数据文件的过程,提供了比读取数据块更为复杂的机制 。
我们已经知道LRUW表示脏数据块链表,该链表上的 指向的都是已经从LRU链表上摘下来、其对应的内存数据块里的内容已经被修改、但是还没有被写入数据文件的内存数据块 。在这些脏数据块在能够被重用之前,它们必须要被DBWR写入磁盘 。从8i以后,LRUW链表同样包含两个子链表:辅助LRUW链表和主LRUW链表 。那么LRUW链表是如何产生 的呢?又是如何对其进行管理的呢?
我们还是接着上面图五所示的例子来说明 。假设这个时候,前台用户发出DML语句,要求修改BH2所指向的内存数据块 。这时,按顺序发生下面的动作:
1) 会将BH2从辅助LRU链表上摘下,同时插入主LRU链表的中间,也就是插入BH1和BH4中间,同时增加BH2的touch的数量 。(与的效果一样, 都会使要查找的块从辅助链表上摘下,放入主LRU链表)
2) 将该BH2的标记设置为钉住(ping) 。(这个在语句中没有说明,不知道有没有,应该是没有的)
3) 更新BH2对应的内存数据块的内容 。
4) 更新完以后,取消钉住的标记(在主LRU列表上进行第一次更新) 。
5) 将BH2从主LRU链表转移到主LRUW链表上 。
6) 如果这个时候又有进程发出更新BH2所对应的内存数据块的内容,则BH2再次被钉住,更新,取消钉住(可以在主LRUW列表上继续更新) 。
7) DBWR启动以后,在扫描主LRUW链表时会将BH2转移到辅助LRUW链表上(必须转移到辅助LURW列表才能写入到磁盘) 。
8) DBWR将辅助LRUW链表上的BH2对应的数据块写入数据文件 。
9) 确认成功写入数据文件以后,将BH2从辅助LRUW链表上转移到辅助LRU链表上(返回到辅助LUR列表) 。
从上面的描述中,我们可以看到,主LRUW链表上包含的 要么是已经更新完了的数据块,要么是被钉住正在更新的数据块 。而当DBWR进程启动以后,它会扫描主LRUW链表,并跳过正在被钉住更新的 ,而将已经更新完了的 从主LRUW链表上摘除,并转移到辅助LRUW链表上去 。
扫描完主LRUW链表,或扫描的 的个数达到一定限度时,DBWR会转到辅助LRUW上,将辅助LRUW上面的 所对应的数据块写入数据文件 。所以说,对于辅助链表上的 来说,要么是正在等待被写入的;要么就是已经发出写入请求,正在写入而还没写完的 。这里要注意的是, 进入LRUW链表,是从尾端进入;而DBWR扫描LRUW链表时,则是从首端开始 。
顺带提一句,这里将主LRUW链表和辅助LRUW链表分开,主要就是为了提高DBWR在主LRUW链表上扫描的效率 。如果只有主LRUW链表而没有辅助LRUW链表的话,势必造成三种类型 交织在LRUW链表上:
1)正在被钉住更新的 ;
2)已经更新完,而正在等待被写入数据文件的 ;
3)已经发出写请求,正在写而尚未写完的。
在这种情况下,必然造成DBWR为了找到第二种类型的 而需要扫描不该扫描的第三种类型的。(把第三种已经发出写请求,但是还没有写完的BH放到了辅助LRUW列表里,避免了扫描第二种已经更新完成,等待被写入的的BH)
3.2.4 DBWR进程
我们已经知道DBWR进程负责将脏数据块写入磁盘 。它是一个非常重要的进程,在后台进程中的sid为2,在PMON进程启动以后随即启动 。
SQL> select c.sid,a.name,a.description2from v$bgprocess a ,v$process b , v$session c3where a.paddr=b.addr4and b.addr = c.paddr;SID NAMEDESCRIPTION---------- ----- -------------------------------------------1 PMONprocess cleanup2 DBW0db writer process 03 LGWRRedo etc.4 CKPTcheckpoint………………………………………………………………………………