SGA系統全域性區記憶體結構瞭解
System global area(SGA) 是一組共享的記憶體結構,它裡面儲存了oracle資料庫例項(instance)的資料和控制檔案資訊。如果有多個使用者同時連線到資料庫,他們會共享這一區域,因此SGA也稱之為shared global area。
SGA和oracle的程式組成了oracle的例項(instance)。在例項啟動的時候記憶體會自動分配,當例項shutdown的時候作業系統會將記憶體回收的。沒一個例項(instance)擁有自己的SGA。
SGA是可以讀寫的,每一個使用者連到資料庫例項時都是可以讀例項的SGA的內容,oracle透過伺服器程式執行一個命令去寫SGA的資料。
SGA包含以下的資料結構:
l Database buffer cache
l Redo log buffer
l Shared pool
l Java pool
l Large pool (optional)
l Data dictionary cache
l Other miscellaneous information
SGA中還包含了後臺程式訪問的一些關於資料庫和例項狀態的資訊,稱之為fixed SGA,使用者的資訊是不會儲存在這塊區域中的。程式之間的一些交流的資訊也會儲存在SGA中。如果使用共享server模式,有些PGA的內容也會儲存在SGA中。
SGA是可以動態調整大小的,也就是說調整其大小是不用shutdown資料庫的。在初始化引數中設定可以設定sga_max_size這個引數,當SGA的各部分的和要大於設定的sga_max_size的引數的時候,設定的sga_max_size將會被忽略掉,而是將各部分的大小相加。當sga_max_size的大小大於各部分的大小相加時,會使用sga_max_size的引數。
對於效能的考慮,SGA區域的記憶體應該是真正的記憶體,如果使用需擬記憶體,會大大降低效能。下面這幾個引數最嚴重的影響到了SGA的大小:
DB_CACHE_SIZE | The size of the cache of standard blocks. |
LOG_BUFFER | The number of bytes allocated for the redo log buffer. |
SHARED_POOL_SIZE | The size in bytes of the area devoted to shared SQL and PL/SQL statements. |
LARGE_POOL_SIZE | The size of the large pool; the default is 0. |
SGA分配的最小單元
SGA在分配和回收的時候是採用一個叫做granule的單元進行分配的,granule的大小是由SGA的大小決定的,如果SGA小於128mb,則granule就是4mb,大於128mb,則為8mb或者16mb,當分配記憶體的時候,將會以granule的整數倍去分配,比如設定DB_CACHE_SIZE=131mb,grance為4mb時,系統會將DB_CACHE_SIZE=132mb。所有關於granule的資訊都會儲存在granule entry,在granule entry中管理每個granule的狀態等資訊。
Database buffer cache
Database buffer cache 是SGA中的一部分,它儲存的是從資料檔案中讀取的資料塊的複製,所有的資料庫連線都會共享訪問這個區域。Database buffer cache 和sql的共享區分在不同的邏輯segment集中(database buffer cache 和 shared pool 是不同的兩個記憶體區域),這樣可以降低他們之間的爭用情況。
Database buffer cache的組織方式
這塊記憶體區域中被組織成兩個連結串列:一個是寫的連結串列,一個是最近最少使用(LRU)的連結串列。寫的連結串列裡面是寫髒資料的,LRU連結串列是控制不包含任何資料的空閒空間(free buffers)、正在使用的空間(pinned buffers)和還沒有寫到寫連結串列的髒資料塊。
當一個程式訪問一個buffer的時候,程式將會將該buffer移到LRU的末尾,稱之為MRU,當越來越多的buffer被移到MRU後,髒資料塊就會接近LRU的LRU端。
開始的時候,使用者程式需要一些資料,它就會到database buffer cache中去搜尋,如果有(cache hit),該程式就可以直接從記憶體中讀資料;如果沒有找到(cache miss),那麼必須先要從資料檔案將資料拷到database buffer cache,然後再去從記憶體中去訪問。Cache hit 要比cache miss 快很多由此可以看出。
在讀一個資料塊到記憶體中去的時候,程式必須先要找到一個空閒的buffer,這時候程式會從LRU的末尾開始訪問LRU連結串列,直到找到一個空閒的buffer 或者搜尋完可以搜尋的所有buffer。
當程式在搜尋LRU的時候找到一個髒資料buffer,它就會將該buffer移到write list,然後繼續查詢,直到找到一個空閒buffer,然後候就從硬碟將資料塊讀到這個buffer並且將這個buffer移到LRU的末尾MRU端。如果這個使用者程式找遍了所有的buffer也沒有找到一個空閒的buffer,這時候就停止查詢LRU,告訴DBW0去寫一些髒資料塊到硬碟。
LRU演算法和全表掃描
當使用者程式執行一個全表掃描的時候,它就會讀表的所有塊到buffer並且將他們放在LRU的LRU端的連結串列上,因為全表掃描的資料基本上就是比較簡短的使用就不再使用了,所以他應該放在LRU的LRU端的連結串列上的,用完了就需要趕緊交換出去了。
也可以採用一些方法改變這樣的一個全表掃描的buffer處理行為,cache可以將表等cache到MRU的末尾,這樣可以避免一些io的消耗,當然這樣的表應該是比較小的。
根據上面,我對database buffer cache的理解LRU是一個什麼樣的連結串列:
LRU
----------------------------------------------------
| buffer| buffer| ..... |buffer|buffer|
-MRU端-----------------------------------LRU端------
因為SGA中只有兩個連結串列:一個是WRITE連結串列,一個是LRU連結串列。所以MRU和LRU應該是一個LRU連結串列中的,而LRU的MRU端是最近最多訪問的,LRU的LRU端是最近最少訪問的。個人認為write連結串列在一開始沒有髒資料需要寫的時候是一個空連結串列,當有髒資料buffer從LRU連結串列移過來時,這個連結串列開始有buffer鏈在上面,其實此時是不會再另外為寫連結串列分配空間的,直接將LRU中的buffer的指標指向寫連結串列就可以了。
Size of the database buffer cache
Oracle允許塊的大小有多種,可以設定db_cache_size的大小。
Redo Log Buffer
該buffer是迴圈的一塊空間在SGA中,它儲存了一些關於資料庫的一些改變。這些資訊就儲存在redo entries,包含在執行INSERT, UPDATE, DELETE, CREATE, ALTER, or DROP 操作時的重構或重做的資訊,在恢復的時候,redo entries也許是有必要的。
Redo entries是資料庫伺服器程式從使用者的記憶體空間中複製到redo log buffer,redo entries是一個連續的buffer 空間。後臺程式LGWR寫redo log buffer去active online log file到磁碟上。
Shared pool
這一塊區域裡面三個主要的部分:library cache,dictionary cache,儲存並行執行的資訊的buffer,還有一些控制資訊。
Library cache
這塊區域中有共享的sql區域。私有的sql區域,PL/SQL的程式和包,還有一些鎖和library cache的控制程式碼。
共享的sql區域和私有的sql區域
Oracle會讓每一條sql語句在共享sql區和私有sql區執行,oracle認為,兩個使用者執行相同的sql,此時這些sql應該是可以共享的,然而每一個使用者還會擁有自己的會話環境,這樣就會擁有一個私用的sql區域。
共享sql區域中包含sql的分析樹和執行計劃,oracle會儲存這部分記憶體在共享的sql區中以便使用者可以多次執行這些sql。當一些新的sql執行的時候,oracle會從shared pool中分配一些記憶體給這條sql,記憶體的大小取決於sql的複雜度。如果整個共享區已經被分配完了,oracle會採用LRU策略將一些buffer flush出去直到空閒的buffer可以將新來的sql放得開,被flush出去的sql的一些資訊,下一次再使用的時候需要重新編譯。
私有sql區域包含執行時的一些記憶體結構和一些 bind資訊,每一個會話在執行sql的時候都會有自己的一個sql區域。
遊標的私有sql區域被分為兩種生命週期不相同的區域:
l 持久區域:例如 bind 資訊,這部分空間只有在這個遊標關閉的時候才會被回收。
l 執行時環境:當該sql執行結束的時候這部分環境就會被回收。
Oracle首先會去建立這個執行時環境在執行請求發過來後,對於insert update delete 操作,oracle會在執行完畢後就釋放這部分空間,當執行select 的時候,oracle會到所有行都被fetch或者查詢取消才會釋放這部分空間。
私有sql區域的分配地址是取決於建立連線的session的型別的,如果是從專有伺服器模式下,該私有sql區域會分配在pga中,如果是共享伺服器,該私有sql區域會分配在sga中。
Dictionary cache
資料字典是資料庫的一組表和檢視,它包含資料庫的結構、使用者等的各種資訊。Oracle在解析sql語句的時候會頻繁的去訪問這些表,對於資料庫的這些操作是必不可少的。因為這些資料非常經常的被訪問,所以有兩個地方存放這些資料在記憶體中。一個地方叫 data dictionary cache,也稱之為 row cache,因為在在這塊區域中儲存的是以行的方式做的。另一個地方叫做library cache,所有的使用者都是共享訪問這兩個地方的。
共享記憶體的分配和重用
一般來說,在記憶體中的一些條目一直會保留著的,除非需要按照LRU演算法從記憶體中flush掉,如果有記憶體的需求,有些不用的就會被flush掉。
當一條sql提交到oracle進行執行的時候,oracle一般會執行分配的以下步驟:
1、 到共享池中去檢查要執行的sql是否存在,如果存在就直接使用,如果不存在就需要在共享sql區中分配記憶體,存放新編譯的sql。不論哪一種情況,都有私有sql區都會和使用者的共享區的sql相關聯。
2、 Oracle會分配一個私有的sql區和會話對應,
Oracle在以下情況下會將共享sql區從共享池中flush掉:
l 當使用analyze的時候,所有涉及的物件,都會被flush掉,下一次使用時會重新分配;
l 當一個物件被修改了,其相應的sql也會被flush掉;
l 改變資料庫的全域性名,所有的sql都會被flush掉;
l ALTER SYSTEM FLUSH SHARED_POOL時,所有的sql也會被flush掉
[@more@]來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7312700/viewspace-1002341/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 2 Day DBA-管理Oracle例項-關於例項記憶體結構-系統全域性區(SGA)Oracle記憶體
- Oracle體系結構之記憶體結構(SGA、PGA)Oracle記憶體
- 設定系統全域性區SGA命令
- oracle記憶體結構:SGA的區域資訊Oracle記憶體
- Oracle記憶體結構(一)----SGA的區域資訊Oracle記憶體
- Oracle記憶體結構(一)----SGA的區域資訊(轉)Oracle記憶體
- Oracle記憶體結構研究-SGA篇Oracle記憶體
- 虛擬記憶體系統——瞭解記憶體的工作原理記憶體
- oracle架構之系統全域性區Oracle架構
- 詳細瞭解 InnoDB 記憶體結構及其原理記憶體
- 記憶體_SGA記憶體
- Oracle體系結構之-記憶體結構Oracle記憶體
- 記憶體四區之程式碼區,全域性區,棧區和堆區記憶體
- Oracle記憶體體系結構Oracle記憶體
- 記憶體分配知識(全域性,區域性,靜態變數)記憶體變數
- 2 Day DBA-管理Oracle例項-關於例項記憶體結構-程式全域性區(PGA)Oracle記憶體
- C++基礎-1-記憶體管理(全域性區、堆區、棧區)C++記憶體
- Oracle體系結構:記憶體結構和程式結構(轉)Oracle記憶體
- [Virtualization]ESXi體系結構與記憶體管理(一)體系結構記憶體
- SGA與共享記憶體記憶體
- Oracle 體系結構 SGA 和PGA 總結Oracle
- oracle 記憶體結構具體解釋Oracle記憶體
- 記憶體結構記憶體
- oracle體系結構梳理---SGA+PGAOracle
- JVM結構-記憶體結構(執行時資料區)JVM記憶體
- JVM之記憶體結構詳解JVM記憶體
- 12張圖開啟JMeter體系結構全域性視角JMeter
- Postgresql資料庫體系結構-程式和記憶體結構SQL資料庫記憶體
- SGA和PGA記憶體管理記憶體
- SGA與共享記憶體2記憶體
- [Virtualization]ESXi體系結構與記憶體管理(二)控制記憶體分配記憶體
- [Virtualization]ESXi體系結構與記憶體管理(三)控制記憶體分配記憶體
- iOS全域性變數與屬性的記憶體管理iOS變數記憶體
- c 結構體記憶體對齊詳解結構體記憶體
- 瞭解計算機體系結構(4)計算機
- PostgreSQL:記憶體結構SQL記憶體
- oracle 記憶體結構Oracle記憶體
- JVM記憶體結構JVM記憶體