备库sga设太大反而坏事,因adg核心任务仅为接收和应用redo,无需主库级sql解析与缓存,过大的sga挤占mrp0依赖的pga空间,导致apply卡顿、ora-04030或oom killer杀进程。
active data guard备库的sga不能按主库比例照搬,盲目调大反而拖慢日志应用速度,甚至引发ora-04030或oom killer杀进程。
为什么备库SGA设太大反而坏事
主库要扛SQL解析、缓存热点数据、执行DML、维护锁和事务状态;而ADG备库的核心任务只有两件:接收redo、apply redo。共享池(SHARED_POOL_SIZE)里几乎不缓存新SQL,数据库缓冲区(DB_CACHE_SIZE)也极少被读操作触发——除非开了只读报表负载。所以过大的SGA不仅浪费内存,还会挤占本该留给PGA的空间,而MRP0进程apply大事务时极度依赖PGA做排序/哈希/构建undo block。
常见错误现象包括:
-
MRP0进程长期卡在APPLYING_LOG但sequence#停滞 -
v$sgastat中free memory持续低于50MB - OS层面
ora_pmon被OOM killer干掉,但top看不出Oracle进程占多少%MEM(因为PGA是私有内存,ps aux看不到)
SGA_TARGET和各子组件怎么设才合理
关键原则:压缩SGA,保障PGA。物理内存为64GB的ADG备库,典型配置如下:
-
SGA_TARGET设为24GB~28GB(即37%~44%),绝不设到50%以上 -
DB_CACHE_SIZE保持默认或显式设为12G(足够应对偶发只读查询,但不过度预留) -
SHARED_POOL_SIZE显式设为2G~3G(够用即可,避免library cache争用和老化开销) -
LARGE_POOL_SIZE设为512M(MRP0使用large pool做redo buffer staging,太小会退化到shared pool争抢) - 禁用
MEMORY_TARGET——它会让Oracle在SGA/PGA间动态挪内存,而MRP0对PGA稳定性极其敏感
执行示例:
ALTER SYSTEM SET sga_target = 26G SCOPE=SPFILE; ALTER SYSTEM SET db_cache_size = 12G SCOPE=SPFILE; ALTER SYSTEM SET shared_pool_size = 2560M SCOPE=SPFILE; ALTER SYSTEM SET large_pool_size = 512M SCOPE=SPFILE; ALTER SYSTEM SET memory_target = 0 SCOPE=SPFILE;
改完参数后MRP0为啥还不用新配置
ADG备库的内存组件虽支持动态调整,但正在运行的MRP0进程不会自动reload PGA分配策略。必须手动中断并重启恢复进程,才能让新PGA_AGGREGATE_TARGET生效(注意:不是重启数据库)。
- 先确认参数已写入spfile:
SHOW PARAMETER sga_target、SHOW PARAMETER pga_aggregate_target - 再检查实际分配:
SELECT component, current_size/1024/1024 MB FROM v$memory_dynamic_components WHERE component IN ('SGA Target', 'PGA Aggregate Target'); - 最后强制MRP0重载:执行
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;,再立刻执行ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT;
这一步漏掉,90%的“调参无效”问题就出在这里——参数改了,但MRP0还在用旧的内存模型跑。
容易被忽略的RAC环境陷阱
RAC备库下,内存压力往往不对称:一个节点先出现WAIT_FOR_LOG卡顿,另一个看似正常,其实只是还没轮到它处理积压日志。不要只盯单节点v$sgastat,必须查gv$memory_dynamic_components全实例视图,并对比各节点的MRP0状态和sequence#推进速度。更隐蔽的是:如果用了Far Sync实例,它的SGA配置也要单独压低,否则可能成为传输链路上的瓶颈点。











