接着,我们再来看跟
LRU LIST:
Buffers containing block images being used
LRU AUXILIARY LIST:
Buffers ready to be used for I/O or CR build,在实例启动的时候,当前实例的buffer cache中的所有buffer都会被链接到LRU AUXILIARY LIST中,当oracle要从datafile中读一个block到buffer cache中来的时候,首先就会去扫描LRU AUXILIARY LIST,如果此时LRU AUXILIARY LIST非空,则直接把从datafile中读到的那个block拷到LRU AUXILIARY LIST上那个buffer header所链接的buffer cache block中,同时把这个buffer header再挪到LRU LIST中;如果此时LRU AUXILIARY LIST为空,则表明当前没有free block,此时就需要去扫描LRU LIST。
WRITE LIST:
Dirty Buffers requiring I/O,当LRU AUXILIARY LIST为空的时候,oracle需要去扫描LRU LIST,当扫到一个block,发现它的Flag是dirty的时候,oracle会把这个block所对应的buffer header从LRU LIST移到WRITE LIST。
CHECKPOINT QUEUE LIST:
Dirty Buffers requiring I/O,当buffer cache中的block第一次变为dirty的时候,它首先一定会在LRU LIST中存在,并且其Flag会被标记为dirty。同时,oracle会把这个block添加到CHECKPOINT QUEUE LIST中。
WRITE AUXILIARY LIST:
Dirty Buffers with I/O in progress,当DBWR需要写dirty block的时候,oracle会把那些dirty block从WRITE LIST移到WRITE AUXILIARY LIST,然后开始写。写完了,会把已经写完的dirty block从CHECKPOINT QUEUE LIST中删掉,同时把这些block再从WRITE AUXILIARY LIST移到LRU AUXILIARY LIST。
简单总结一下,oracle中buffer cache管理最简单的流程就是:
oracle首先会去LRU LIST中找,看看要找的block是否已经缓存在buffer cache中,找到了就直接用;找不到就再去LRU AUXILIARY LIST中找free block,如果找到了(即LRU AUXILIARY LIST非空),就去datafile中把要读的那个block拷到LRU AUXILIARY LIST上那个buffer header所链接的buffer cache block中,同时把这个buffer header再挪到LRU LIST中;如果找不到(即此时LRU AUXILIARY LIST为空),则表明当前没有free block,此时就需要去扫描LRU LIST,因为要找一个buffer header来reuse。此时,在扫描LRU LIST的过程中,当扫到一个buffer header,且发现它的Flag是dirty的时候,oracle会把这个buffer header从LRU LIST移到WRITE LIST;当WRITE LIST达到一定的阀值,DBWR会写这些buffer header所指向的dirty block,当DBWR需要写dirty block的时候,oracle会把那些dirty block所对应的buffer header从WRITE LIST移到WRITE AUXILIARY LIST,然后开始写。写完了,会把已经写完的dirty block所对应的buffer header从CHECKPOINT QUEUE LIST中删掉,同时把这些dirty block所对应的buffer header再从WRITE AUXILIARY LIST移到LRU AUXILIARY LIST,如此循环往复,生生不息!