在BUFFER CACHE中,oracle通过几个链表进行内存管理,最为人熟知的是LRU LIST与DIRTY LIST(WRITE LIST或CHECKPOINT QUENE),各个LIST上存放的是指向具体BUFFER的指针。

注:除LRU和DIRTY LIST这两个重要链表之外,BUFFER CACHE的管理还存在另外两个重要的数据结构:hash bucket和cache buffer chain。

具体的LRU算法不多说了,下面就BUFFER的原理及使用做个简单介绍:

1、当一个SERVER进程需要读数据到BUFFER CACHE中时,首先会判断BUFFER是否存在,如果存在且可用,则获取该数据,如果BUFFER中不存在该数据,则需要从数据文件中读取。

2、在读取数据之前,SERVER进程需要扫描LRU LIST需找FREE的BUFFER,扫描过程中SERVER进程会把发现的所有已经被修改过的BUFFER移动到CHECKPOINT QUENE上,这些DIRTY BUFFER随后可以被写出到数据文件中。

3、如果CHECKPOINT QUENE超过了阀值,SERVER进程就会通知DBWn去写出脏数据,这是触发DBWn写的一个条件,这个阀值是25%,也就是检查点队列超过25%时就会触发DBWn的写操作。

SQL> select kvittag,kvitval,kvitdsc from x$kvit
  2    where kvittag='kcbldq';

KVITTAG                                                             KVITVAL
---------------------------------------------------------------- ----------
KVITDSC
----------------------------------------------------------------
kcbldq                                                                   25
large dirty queue if kcbclw reaches this

如果SERVER进程扫描LRU超过一个阀值仍然不能找到足够的FREE BUFFER,将停止需找,转而通知DBWn去写出脏数据,释放内存空间。这个阀值是40%

SQL> select kvittag,kvitval,kvitdsc from x$kvit
  2   where kvittag='kcbfsp';

KVITTAG                                                             KVITVAL
---------------------------------------------------------------- ----------
KVITDSC
----------------------------------------------------------------
kcbfsp                                                                   40
Max percentage of LRU list foreground can scan for free

4、找到足够的BUFFER之后,SERVER进程就可以将数据从数据文件读入BUFFER CACHE中。

5、如果读取的BLOCK不满足读一致性需求,则SERVER进程需要通过当前BLOCK版本和回滚段构造前镜像返回给用户。

从ORACLE 8i开始LRU LIST和DIRTY LIST又分别增加了辅助LIST(AUXILIARY LIST),引入辅助LIST之后,当数据库初 始化时,BUFFER首先存放在LRU的辅助LIST上,当被使用后移动到LRU住LIST上(MAIN PRL_LIST),这样用户进程搜索FREE BUFFER时,就可以从LRU-AUX LIST开始,而DBWR搜索DIRTY BUFFER时,则可以从LRU-MAIN LIST开始,从而提高搜索效率和数据库性能。

可以通过如下命令转储BUFFER CACHE内容,从而清晰地看到以上描述的数据结构:

alter session set events 'immediate trace name buffers level n';

不同LEVEL转储的内容详细程度不同,此命令可用级别主要有1~10级,各级别含义如下:

LEVEL 1:仅包含BUFFER HEADERS信息。

LEVEL 2:包含BUFFER HEADERS和BUFFER概要信息转储。

LEVEL 3:包含BUFFER HEADERS和完整BUFFER内容转储。

LEVEL 4:LEVEL1 + LATCH转储 + LRU队列。

LEVEL 5:LEVEL4 + BUFFER概要信息转储。

LEVEL 6和LEVEL 7:LEVEL4 + 完整的BUFFER内容转储。

LEVEL 8:LEVEL4 + 显示users/waiters信息。

LEVEL 9:LEVEL5 + 显示users/waiters信息。

LEVEL 10:LEVEL6 + 显示users/waiters信息。

SQL> alter session set events 'immediate trace name buffers level 4';

会话已更改。

在跟踪文件中找到了我想要看到的:

MAIN RPL_LST Queue header (NEXT_DIRECTION)[24be8c70,24bf3a7c]
24BE8C1C=>247E7BF4=>247E7848=>247E7904=>247E7CB0=>247E79C0=>247E7D6C=>247E7A7C
247E7B38=>247E7E28=>24BE8CD8=>247F7F30=>247F7FEC=>24BE8290=>247E7EE4=>247E7FA0
247E805C=>247E8118=>247E81D4=>247E8290=>247E834C=>247E8408=>247E84C4=>247E8580
.........................
MAIN RPL_LST Queue header (PREV_DIRECTION)[24be8c70,24bf3a7c]
24BF3A28=>24BF3AE4=>24BF3BA0=>24BF3C5C=>24BF3D18=>24BF3DD4=>24BF3E90=>24BF3F4C
24BF4008=>24BF40C4=>24BF4A50=>25FF2ABC=>24BEAD28=>24BEBC94=>24BEC040=>24BEBEC8
24BEB480=>24BEB770=>257E778C=>257E7848=>257E7904=>257E7D6C=>277F947C=>277F976C
.........................
MAIN WRT_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN WRT_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY WRT_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY WRT_LST Queue header (PREV_DIRECTION)[NULL]
MAIN XOBJ_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN XOBJ_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY XOBJ_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY XOBJ_LST Queue header (PREV_DIRECTION)[NULL]
MAIN XRNG_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN XRNG_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY XRNG_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY XRNG_LST Queue header (PREV_DIRECTION)[NULL]
MAIN REQ_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN REQ_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY REQ_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY REQ_LST Queue header (PREV_DIRECTION)[NULL]

红色部分我们可以清晰的看到LRU主LIST的队列信息,很直观的链表。

CHAIN: 9636 LOC: 0x33a98bc4 HEAD: [0x2a3eaa00,0x2a3eaa00]
    BH (0x2a3ea984) file#: 1 rdba: 0x0040c0bf (1/49343) class: 1 ba: 0x2a14e000
      set: 9 pool 3 bsz: 8192 bsi: 0 sflg: 1 pwc: 0,28
      dbwrid: 0 obj: 37 objn: 37 tsn: 0 afn: 1 hint: f
      hash: [0x33a98bc4,0x33a98bc4] lru: [0x2b3ee0d8,0x2a3eb918]
      lru-flags: debug_dump
      ckptq: [NULL] fileq: [NULL] objq: [0x2b3ee0f0,0x2a3eb930]
      st: XCURRENT md: NULL tch: 1
      flags: only_sequential_access
      LRBA: [0x0.0.0] LSCN: [0x0.0] HSCN: [0xffff.ffffffff] HSUB: [65535]
      cr pin refcnt: 0 sh pin refcnt: 0
CHAIN: 9637 LOC: 0x33a98bcc HEAD: [NULL]
CHAIN: 9638 LOC: 0x33a98bd4 HEAD: [0x2aff7834,0x2aff7834]
    BH (0x2aff77b8) file#: 1 rdba: 0x00402754 (1/10068) class: 1 ba: 0x2af40000
      set: 10 pool 3 bsz: 8192 bsi: 0 sflg: 1 pwc: 0,23
      dbwrid: 1 obj: 18 objn: 18 tsn: 0 afn: 1 hint: f
      hash: [0x33a98bd4,0x33a98bd4] lru: [0x297ed540,0x2b3f2318]
      lru-flags: debug_dump hot_buffer
      ckptq: [NULL] fileq: [NULL] objq: [0x297ed558,0x2b3f1c90]
      st: XCURRENT md: NULL tch: 8
      flags:
      LRBA: [0x0.0.0] LSCN: [0x0.0] HSCN: [0xffff.ffffffff] HSUB: [65535]
      cr pin refcnt: 0 sh pin refcnt: 0
补贴一份cache buffer chains 和buffer header的trace

装载自passion_of_data http://space.itpub.net/25964700/viewspace-703109