SGA_MAX_SIZE與SGA_TARGET

bitifi發表於2015-11-24

原文地址:http://chenzs19850728.blog.163.com/blog/static/7629609200822374034376/


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 PoolJava PoolLarge PoolStreams Pool這幾塊記憶體區的大小是相應系統引數設定而改變的,所以有通稱為可變SGAVariable SGA)。最後一個fixed sga部分,一般是在例項啟動以後就固定在sga中了,是不會發生變化的,這個部分的區域一般小於100k

     理解了SGA的組成以後,下面就來解釋一下有關設定SGA大小的兩個引數SGA_MAX_SIZESGA_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實際記憶體分配給oraclesga,可能也最多就給了350M,剩下的150M使用虛擬記憶體。OracleSGA達到500M的時候(即達到SGA_MAX_SIZE指定的大小),實際上這個sga350M實際記憶體和150M的虛擬記憶體組成,如果這個時候Oracle想繼續申請記憶體給SGA使用,那麼OS是不會再給其分配記憶體,因為它已經達到了SGA_MAX_SIZE的最大值。這個例子,雖然比較極端,即使OS實際上比方說有1G記憶體,OracleSGA也未必全部由實際記憶體組成,可能是由400M實際記憶體和100M的虛擬記憶體組成,這是由作業系統的記憶體管理策略決定的。此時,很顯然有個問題,假設我的機器實體記憶體(實際記憶體)足夠多,如何讓Oracle所申請的SGA記憶體全部在實體記憶體中呢,因為假設使用了虛擬記憶體,必定會帶來額外的PAGE IN/PAGE OUTI/O操作,這是很不合算的。這個問題其實就是在實體記憶體中固定SGA的問題,這要涉及到另外兩個引數LOCK_SGAPRE_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_SIZE10g中的新記憶體池)

+ 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 CacheShared 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特性。

     當啟用OracleASMM新特性以後,也不是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_TARGETSGA的所有元件的大小的最大值之和,即當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中是什麼樣子的呢?下面來看看,也讓我們猜測一下oracleSGA_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會自動幫你調整,設定比它大,那還是出錯。現在可以自己想想,oracleSGA_TARGET的大小處理在往正確的簡單的方向前進中。

SGA_TARGET帶來一個重要的好處就是,能使SGA的利用率達到最佳,從而節省記憶體成本。因為ASMM啟動後,Oracle會自動根據需要調整各個區域的大小,大大減少了某些區域記憶體緊張,而某些區域又有記憶體空閒的矛盾情況出現。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30496894/viewspace-1845633/,如需轉載,請註明出處,否則將追究法律責任。

相關文章