暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

ORACLE内存调整的真相

IT界数据库架构师的漂泊人生 2020-12-14
925

  ORACLE如何分配内存,如何调整内存这个问题,对于新手来说确实困难。其实这个事情很简单的而已,只不过思维会被混乱了。尤其是网文一大堆的情况下。很少人去耐心看官方文档,尤其是英文文档!


为什么会发生这样的情况呢? 小仙我认为主要是东西方思维方式不一样而已。西方人是从局部到整体,而我们东方人喜欢大观局,战略层面上看。是从上往下看而已。

ORACLE 数据库是从8I 开始到如今的12C,自然前面还有7,6,5,4,3,2,1。以前的不重要,目前中国市场上运行的数据库版本是8I,9I,10G,11G,12C。用得最多的是11G,10G。从10G开始ORACLE公司开始用户友好化了,尤其是DBA管理工作开始自动化,在内存方面可以SGA自动管理,PGA也自动管理了。不用像9I那样,人工分配SGA里面的 SHARD_POOL,DATA_BUFFER,LOG_BUFFER等各种池的大小。

到了11G 来个MEMORY_TARGET 整个内存一起管理了。这样就方便ORACLE的使用,让ORACLE数据库得到更多的用户,尤其是开发人员来说,安装和使用特方便了。

12C 完善了MEMORY_TARGE  整个内存分配工作,完全交给ORACLE自己打理了。只要告诉它该占多少系统内存就行了。

是不是很爽啊??

对开发人员来说自然是,对DBA来说,要进步深入就难了,需要钻研下去。因为默认的并不很好!


第一 我们从12C 往回说

show parameter target

memory_max_target     big integer 800M

memory_target              big integer 800M

pga_aggregate_target     big integer 0

sga_target              big integer 0


show parameter max_size

sga_max_size     big integer 800M


SQL> show parameter pga

NAME                                 TYPE        VALUE

------------------------------------ ----------- ------------------------------

pga_aggregate_limit                  big integer 2G

pga_aggregate_target                 big integer 0


我画个图让大家清楚认识下内存分配法


第一个问题

memory_max_target   

memory_target             


这两个参数 设定ORACLE使用整个内存多少?  比如说32G物理内存,ORACLE使用800MB内存。

一般来说 使用80%。内存大的话比如256GB 可以达到90%。如果你上面还跑OEM,建议就降低些70%。


第二 MEMROY 管制

PGA和SGA 也就是说PGA+SGA不能超过MEMORY设定的大小。

PGA和SGA之间如何分配?

如果是OLTP 那么SGA多占些

如果是DSS 也就是统计类型比较多 PGA就多占些 OLAP,OLHP。


第三个问题 MAX_TARGET 和 TARGET 的区别


memory_max_target   

memory_target

sga_target

sga_max_size


MAX_SIZE 说明该参数最大上限,TARGET实际分配内存的目标值。自然目标值是不可以大于最大上限值的。


第四问题  PGA 是后来加强管控的。

 LIMIT和TARGET 跟第三个是一个道理的。

pga_aggregate_limit                    big integer 2G

pga_aggregate_target                 big integer 0


因此PGA_AGGREATE_limit+SGA_MAX_SIZE=MEMORY_MAX_TARGET

11G和10G PGA 不受控制,只受系统物理内存大小的限制。虽然有了PGA_AGGREGATE_TARGET 这个参数。它只是参考值,不起什么卵用的。在12C就得到了控制。


第五个问题 0值和非0值  也就是自动调整和手工调整的区别


0 值有时表示自动调整,有时表示非自动调整。

memory_max_target,memory_target 设置0值 就是放弃自动内存调整。

sga_target ,sga_max_size 设置0 表示接受自动调整。


困惑就在这里。什么AMM MMA? 复杂得很!我们不必纠结这些

类似下面的说法

 1:sga_target和pga_aggregate_target已经设置大小

如果Oracle中 已经设置了参数sga_target和pga_aggregate_target,

则这两个参数将各自被分配为最小值最为它们的目标值。

Memory_Target =SGA_TARGET+PGA_AGGREGATE_TARGET ,大小和  

          memory_max_size一致。 


2:sga_target 设置大小,pga_aggregate_target 没有设置大小 

          那么pga_aggregate_target初始化值=memory_target-sga_target 


3:sga_target 没有设置大小,pga_aggregate_target 设置大小 

          那么sga_target初始化值=memory_target-pga_aggregate_target 


 4:sga_target 和pga_aggregate_target 都没有设置大小Oracle 11g 

中对这种sga_target和pga_aggregate_target都没有设定大小的情况下,Oracle将对这两个值没有最小值和默认值。Oracle将根据数据库运行状况进行分配大小。


是不是很困惑啊? 我们不要让ORACLE默认设置,全自动管理,也不要退回手工分配和管理。采用我们中国人思维中庸之法。


就是把所有的0都改成有值。比如说 系统32GB内存

80%给ORACLE 那么 memory_max_size=32GB*0.8=25.6GB 约等于26GB

80%给SGA 26*0.8=21GB  PGA=5GB


NAME                                       TYPE              VALUE

------------------------------------ -----------          ------------------------------

memory_max_target big integer      26GB

memory_target         big integer      20GB

sga_target         big integer      15GB

sga_max_size         big integer      21GB

pga_aggregate_limit                big integer      5G

pga_aggregate_target             big integer      2G


这样设置就让ORACLE有个对各个内存有个基础值,又给ORACLE自动调整的空间,以及最高限制的值。其实我一般会设置TARGET跟MAX一样的值,不让PGA和SGA相互之间内存借用。

NAME                                       TYPE              VALUE

------------------------------------ -----------          ------------------------------

memory_max_target big integer      26GB

memory_target         big integer      26GB

sga_target         big integer      21GB

sga_max_size         big integer      21GB

pga_aggregate_limit                big integer      5G

pga_aggregate_target             big integer      5G


同理SGA内部 共享池和数据缓存池 也可以设定个基础值,也就是最小值,

SGA由如下组成

SGA=SHARD_POOL_SIZE+DB_CACHE_SIZE+RESULT_CACHE_SIZE

         +large pool+java pool+redo log buffer+streams_pool_size+db_Nk_cache_size


在这里SGA内部分配的话,我小仙一般设置个共享池和数据缓存的值

SHARD_POOL_SIZE   9GB

DB_CACHE_SIZE        9GB

java pool   =50MB

剩余的3GB 让SGA自动去分配,共享池如果不够用会向剩余的池挤压索要内存。

这里LOG BUFFER 在11G是不可以设定值的,在10G可以人工设定值。


共享池内部组成

shared_pool_reserved_size     big integer 9M

shared_pool_size              big integer 0

result_cache_max_result       integer  5

result_cache_max_size                big integer 2M

result_cache_mode              string  MANUAL

在这里 我们设置 shared_pool_reserved_size=1GB,记住RESULT_CACHE是在共享池里面分配内存



数据缓存池

SQL> show parameter cache

NAME     TYPE VALUE

------------------------------------ ----------- ------------------------------

db_16k_cache_size     big integer 0

db_2k_cache_size     big integer 0

db_32k_cache_size     big integer 52M

db_4k_cache_size     big integer 0

db_8k_cache_size     big integer 0

db_cache_size     big integer 0

db_keep_cache_size     big integer 0

db_recycle_cache_size      big integer 0


这里我们看到了好多CACHE,这在11G后开始使用的CACHE参数

10G以前是BUFFER 

buffer_pool_keep     string

buffer_pool_recycle     string

db_block_buffers     integer 0

log_buffer     integer 2199552


请注意这是一组

db_cache_size      big integer 0

db_keep_cache_size      big integer 0

db_recycle_cache_size      big integer 0

DB_CACHE_SIZE 是默认块的缓存区,一般是8K的块。



这里DB_CACHE_SIZE 不是指整个数据缓存区,而是默认缓存区,并且是默认块的缓冲区。其他KEEP RECYCLE DB_NK_CACHE_SIZE 直接从SGA分配内存

select * from V$sga_dynamic_components;

从这个视图上看到SGA可自动调节的内存组件。

也就是说上面KEEP RECYCLE DB_NK_CACHE_SIZE 分配内存的时候需要注意内存溢出

我用11G做的实验 设置了MEMORY_TARGET=MEMORY_MAX_TARTET=

memory_max_target     big integer       352M

memory_target              big integer       352M



SQL> alter system set db_keep_cache_size=50M scope=spfile;

系统已更改。

SQL> alter system set db_keep_cache_size=10M scope=spfile;

系统已更改。

SQL> alter system set db_recycle_cache_size=10M scope=spfile;

系统已更改。

SQL> alter system set db_32k_cache_size=10M scope=spfile;

系统已更改。



 alter system set db_16k_cache_size=100m scope=spfile;


SQL> alter system set db_4k_cache_size=10M scope=spfile;

ORACLE 例程已经关闭。

SQL> startup nomount

ORA-00838: Specified value of MEMORY_TARGET is too small, needs to be at least 452M


我本来设置了SGA_MAX_SIZE=0,SGA_TARTGE=0 自己不断地自我调高。 

看来11G 无法回到10G,9I的时代了。



文章转载自IT界数据库架构师的漂泊人生,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论