Oracle的記憶體的分配、回收[final]

tolywang發表於2010-10-25


Oracle中的共享記憶體區的分配都是以chunk為最小單位的。Chunk不是一個固定值,它是一個擴充套件段(extent)中一塊連續的記憶體。而Oracle的記憶體(其他儲存,如磁碟也是)的增長是以擴充套件段為基礎的。


1. 空閒列表和LRU連結串列
空閒的chunk按照大小來組織在相應的空閒列表(Free List)中。而未pin住的、可重建(unpinned recreatable)的chuck被維護在兩個分別用於週期性chunk和短期chunk的LRU連結串列中。子堆還有一個包含少許空閒記憶體的主永久記憶體chunk。

2. 空閒記憶體分配和回收
空閒記憶體都是由空閒列表(free list)統一管理、分配的。每個空閒的chunk(大塊)都會屬於也只屬於一個空閒列表。空閒列表上的chunk的大小範圍是由bucket來劃分的。Bucket直譯為“桶”,在西方,往往用桶來盛裝一定品質範圍的物品,以便查詢。比如,在採礦時,用不同的桶來裝不同純度的礦石,在桶上標明礦石的純度範圍,以便在提煉時可以採用不同工藝。在這裡,我們也可以把bucket視為一種索引,使Oracle在查詢空閒塊時,先定位所需的空閒塊在哪個bucket的範圍內,然後在相應的空閒列表中查詢。

一次記憶體的分配過程如下:當一個程式需要一個記憶體的大塊(chunk)時,它會先掃描目標空閒列表(每個空閒列表對應有一個bucket,bucket是這個空閒列表的中chunk的大小範圍)以查詢最適合大小的chunk。如果找不到一個大小正好合適的chunk,則繼續掃描空閒列表中更大的chunk。如果找到的可用chunk比所需的大小大24位元組或者更多,則這個chunk就會被分裂,剩餘的空閒chunk又被加到空閒列表的合適位置。如果空閒列表中沒有一個chunk能滿足要求的大小,則會從非空的相鄰bucket的空閒列表中取最小的chunk。如果所有空閒列表都是空的,就需要掃描LRU連結串列釋放最近最少使用的記憶體。當chunk空閒時,如果相鄰的chunk也是空閒的,它們可能會結合(coalesce)起來。

當所有空閒列表都沒有合適的空閒chunk可用時,就開始掃描LRU連結串列,將最近最少使用的chunk釋放掉(如有空閒的相鄰chunk,則結合),放到相應的空閒列表種去,直到找到合適的chunk或者達到最大查詢數限制。如果在釋放了LRU連結串列中最近最少使用的chunk後沒沒有找到合適空閒chunk,系統就拋4031錯誤。

如果找到了可用空閒chunk,就將它從空閒列表中移出,放到LRU連結串列中去。

下面介紹一下Shared Pool的分配和回收。

3. Shared Pool的分配和回收
在Shared Pool中,空閒列表掃描、管理和chunk分配的操作都是受到shared pool latch保護的。顯然,如果shared pool含有大量的非常小的空閒chunk,則掃描空閒列表時間將很長,而shared pool latch則會要保持很久。這就是導致shared pool latch爭用的主要原因了。有些DBA透過增加shared pool來減少shared pool latch爭用,這種方法是沒有用的,可能反倒會加劇爭用(作為短期解決方法,可以flush shared pool;而要真正解決問題,可以採取在例項啟動時keep住那些可能會斷斷續續使用的物件【這種物件最容易導致shared pool碎片】)。

只有執行了ALTER SYSTEM FLUSH SHARED_POOL才會使shared pool的空閒chunk全結合起來。因此,即使shared pool空閒記憶體之和足夠大,也可能出現記憶體請求失敗(空閒記憶體都是一些很小的碎片chunk)。

實際上,oracle例項啟動時,會保留大概一半的Shared Pool,當有記憶體壓力時逐漸釋放它們。Oracle透過這種方法限制碎片的產生。Oracle的少量空襲記憶體(spare free memory)和X$表即其他持久記憶體結構一起,隱含在shared pool的主要持久記憶體chunk中。這些記憶體不在shared pool的空閒列表中,因此能夠立即被分配。但是,卻包含在檢視V$SGASTAT的free memory的統計資料中。

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

相關文章