ORACLE SGA之shared pool

dayong2015發表於2014-06-06
1.shared pool的記憶體塊組成

shared pool中主要的記憶體區域:free、library cache、row cache

為了確保共享池中共享資料的訪問效能,共享池的每次記憶體分配都必須是連續的記憶體空間,經過一段時間的執行,共享池中會產生一些碎片,這些碎片分佈在一些連續分配的空間之間。

2.共享池堆的內部結構

oracle的記憶體空間分配是採用堆管理(HEAP)的模式。比如SGA HEAP、PGA HEAP、HEAP TABLE等都是堆記憶體管理。每個堆包含一個堆控制程式碼和一系列的記憶體擴充套件,每個擴充套件又包含一系列連續的chunk。記憶體申請者透過在堆上申請空間的模式來獲得記憶體。

堆建立包含兩個步驟:一是初始化堆的控制程式碼,二是給堆分配空間。

從chunk中分配空間的基本順序如下:

1)首先搜尋freelist上是否存在可以釋放的chunk(在該區域查詢的時候首先根據需要分配空間的大小,找到相應的bucket,然後搜尋整個連結串列,如果找到了大小相同的chunk,那麼就直接分配使用。如果找不到合適的chunk,就會選擇一個稍大的chunk,分配一個和所需空間大小一致的chunk,剩下的空間根據大小掛載到相應的bucket連結串列上)。

2)如果沒找到,就查詢是否有recreateable的chunk可以釋放。釋放已經使用的chunk,需要用到LRU連結串列。LRU連結串列根據使用的頻繁程度,透過一個雙向鏈來串聯已經被分配的chunk。如果在LRU鏈上找到了可以釋放的chunk,就通知HEAP MANAGER去釋放,如果該chunk是被鎖住的,首先要解鎖,然後才能釋放。HEAP MANAGER在釋放記憶體時,會自動合併碎片。

3)如果此時還沒有找到可以釋放的chunk,就從父堆裡分配空閒的空間。

4)如果父堆無法分配空間,就會報錯。

3.free空間

是一個一個的記憶體塊,使用鏈(chain)將空閒記憶體塊鏈起來,(每個鏈上所掛載的記憶體塊大小是不一樣的)。如:硬解析一個sql語句,需要根據解析的sql語句和sql語句的執行計劃,它所需要佔用的實際記憶體空間,從相應的鏈上找空間存放。硬解析需要記憶體空間,根據實際大小的free記憶體空間中的鏈中找到相應大小記憶體塊使用,會產生小記憶體塊(記憶體碎片)。系統如果有大量硬解析的話。雖然free裡面還有很多空間,但是所有的空間都是小的。並不能使用。

SQL> select * from v$sgastat where pool='shared pool' and name='free memory';

4.library cache空間

library cache裡面有很多鏈,鏈下掛有很多chunk,但是chunk裡面都寫了內容(sql,sql執行計劃)。

根據什麼把不同的chunk寫上記憶體後掛在不同鏈上:

把sql語句所有的字母轉換成ASCII碼值,就成了數字,對這些數字經過幾次運算,就是鏈的編號,這個sql語句就掛到所對應的編號上。當再次執行sql語句的時候,就會從對應編號的鏈上去找對應的chunk。

SQL>select * from v$sgastat where name='library cache';

5.資料字典快取(row cache)

資料字典快取不是純粹的資料字典表的快取,資料字典快取是經過組織的,用於資料庫執行中sql解析、許可權控制等用途的內部資料結構,是一種字典表的記憶體檢視。如:在執行某個sql的時候,為了sql解析,需要訪問一些字典表,從中獲取一些資料,那麼它會透過一些遞迴呼叫sql來完成這些事情。首先需要將資料塊從系統表空間中讀取到DB cache,然後從DB cache中獲得sql所需要的行資料。為了減少遞迴sql的執行開銷,這些行資料被快取在共享池中,這個快取就是資料字典快取。

SQL> select * from v$sgastat where name='row cache';

6.執行一條之前為快取的sql語句,檢視連結串列中chunk數量的變化

SQL> select count(*) from x$ksmsp;

  COUNT(*)
----------
     36635

SQL> select count(*) from dba_indexes;         --第一次執行發生硬解析,鏈上的chunk數量將有所增加

  COUNT(*)
----------
      2344

SQL> select count(*) from x$ksmsp;

  COUNT(*)
----------
     36650

SQL> alter system flush shared_pool;          --將shared pool清空,之後第一次執行的所有DML語句都將是硬解析

7.shared pool中的保留池設定
如果共享池中碎片化變得十分嚴重,就會導致比較大的共享記憶體分配無法滿足需求,oracle在共享池中設計了保留池.
保留池的設計目的是為了在共享池碎片化很嚴重的時候,還能夠有一部分保留空間,用於較大的記憶體分配。可以透過引數shared_pool_reserved_size來設定保留池的大小(由於oracle的記憶體自動管理機制,一般情況下不需要手動設定)。
SQL> show parameter shared_pool_reserved_size;
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
shared_pool_reserved_size            big integer 6081740
保留池的使用條件:
1)必須是在共享池的freelist中找不到足夠大的chunk
2)分配的記憶體容量要大於shared_pool_reserved_min_alloc的設定值(從8i開始該引數變為隱含引數,即_shared_pool_reserved_min_alloc,預設值為4400B),只有大於該設定值的記憶體分配才被認為是大記憶體分配。

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

相關文章