Oracle 記憶體管理SGA

來源:互聯網
上載者:User

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的最大限制。此外,一旦分配後,各個區的記憶體只能給本區使用,www.bkjia.com相互之間是不能共用的。拿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會自動根據需要調整各個地區的大小,大大減少了某些地區記憶體緊張,而某些地區又有記憶體閒置矛盾情況出現。

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.