[oracle]Buffer Cache 原理

Buffer Cache

 

 

通常的数据访问和修改都需要通过 Buffer Cache 来完成。当一个进程需要访问数据时,首先需要确定数据在内存中是否存在,如果数据在 Buffer 中存在,则需要根据数据的状态来判断是否可以直接访问还是需要构造一致性读取;

如果数据在 Buffer 中不存在,则需要在 Buffer Cache 中寻找足够的空间以装载需要的数据,如果 Buffer Cache 中找不到足够的内存空间,则需要触发 DBWR 去写出脏数据,释放 Buffer 空间。

 Oracle通过3个list来对buffer进行管理,是LRU List + Dirty List+Auxiliary List

LRU 与 LRUW List

LRU List 用于维护内存中的 Buffer,按照 LRU 算法进行管理,数据库初始化时,所有的 Buffer 都被 Hash 到 LRU List 上管理。当需要从数据文件上读取数据时,首先要在 LRU List上寻找 Free 的 Buffer,然后读取数据到 Buffer Cache中;
当数据被修改之后,状态变为 Dirty,就可以被移动至 LRUW List,LRUW List 上的都是候选的可以被 DBWR 写出到数据文件的 Buffer,一个 Buffer 要么在 LRU List 上,要么在LRUW List 上存在,不能同时在这两个 List 上存在。

Checkpoint Queue

负责按照数据块的修改顺序记录数据块,同时将 RBA和数据块关联起来,这样在进行增量检查点时,数据库可以按照数据块修改的先后顺序将其写出,从而在进行恢复时,可以根据最后写出数据块及其相关的 RBA 开始进行快速恢复。在检查点触发时 DBWR 根据检查点队列执行写出,在其他条件触发时,DBWR 由 Dirty List 执行写出。检查点队列的内存在 Shared Pool 内存中分配:

 SQL> select BANNER_FULL from v$version;


BANNER_FULL
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Version 19.3.0.0.0
SQL>  select * from v$sgastat where name='Checkpoint queue';

POOL           NAME                   BYTES     CON_ID
-------------- -------------------------- ---------- ----------
shared pool    Checkpoint queue         2304          1
SQL> col name for a40
SQL> select name ,gets,misses from v$latch where name like '%checkpoint queue%';

NAME                           GETS    MISSES
---------------------------------------- ---------- ----------
active checkpoint queue latch               7683         1
checkpoint queue latch                 109773         9

Buffer Cache 的原理及使用

 

1.当一个 Server 进程需要读数据到 Buffer Cache 中时,首先必须判断该数据在 Buffer中是否存在(图中①所示过程),如果存在且可用,则获取该数据,同时根据 LRU算法增进其访问计数;如果 Buffer 中不存在该数据,则需要从数据文件上进行读取。
2.在读取数据之前,Server 进程需要扫描LRU List 寻找 Free 的 Buffer,扫描过程中Server 进程会把发现的所有已经被修改过的 Buffer 注册到 LRUW List (Checkpoint Queue)上(图中②所示过程),这些 Dirty Buffer 随后可以被写出到数据文件
--(Server process主动将Dirty buffer从LRU List移动到Dirty List)   --移动
3.如果 LRUW Queue(Checkpoing Queue) 超过了阀值,Server 进程就会通知 DBWn 去写出脏数据(图中③所示过程);这也是触发 DBWn 写的一个条件,这个阀值曾经到是 25%,也就是当 DirtyQueue 超过 25%满就会触发 DBWn 的写操作:
-- (Checkpoint Queue阀值到达25%,导致Server Proceess通知DBWn写赃数据)   --写
SQL> set linesize 300
SQL> select kvittag,kvitval,kvitdsc from x$kvit where kvittag='kcbldq';

KVITTAG                                 KVITVAL KVITDSC
---------------------------------------------------------------- ---------- ----------------------------------------------------------------
kcbldq                                     25 large dirty queue if kcbclw reaches this
如果 Server 进程扫描 LRU 超过一个阀值仍然不能找到足够的 Free Buffer,将停止寻找,转而通知 DBWn 去写出脏数据,释放内存空间。同样这个阀值可以从以上字典表中查询得到,这个数字是 40%,
也就是说当Server 进程扫描 LRU 超过 40%还没能找到足够的 Free Buffer 就会停止搜索,通知DBWn 执行写出,这是进程会处于 free buffer wait 等待:
--(如果Server process扫描了LRU超过一个阀值也没有找到足够的Free的buffer,这个时候也将会停止搜索free buffer的任务然后直接通知DBWn写脏数据来释放内存空间,当然这个Server process会处于free busy wait的等待事件.这个阀值是40%,同时这还是触发我们DBWn进程的一个条件)
SQL> select kvittag,kvitval,kvitdsc from x$kvit where kvittag='kcbfsp';

KVITTAG                                 KVITVAL KVITDSC
---------------------------------------------------------------- ---------- ----------------------------------------------------------------
kcbfsp                                     40 Max percentage of LRU list foreground can scan for free
同时我们知道,由于增量检查点的引入,DBWn 也会主动扫描 LRU List,将发现的Dirty Buffer 注册到 Dirty List 以及 Checkpoint Queue,这个扫᧿也受一个内部约束,在这里,这个比例是 25%:(19C没有找到这个参数)
SQL> select kvittag,kvitval,kvitdsc from x$kvit where kvittag='kcbdsp';

no rows selected
-- (DBWn主动扫描LRU的25%,依照结果从LRU中移动Dirty Buffer到Dirty List中) --移动
4.找到足够的 Buffer 之后,Server 进程就可以将 Buffer 从数据文件读入 Buffer Cache(图中④所示过程)
5.如果读取的 Block 不满足读一致性需求,则 Server 进程需要通过当前 Block 版本和回滚段构造前镜像返回给用户。

AUXILIARY List

当数据库初始化时,Buffer 首先存放在 LRU 的辅助 List 上(AUXILIARY RPL_LST),当被使用后移动到 LRU 主 List 上(MAIN RPL_LST),这样当用户进程搜索 Free Buffer 时就可以从 LRU-AUX List 开始,而 DBWR 搜索 Dirty Buffer时,则可以从 LRU-Main List 开始,从而ᨀ高了搜索效率和数据库性能。
 

 

通过以下命令转储Buffer Cache的内容,从而清晰的看到以上描述的数据结构:

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

 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/7:Level4+完整Buffer内存转储。

Level 8:Level4+显示users/waits信息。

Level 9:Level 5+显示users/waits信息。

Level 10:Level 6+显示users/waits信息。

 因为生产环节中转储文件可能非常大,建议设置初始化参数max_dump_file_size为UNLIMITED。

DUMP文件所在位置,可以通过V$DIAG_INFO获得,DUMP中的具体内容这里在详细介绍。

 

 

posted on 2020-05-05 10:39  InnoLeo  阅读(827)  评论(0编辑  收藏  举报