今天在生产的数据库中发现了一个报错。是关于内存的。记录一下:
WARNING: Granules of pga_aggregate_target %d cannot be more than memory_target (%d) - sga_target (%d) or
min_sga(%d)。
版本:
11.1.0.6及以后的版本
原因官方文档解释:
引发此警告消息的原因是MEMORY_TARGET/MEMORY_MAX_TARGET和SGA_MAX_SIZE/SGA_TARGET参数设置为或默认为最小值,并且参数值之间的差异小于所需的PGA_AGGREGATE_TARGET。在Oracle11g中,memory_target参数定义了Oracle可以使用的总内存量,它同时包含SGA和PGA区域。因此,如果将这些参数设置为与SGA_MAX_SIZE/SGA_TARGET参数相同,或者它们之间的差异太小,则这将使PGA没有可用的内存,因此会引发此警告消息。
在这里,我简单说一下oracle的自动内存管理机制(AMM:Automatic Memory Management),便于大家对这几个参数了解。
MEMORY_MAX_TARGET : oracle内存的最大值能达到的上限。非动态可调。如果没有指定,默认和memory_target等同。
MEMORY_TARGET:oracle内存的最大值。这个值表示oracle内存最高可用到的值,但是如果MEMORY_TARGET没有指定值,该值可动态调整,最高到MEMORY_MAX_TARGE。如果没有指定MEMORY_TARGET,而指定了MEMORY_MAX_TARGE,oracle重启后该值为0。
sga_max_size:sga最大值。
sga_target :为0,oracle则能完全自动管理。
PGA_AGGREGATE_TARGET:pga的自动管理配置,为0,oracle则能完全自动管理。
Oracle 9i引入pga_aggregate_target,可以自动对PGA进行调整;
Oracle 10g引入sga_target,可以自动对SGA进行调整;
Oracle 11g则对这两部分进行综合,引入memory_target,可以自动调整所有的内存,这就是新引入的自动内存管理特性。
下图是我司生产的配置:
sga_target 和 pga_aggregate_target 都没有设置大小 Oracle 11g中对这种 sga_target 和 pga_aggregate_target 都没有设定大小的情况下, Oracle 将对这两个值没有最小值和默认值。 Oracle 将根据数据库 运行状况进行分配大小。 但在数据库启动是会有一个固定比例来分配:
sga_target =memory_target *60%
pga_aggregate_target=memory_target *40%
原理也懂了,根据官方描述,问题也明白了,只是我们的配置没有问题,怎么也有这种告警呢?
下面说几个非常有用的视图,并附上语句。
select m.COMPONENT,m.OPER_TYPE,m.OPER_MODE,m.PARAMETER,m.INITIAL_SIZE/1024/1024/1024 初始值GB,
M.TARGET_SIZE/1024/1024/1024 目标值GB,m.FINAL_SIZE/1024/1024/1024 最终值GB,
TO_CHAR(M.START_TIME,'YYYY-MM-DD HH24:MI:SS') 开始时间,
TO_CHAR(M.END_TIME,'YYYY-MM-DD HH24:MI:SS') 结束时间
from V$MEMORY_RESIZE_OPS m
where m.COMPONENT in ('PGA Target','SGA Target');--包含最近完成的800 个内存大小调整请求的循环历史记录缓冲区
select MDC.COMPONENT,
mdc.CURRENT_SIZE/1024/1024/1024 当前大小GB,
MDC.MIN_SIZE/1024/1024/1024 最小值GB,
MDC.MAX_SIZE/1024/1024/1024 最大值GB,
MDC.OPER_COUNT,
MDC.LAST_OPER_TYPE,
MDC.LAST_OPER_MODE,
to_char(MDC.LAST_OPER_TIME,'yyyy-mm-dd hh24:mi:ss') 最后操作时间,
MDC.GRANULE_SIZE/1024/1024 调整颗粒MB
FROM V$MEMORY_DYNAMIC_COMPONENTS MDC;--包含所有内存组件的当前状态
select * from V$MEMORY_TARGET_ADVICE;--提供针对MEMORY_TARGET 初始化参数的优化建议
接下来在简单说下内存中sga和pga的内容吧:
sga:包含实例的数据和控制信息,包含如下内存结构:
1)Database buffer cache:缓存了从磁盘上检索的数据块。
2)Redo log buffer:缓存了写到磁盘之前的重做信息。
3)Shared pool:缓存了各用户间可共享的各种结构。
4)Large pool:一个可选的区域,用来缓存大的I/O请求,以支持并行查询、共享服务器模式以及某些备份操作。
5)Java pool:保存java虚拟机中特定会话的数据与java代码。
6)Streams pool:由Oracle streams使用。
7)Keep buffer cache:保存buffer cache中存储的数据,使其尽时间可能长。
8)Recycle buffer cache:保存buffer cache中即将过期的数据。
9)nK block size buffer:为与数据库默认数据块大小不同的数据块提供缓存。用来支持表空间传输。
database buffer cache, shared pool, large pool, streams pool与Java pool根据当前数据库状态,自动调整;
keep buffer cache,recycle buffer cache,nK block size buffer可以在不关闭实例情况下,动态修改。
PGA 每个服务进程私有的内存区域,包含如下结构:
1)Private SQL area:包含绑定信息、运行时的内存结构。每个发出sql语句的会话,都有一个private SQL area(私有SQL区)
2)Session memory:为保存会话中的变量以及其他与会话相关的信息,而分配的内存区。
那结合业务,问题基本确定,可能是kettle抽数造成的,占用了较多的PGA,当oracle需要SGA 的时候,这些target值的比例完全不对而产生的告警。
调整:
修改为ASMM管理模式,在amm模式下,内存的抖动一直是个问题,而对于某些业务来说,就像我上面的截图,已经有点鸠占鹊巢了。虽然oracle19c开始已经推出全自愈的数据库,至少在11g下,建议针对具体的业务具体调整。
ASMM方式:设置memory的参数全部为0;设置sga和pag的大小值。
命令方式:
alter system set memory_target=0 scope=both;