Oracle的KEEP、RECYCLE和DEFAULT缓冲池按访问热度与生命周期分类管理数据块:KEEP池缓存小而热的表(如配置表),RECYCLE池加速大而冷的段淘汰,DEFAULT池处理其余对象;三者内存互斥,需显式设置db_keep_cache_size和db_recycle_cache_size参数(默认为0)才能启用,且各池拥有独立LRU链表与统计指标。

多个缓冲池对应不同访问模式的段对象
Oracle 的 KEEP、RECYCLE 和 DEFAULT 缓冲池不是为了“多开几个缓存”,而是把数据块按访问热度和生命周期分类管理。比如一张小配置表被反复查询,它在 KEEP 池里就不太可能被刷出;而一张超大日志表做全表扫描后,如果进 DEFAULT 池,可能挤走其他热数据——放进 RECYCLE 池则会更快老化淘汰。
db_keep_cache_size 和 db_recycle_cache_size 必须显式设置才生效
很多人以为只要把表指定到 KEEP 池,系统就会自动分配内存,其实不会。这两个参数默认为 0,不设就等于没启用对应池。执行以下语句才能真正启用:
ALTER SYSTEM SET db_keep_cache_size = 128M SCOPE=BOTH;
注意点:
-
db_keep_cache_size值必须是db_block_size的整数倍,否则启动报错ORA-02097: parameter cannot be modified because specified value is invalid - 设置后需重启实例或使用
SCOPE=MEMORY(动态生效),但SCOPE=BOTH更稳妥 -
DEFAULT池大小由db_cache_size控制,它和KEEP/RECYCLE是互斥占用关系:总 buffer cache =db_cache_size+db_keep_cache_size+db_recycle_cache_size+ 其他nk池
段对象绑定缓冲池后,行为受访问方式影响极大
把表指定到 KEEP 池(ALTER TABLE t STORAGE (BUFFER_POOL KEEP))只是“标记”,实际是否真能常驻,取决于怎么读它:
- 索引范围扫描或单行
WHERE查询:只加载涉及的块,KEEP池效果明显 - 全表扫描(尤其未加
/*+ FULL(t) */提示时):Oracle 可能绕过池策略,直接走DEFAULT池的批量读逻辑 - 并行查询:每个 PX 进程可能独立申请 buffer,
KEEP池若太小,反而引发free buffer waits - 大对象(LOB)段:即使指定了
KEEP,LOB 数据块仍可能进入DEFAULT池,除非显式用STORAGE (BUFFER_POOL KEEP)在 LOB 子句中重申
LRU 算法在各池中完全独立运行,但共享同一套底层机制
每个缓冲池都有自己的 LRU 链表、检查点队列和 latch(如 cache buffers lru chain),所以 KEEP 池高负载不会拖慢 RECYCLE 池的淘汰速度。但要注意:
- 所有池共用 DBWn 进程写脏块,若
RECYCLE池里有大量短命脏块,DBWn 写压力会上升 - 当
v$buffer_pool显示某个池的physical_reads异常高,说明该池命中率差,不是因为算法问题,而是池大小或对象选择不合理 - 别指望
RECYCLE池能“加速”大表扫描——它只是防止污染热数据,扫描本身 I/O 开销不变
真实调优中,最容易被忽略的是:绑定缓冲池只是起点,后续必须配合访问路径分析和命中率监控。比如 SELECT * FROM v$buffer_pool_statistics WHERE name = 'KEEP' 查看 physical_reads 和 db_block_gets 比值,再结合 AWR 中的 buffer cache hit ratio 分池统计,才能判断是不是真起了作用。











