天天看點

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html><head><meta http-equiv="Cont

SGA_MAX_SIZE是從9i以來就有的作為設定SGA大小的一個參數,而SGA_TARGET則是從10g才有的一個新參數,作為配合10g自動管理SGA而出現的,下面以實驗的方式,深入解析這2個參數的差別和作用

[oracle@bak ~]$ sqlplus / as sysdba

SQL*Plus: Release 10.2.0.1.0 - Production on Mon Oct 13 01:59:11 2014

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Connected to:

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production

With the Partitioning, OLAP and Data Mining options

SQL> show parameter sga

NAME                                 TYPE        VALUE

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

lock_sga                             boolean     FALSE

pre_page_sga                         boolean     FALSE

sga_max_size                         big integer 272M

sga_target                           big integer 272M

SQL> desc v$sgainfo

 Name                                      Null?    Type

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

 NAME                                               VARCHAR2(32)

 BYTES                                              NUMBER

 RESIZEABLE                                         VARCHAR2(3)

SQL> set pages 100

SQL> select name,bytes/1024/1024 "size(MB)",resizeable from v$sgainfo;

NAME                               size(MB) RES

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

Fixed SGA Size                   1.16254425 No

Redo Buffers                      2.8359375 No

Buffer Cache Size                       172 Yes

Shared Pool Size                         80 Yes

Large Pool Size                           4 Yes

Java Pool Size                            4 Yes

Streams Pool Size                         8 Yes

Granule Size                              4 No

Maximum SGA Size                        272 No 

  --SGA_MAX_SIZE對應的值

Startup overhead in Shared Pool          36 No

Free SGA Memory Available                 0

11 rows selected.

注意,resizeable值為NO的,都是不可動态調整的值,并且由于SGA_TARGET和SGA_MAX_SIZE的大小一緻,是以Free

SGA Memory Available=0,而所有可動态調整的幾個記憶體元件再加上一個4M Granule Size,則正好等于SGA_TARGET的值

SQL> select (172 + 80 + 4 + 4 + 8 + 4) "sga_target(MB)" from dual;

sga_target(MB)

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

           272

我們也可以從v$sga_dynamic_components這個視圖了解各記憶體元件的記憶體配置設定情況,和v$sgainfo内容基本是一緻的,除了沒有展示Gradual Size這一項

SQL> select component,current_size/1024/1024 "size(MB)" from v$sga_dynamic_components;

COMPONENT                                                          size(MB)

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

shared pool                                                              80

large pool                                                                4

java pool                                                                 4

streams pool                                                              8

DEFAULT buffer cache                                                    172

KEEP buffer cache                                                         0

RECYCLE buffer cache                                                      0

DEFAULT 2K buffer cache                                                   0

DEFAULT 4K buffer cache                                                   0

DEFAULT 8K buffer cache                                                   0

DEFAULT 16K buffer cache                                                  0

DEFAULT 32K buffer cache                                                  0

ASM Buffer Cache                                                          0

13 rows selected.

SGA = shared pool + large pool + java pool + streams pool + DEFAULT buffer cache = 80 +4 + 4 + 8 + 172 =268M

這個算出來的SGA值比SGA_TARGET的值少了4M,其實就是那個Gradual Size的值

SQL> col name for a35

SQL> select name,issys_modifiable from v$parameter where name like '%sga%';

NAME                                ISSYS_MOD

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

sga_max_size                        FALSE

pre_page_sga                        FALSE

lock_sga                            FALSE

sga_target                          IMMEDIATE

ISSYS_MODIFIABLE列的值為FALSE的,就是不能動态修改的參數,需重新開機生效,為IMMEDIATE的,即可以動态修改

SQL> alter system set sga_target=350m;

alter system set sga_target=350m

*

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

如果不帶scope參數,預設為both,但要在記憶體中生效,必須滿足SGA_TARGET<SGA_MAX_SIZE的條件,是以必須指定scope=spfile,是以雖然是動态參數,但是依舊要重新開機後生效

SQL> alter system set sga_target=350m scope=spfile;

System altered.

SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup

ORACLE instance started.

Total System Global Area  369098752 bytes

Fixed Size                  1219472 bytes

Variable Size             100664432 bytes

Database Buffers          264241152 bytes

Redo Buffers                2973696 bytes

Database mounted.

Database opened.

sga_max_size                         big integer 352M

sga_target                           big integer 352M

可以看到,當調整了SGA_TARGET參數後,盡管沒有去手動調整SGA_MAX_SIZE的值,但現在它自動和修改後的SGA_TARGET的值比對了,從272M調整為352M,這裡還有個比較有意思的地方,就是指定了350M,為何會變為352M,這多出來的2M又是什麼呢?

SQL> select 350/4 "Granual Count" from dual;

Granual Count

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

         87.5

SQL> select 88*4 "SGA_SIZE(MB)" from dual;

SGA_SIZE(MB)

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

         352

其實很容易了解,剛才說了Granual Size的大小為4M,由于Granual必須完整地配置設定,是以會配置設定給SGA共88個Granual,即88*4=352M,也就是多給了2M

再來看一下剛才那些記憶體元件的記憶體配置設定情況

SQL> select name,bytes/1024/1024 "size(MB)",resizeable from v$sgainfo;

NAME                                  size(MB) RES

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

Fixed SGA Size                      1.16297913 No

Redo Buffers                         2.8359375 No

Buffer Cache Size                          252 Yes

Shared Pool Size                            80 Yes

Large Pool Size                              4 Yes

Java Pool Size                               4 Yes

Streams Pool Size                            8 Yes

Granule Size                                 4 No

Maximum SGA Size                           352 No

Startup overhead in Shared Pool             36 No

Free SGA Memory Available                    0

SQL> select component,current_size/1024/1024 "size(MB)" from v$sga_dynamic_components;

DEFAULT buffer cache                                                    252

SQL> 

當我們把SGA_TARGET從272M調整為350M時,由于Gruanual的存在,Oracle實際給SGA配置設定了352M的記憶體,而這352M記憶體中,其他記憶體元件的大小都沒有發生變化,僅僅隻是db buffer cache的值由之前的172M調整到了252M

之是以db buffer cache size随着SGA_TARGET的值自動調整,是因為這時10g的新特性,隻要SGA_TARGET為非零值,那麼記憶體元件就是采用動态配置設定原則,由Oracle自動調整各記憶體元件的大小。不過有個地方挺奇怪的,雖然從啟動執行個體時配置設定地記憶體也好,從v$sgainfo以及v$sga_dynamic_components中也好,看到的值都是252M,而從參數看db_cache_size的值,仍然是172M,不知何故,難道是bug?

SQL> show parameter db_cache

db_cache_advice                      string      ON

db_cache_size                        big integer 172M

剛才是直接修改SGA_TARGET而不修改SGA_MAX_SIZE的情況,我們再來看一下反過來的情況,先把SGA_TARGET調整回272M

SQL> alter system set sga_target=270m scope=spfile;

Total System Global Area  285212672 bytes

Fixed Size                  1219016 bytes

Variable Size             100664888 bytes

Database Buffers          180355072 bytes

注意,一旦SGA_TARGET動了,重新開機資料庫後,SGA_MAX_SIZE會跟着調整,也一起回到了272M的狀态,但與增大SGA_TARGET時的情況不同,也可以選擇不重新開機資料庫,那麼SGA_MAX_SIZE的值就不會做調整,而記憶體元件的值依然會跟着SGA_TARGET走(展現動态調整)

SQL> alter system set sga_target=270m;

由于是減小SGA_TARGET的值,是以不受必須比TARGET_MAX_SIZE小的這個條件限制,是以資料庫無需重新開機

Buffer Cache Size                          172 Yes 

  --僅僅調整了db buffer cache,由252M變為172M

Free SGA Memory Available                   80

剛才是直接調整SGA_TARGET,我們再來看一下隻調整SGA_MAX_SIZE的情況,先重新開機資料庫,使SGA_MAX_SIZE的值回到272M

SQL> alter system set sga_max_size=350m scope=spfile;

Fixed Size                  1219496 bytes

Variable Size             184550488 bytes

Fixed SGA Size                      1.16300201 No

Buffer Cache Size                          172 Yes

注意,僅僅調整SGA_MAX_SIZE後,SGA_TARGET并不會跟着調整,是以各記憶體元件的值也不會調整,而這時我們發現Free SGA Memory Available的值為80M,而不再是之前的0了,調整SGA_MAX_SIZE為SGA_TARGET增加了80M的上限,這80就是352-272得到的,相當于做了個預留,告訴SGA,你可以現在隻用172M,但如果想增加,可以再多用80M,達到352M。而這個時候隻要SGA_TARGET重新設定的值沒有超過SGA_MAX_SIZE的值,就可以在不停庫的情況下增加SGA大小,這樣做是有好處的

最後,我們還可以把SGA_TARGET設定為0,即表示禁用10g的新特性——自動配置設定記憶體,這樣我們可以對各個記憶體元件的值進行單獨設定,對于特殊的應用場景,有時候也是需要的,因為自動管理隻是oracle提供的一種便利行,但并不意味着自動調整就一定萬事皆OK,11g的自動記憶體管理就一度被诟病,這裡不讨論

SQL> alter system set sga_target=0;

sga_target                           big integer 0

設定SGA_TARGET=0以後,已經配置設定的記憶體元件的值不會變化,如果不設定新值,那麼依舊保持原來的值,除非單獨設定,即使從起資料庫執行個體也一樣,SGA_MAX_TARGET依然不會再根據SGA_TARGET調整,因為SGA_MAX_TARGET我們是給過它确定的值的

SQL> show parameter sge

sga_max_size                         big integer 352M 

  --重新開機後依然是352M,并不會變為0

重新開機資料庫執行個體後,SGA_MAX_SIZE的值沒有跟着SGA_TARGET做調整,除非再次增大SGA_TARGET的大小并超過SGA_MAX_SIZE的上限,那麼下次重新開機後,SGA_MAX_SIZE又會再一次跟着SGA_TARGET調整

SQL> alter system set sga_target=380m scope=spfile;

Total System Global Area  398458880 bytes

Fixed Size                  1219640 bytes

Variable Size             100664264 bytes

Database Buffers          293601280 bytes

sga_max_size                         big integer 380M

sga_target                           big integer 380M

SGA_MAX_SIZE又再一次和SGA_TARGET的值一緻了,并且380正好可以除盡4,共配置設定95個Granual,是以不會有多2M的問題

總結:

1.SGA_MAX_SIZE是靜态參數,而SGA_TARGET可以動态修改,當要改的SGA_TARGET值超過SGA_MAX_SIZE的值時,因為不允許在記憶體中直接生效,即scope=both或memory都不行,是以必須指定scope=spfile,重新開機後才能修改成功。如果此時沒有設定過SGA_MAX_SIZE得值,那麼無論是改大還是改小,重新開機資料庫後,SGA_MAX_SIZE都回跟着SGA_TARGET做調整。

2.當先給SGA_MAX_SIZE設定了一個較大的值,重新開機資料庫後,SGA_TARGET可以依然保持原有大小,相當于給SGA_TARGET先預留了一些記憶體,預先設定好可SGA可配置設定記憶體,等到資料庫出現壓力導緻SGA記憶體不足,可以直接通過SGA_TARGET動态修改到這一上限而無需停庫。

3.當給SGA_TARGET設定非零值時,表示采用記憶體元件記憶體由oracle動态調整,如shared

pool,db buffer cache等,這些記憶體元件隻會跟着SGA的大小動态進行調整(增大或減小),與其他值無關。

4.當SGA_TARGET設定為零時,表示禁用記憶體元件由SGA自動管理,如果未做單獨設定,那麼保持原有值。此時可以根據具體場景需求,單獨

為某個記憶體元件配置合理的記憶體大小。

5.如果是先設定了SGA_MAX_SIZE的值,再設定了SGA_TARGET,那麼隻有當SGA_TARGET設定的值超過SGA_MAX_SIZE的值時,SGA_MAX_SIZE才會在重新開機生效後,調整到與SGA_TARGET的值一緻,反之則不會改變。