您的位置:首页 > 其它

SGA_MAX_SIZE与SGA_TARGET

2011-03-01 10:59 246 查看
Oracle
的SGA
包括以下几个部分,可以通过show sga
命令或者是通过查看v$sga
视图来查看SGA
的大概组成:

17:39:48 SQL> show sga

Total System Global Area 1048576000 bytes

Fixed Size
1223392 bytes

Variable Size
847250720 bytes

Database Buffers
192937984 bytes

Redo Buffers
7163904 bytes

17:42:05 SQL> select * from v$sga;

NAME
VALUE

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

Fixed Size
1223392.00

Variable Size
847250720.00

Database Buffers
192937984.00

Redo Buffers
7163904.00

从上面可以大致的看到sga
包括一个固定区,一个可变区,一个数据库缓存和一个redo
缓存。这些是比较笼统的信息,具体的SGA
是由以下几个部分组成的:

-
数据缓冲(Buffer Cache


-
共享池(Shared Pool


-
大池(Large Pool


- Java
池(Java Pool


-
流池(Streams Pool --- 10g
以后才有)

-
重做日志缓冲(Redo Log Buffer


-
其他buffer caches
(如KEEP, RECYCLE, and other block sizes cache
等)

- Fixed SGA and other internal allocations


其中,Shared Pool
、Java Pool
、Large Pool
和Streams Pool
这几块内存区的大小是相应系统参数设置而改变的,所以有通称为可变SGA
(Variable SGA
)。最后一个fixed sga
部分,一般是在实例启动以后就固定在sga
中了,是不会发生变化的,这个部分的区域一般小于100k


理解了SGA
的组成以后,下面就来解释一下有关设置SGA
大小的两个参数SGA_MAX_SIZE
和SGA_TARGET
的含义。

SGA_MAX_SIZE


这个参数顾名思义,它用来控制SGA
使用虚拟内存
的最大大小,这里的虚拟内存的含义可能会有所模糊,先可以这样理解,就是Oracle
所能在内存中给SGA
分配的最大大小


现在来解释一下我这里“虚拟内存”的含义,确切的应该这样说:实际内存和虚拟内存。我们知道当OS
中实际内存不够使用的时候,OS
就会去使用虚拟内存。oracle
是运行与os
之上的一个系统软件,它也是一个程序,它所请求os
给它多少内存用来作为其sga
(比方说Oracle
申请500M
内存用作SGA
,即SGA_MAX_SIZE=500M
),os
一般是不会在oracle
启动的时候就给它全部的实际内存,而可能只给200M
。随着程序的运行,Oracle
不断的需要内存,而假设计算机的所有实际内存只有500M
,那么很肯定的是OS
不可能把全部500M
实际内存分配给oracle
的sga
,可能也最多就给了350M
,剩下的150M
使用虚拟内存。Oracle
的SGA
达到500M
的时候(即达到SGA_MAX_SIZE
指定的大小),实际上这个sga
由350M
实际内存和150M
的虚拟内存组成,如果这个时候Oracle
想继续申请内存给SGA
使用,那么OS
是不会再给其分配内存,因为它已经达到了SGA_MAX_SIZE
的最大值。这个例子,虽然比较极端,即使OS
实际上比方说有1G
内存,Oracle
的SGA
也未必全部由实际内存组成,可能是由400M
实际内存和100M
的虚拟内存组成,这是由操作系统的内存管理策略决定的。此时,很显然有个问题,假设我的机器物理内存(实际内存)足够多,如何让Oracle
所申请的SGA
内存全部在物理内存中呢,因为假设使用了虚拟内存,必定会带来额外的PAGE IN/PAGE OUT
的I/O
操作,这是很不合算的。这个问题其实就是在物理内存中固定SGA
的问题,这要涉及到另外两个参数LOCK_SGA
和PRE_PAGE_SGA
以及具体操作系统是否支持内存锁定的问题了,对此在这不予讨论。因此可以简洁的这样说:当实例启动后,各个内存区只分配实例所需要的最小大小,在随后的运行过程中,再根据需要扩展他们的大小,而他们的总和大小受到了SGA_MAX_SIZE
的限制。

根据前面的SGA
的组成介绍,我们很容易得到一个计算SGA
的实际值的公式,如下:

SGA
实际大小 = DB_CACHE_SIZE

+ DB_KEEP_CACHE_SIZE

+ DB_RECYCLE_CACHE_SIZE

+ DB_nk_CACHE_SIZE

+ SHARED_POOL_SIZE

+ LARGE_POOL_SIZE

+ JAVA_POOL_SIZE

+ STREAMS_POOL_SIZE
(10g
中的新内存池)

+ LOG_BUFFERS+11K(Redo Log Buffer
的保护页)

+ 1MB

+ 16M(SGA
内部内存消耗,适合于9i
及之前版本)

而SGA_MAX_SIZE
就是它的各个部分内存区都达到定义的最大值的时候的大小之和。修改SGA_MAX_SIZE
的大小,必须要重新启动数据库实例。

这样就可能出现这样的一种情况,在spfile
中,SGA
各个内存区设置大小总和大于SGA_MAX_SIZE
。这时,oracle
会如下处理:当实例再次启动时,如果发现SGA
各个内存总和大于SGA_MAX_SIZE
,它会将SGA_MAX_SIZE
的值修改为SGA
各个内存区总和的值。

SGA_TARGET


在Oracle 10g
中引入了一个非常重要的参数:SGA_TARGET
,这也是Oracle 10g
的一个新特性。

在10g
之前,SGA
的各个内存区的大小都需要通过各自的参数指定,并且都无法超过参数指定大小的值,尽管他们之和可能并没有达到SGA
的最大限制。此外,一旦分配后,各个区的内存只能给本区使用,相互之间是不能共享的。拿SGA
中两个最重要的内存区Buffer Cache
和Shared Pool
来说,它们两个对实例的性能影响最大,但是就有这样的矛盾存在:在内存资源有限的情况下,某些时候数据被cache
的需求非常大,为了提高buffer hit
,就需要增加Buffer Cache
,但由于SGA
有限,只能从其他区“抢”过来——如缩小Shared Pool
,增加Buffer Cache
;而有时又有大块的PLSQL
代码被解析驻入内存中,导致Shared Pool
不足,甚至出现4031
错误,又需要扩大Shared Pool
,这时可能又需要人为干预,从Buffer Cache
中将内存夺回来。

有了这个新的特性后,SGA
中的这种内存矛盾就迎刃而解了。这一特性被称为自动共享内存管理(Automatic Shared Memory Management ASMM
),控制这一特性的,就仅仅是这个参数SGA_TARGE
。设置这个参数后,你就不需要为每个内存区来指定大小了。SGA_TARGET
指定了SGA
可以使用的最大内存大小,而SGA
中各个内存的大小由Oracle
自行控制,不需要人为指定。Oracle
可以随时调节各个区域的大小,使之达到系统性能最佳状态的个最合理大小,并且控制他们之和在SGA_TARGET
指定的值之内。一旦给SGA_TARGET
指定值后(默认为0
,即没有启动ASMM
),就自动启动了ASMM
特性。

当启用Oracle
的ASMM
新特性以后,也不是SGA
的所有区的大小都开始动态起来,只有以下的这些区的内存大小动态共享起来:

* Buffer cache (DB_CACHE_SIZE)

* Shared pool (SHARED_POOL_SIZE)

* Large pool (LARGE_POOL_SIZE)

* Java pool (JAVA_POOL_SIZE)

* Streams pool (STREAMS_POOL_SIZE)

而SGA
中的其他区域的内存大小仍然是固定不共享的。

SGA_TARGET
参数带来了ASMM
的新特性,但是它的含义和SGA_MAX_SIZE
的一样,也表示SGA
最大的大小,于是它也就有了一个限制,那就是它的大小不能大于SGA_MAX_SIZE
的大小。请看:

18:29:32 SQL> show parameter sga

NAME
TYPE
VALUE

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

lock_sga
boolean
FALSE

pre_page_sga
boolean
FALSE

sga_max_size
big integer
1000M

sga_target
big integer
300M

18:29:36 SQL> alter system set sga_target=1100m;

alter system set sga_target=1100m

*

ERROR at line 1:

ORA-02097: parameter cannot be modified because specified value is invalid

ORA-00823: Specified value of sga_target greater than sga_max_size

从上面这个例子的错误报告中,我们还可以发现一点那就是SGA_TARGET
是可以在本实例内动态修改的,请看:

18:29:46 SQL> alter system set sga_target=500m;

System altered.

问题又出现了,既然SGA_TARGET
除了带来这个ASMM
新特性以及可动态修改以外,它的含义和SGA_MAX_SIZE
是一样的,即表示Oracle
所能使用的SGA
的最大大小。那么这里就有两个最大,虽然有限制SGA_TARGET
不能大于SGA_MAX_SIZE
大小,可是并没有限制它比它小啊。因此,当SGA_TARGET
小于SGA_MAX_SIZE
的时候,这两个最大,Oracle
该听谁的呢?前面的例子,我们知道SGA_TARGET=500M < SGA_MAX_SIZE=1000M
,那么继续试验,请看:

18:31:04 SQL> startup force

ORACLE instance started.

Total System Global Area 1048576000 bytes

Fixed Size
1223392 bytes

Variable Size
637535520 bytes

Database Buffers
402653184 bytes

Redo Buffers
7163904 bytes

Database mounted.

Database opened.

18:35:17 SQL> show parameter sga

NAME
TYPE
VALUE

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

lock_sga
boolean
FALSE

pre_page_sga
boolean
FALSE

sga_max_size
big integer
1000M

sga_target
big integer
500M

18:35:31 SQL> select * from v$version;

BANNER

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

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod

PL/SQL Release 10.2.0.1.0 - Production

CORE
10.2.0.1.0
Production

TNS for Linux: Version 10.2.0.1.0 - Production

NLSRTL Version 10.2.0.1.0 - Production

从这个版本来看,这里似乎并没有发生改变。那说明是什么问题呢?很显然,SGA_MAX_SIZE
仍然表示SGA
的大小的上限值,而SGA_TARGET
是SGA
的所有组件的大小的最大值之和,即当SGA_TARGET< SGA_MAX_SIZE
的时候,oracle
就会忽略SGA_MAX_SIZE
的值,SGA_TARGET
也就成了SGA
的在此实例中的上限制,它能动态改变大小,但是不能够大于SGA_MAX_SIZE
的值。

有人曾经做过试验,在某些版本中(可能在我的版本之后的版本),当SGA_TARGET < SGA_MAX_SIZE
时,实例重启以后SGA_MAX_SIZE
就变成SGA_TARGET
的大小了。

那么这就说明SGA_TARGET
的处理,在不同的版本中是不一样的。那么在最新的11g
中是什么样子的呢?下面来看看,也让我们猜测一下oracle
对SGA_TARGET
的处理方向:

18:52:15 SQL> show parameter sga

NAME
TYPE
VALUE

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

lock_sga
boolean
FALSE

pre_page_sga
boolean
FALSE

sga_max_size
big integer 276M

sga_target
big integer 0

18:52:31 SQL> alter system set sga_target=200m;

System altered.

18:52:38 SQL> show parameter sga

NAME

TYPE
VALUE

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

lock_sga
boolean
FALSE

pre_page_sga
boolean
FALSE

sga_max_size

big integer 276M

sga_target
big integer 276M

18:52:43 SQL> alter system set sga_target=202M;

alter system set sga_target=202M

*

ERROR at line 1:

ORA-02097: parameter cannot be modified because specified value is invalid

ORA-00827: could not shrink
sga_target to specified value

18:53:11 SQL> alter system set sga_target=322M;

alter system set sga_target=322M

*

ERROR at line 1:

ORA-02097: parameter cannot be modified because specified value is invalid

ORA-00823: Specified value of sga_target greater than sga_max_size

18:57:50 SQL> select * from v$version;

BANNER

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

Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production

PL/SQL Release 11.1.0.6.0 - Production

CORE
11.1.0.6.0
Production

TNS for Linux: Version 11.1.0.6.0 - Production

NLSRTL Version 11.1.0.6.0 - Production

从试验中很显然的看到,在11g
中,这个SGA_TARGET
只能设置是等于SGA_MAX_SIZE
的大小了,设置比它小,oracle
会自动帮你调整,设置比它大,那还是出错。现在可以自己想想,oracle
对SGA_TARGET
的大小处理在往正确的简单的方向前进中。

SGA_TARGET
带来一个重要的好处就是,能使SGA
的利用率达到最佳,从而节省内存成本。因为ASMM
启动后,Oracle
会自动根据需要调整各个区域的大小,大大减少了某些区域内存紧张,而某些区域又有内存空闲的矛盾情况出现。

========================================个人补充============================================================================

If SGA_TARGET is set to a value greater than SGA_MAX_SIZE at startup, then the latter is bumped up to accommodate SGA_TARGET.

Note: Do not dynamically set or unset the SGA_TARGET parameter. This should be set only at startup.

sga_max_size是静态参数,sga_target是动态参数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: