ADG备库的DB_CACHE_SIZE多数场景无效,因重做应用绕过缓冲区直写数据文件;仅只读查询使用buffer cache,且需结合v$db_cache_advice和物理读类型判断真实需求。
adg(active data guard)备库的 db_cache_size 不能盲目调大,多数场景下它根本不起作用——因为 adg 默认以只读 + 应用重做模式运行,数据块不写入缓冲区,db_cache_size 只影响本地查询缓存,不参与重做应用。
ADG 中 DB_CACHE_SIZE 实际生效的两个前提
ADG 备库默认启用 STANDBY_FILE_MANAGEMENT=AUTO 和只读打开(OPEN READ ONLY WITH APPLY 或 READ ONLY),此时:
- 重做应用线程(MRP)绕过 buffer cache,直接将变更写入数据文件(即“direct write”),
DB_CACHE_SIZE对这部分完全无影响 - 只有用户发起的只读查询(如报表、ETL抽取)才会使用 buffer cache;若备库几乎无人查,增大
DB_CACHE_SIZE只是浪费内存 - 必须确认开启了
DB_CACHE_ADVICE=ON并观察v$db_cache_advice的建议值——但注意:该视图在 ADG 上仅反映查询负载下的预估,不代表重做应用路径
查真实缓存压力:别信 Buffer Cache Hit Ratio
ADG 上执行传统命中率计算会严重误导:
SELECT 1 - ((physical.value - direct.value - lobs.value) / logical.value) "Buffer Cache Hit Ratio" FROM v$sysstat physical, v$sysstat direct, v$sysstat lobs, v$sysstat logical WHERE physical.name = 'physical reads' AND direct.name = 'physical reads direct' AND lobs.name = 'physical reads direct (lob)' AND logical.name = 'session logical reads';
问题在于:physical reads direct 在 ADG 中占比极高(MRP 直写),导致分母虚高、命中率被拉低,但这和缓存大小无关。更应关注:
-
physical reads是否持续增长且非 direct —— 表明只读查询确实在触发物理读 -
free buffer waits> 0?说明 buffer cache 真有争用(罕见,除非并发查询极强) -
consistent gets与db block gets比例是否异常高?可能 SQL 未走索引,全表扫描压垮缓存
真正影响 ADG 性能的内存参数其实是这些
比起调 DB_CACHE_SIZE,以下参数对 ADG 更关键:
-
LOG_BUFFER:太小会导致频繁 log file sync,拖慢 MRP 应用速度;建议 ≥ 64M,但不超过 256M(避免日志缓冲区争用) -
SHARED_POOL_SIZE:MRP 解析重做记录、构建 undo/redo 元数据都依赖共享池;若出现ORA-4031或library cache lock等等待,优先加此值 -
PGA_AGGREGATE_TARGET:MRP 进程本身是服务器进程,排序、哈希等操作用 PGA;若v$pgastat中cache hit percentage -
_log_parallelism_max(隐含参数):控制 MRP 并行 worker 数量,影响重做应用吞吐,但需 DBA 权限且测试验证
如果真要调 DB_CACHE_SIZE,按这个步骤来
仅当确认备库承担大量只读查询负载,且 v$db_cache_advice 显示明显收益时才考虑:
- 先开顾问:
ALTER SYSTEM SET DB_CACHE_ADVICE=ON SCOPE=BOTH;,运行至少 30 分钟典型查询负载 - 查建议值:
SELECT size_for_estimate, ESTD_PHYSICAL_READS FROM v$db_cache_advice WHERE advice_status='ON' AND block_size=(SELECT value FROM v$parameter WHERE name='db_block_size'); - 选 ESTD_PHYSICAL_READS 下降最陡的拐点(如从 500M → 600M 时下降 30%,再加到 700M 仅降 2%,就停在 600M)
- 动态修改:
ALTER SYSTEM SET DB_CACHE_SIZE=600M SCOPE=BOTH;(注意:若启用了MEMORY_TARGET,该设置会被忽略) - 改完立刻查
gv$memory_dynamic_components确认实际分配值,尤其在 RAC ADG 环境中各节点是否一致
最常被忽略的一点:ADG 备库若配置了 INMEMORY_SIZE > 0,它会静态占用 SGA 内存,进一步挤压 DB_CACHE_SIZE 可用空间——调之前务必检查 inmemory_size 是否非零。











