還是想嘮叨一下,要想把oracle體繫結構學深學透,必須結合備份與恢複的實驗及原理去學,這個我在後續也會寫相應的blog。在這裡我在介紹記憶體結構時,只是做些基礎性的瞭解。
我們先看兩個容易混淆的概念。SID和ORACLE_SID,其實吧,這兩個沒啥本質的區別。若真箇想分一分的話。那麼,SID是網站標識符,也即工作階段識別項,他和$ORACLE_HOME一起唯一標識了一個SGA;而ORACLE_SID則可以認為是執行個體名,通過v$instance的欄位instance_name查出。
當DBA安裝oracle軟體時,針對os首先會辨別是32位還是64位,而這32位和64位又是代表什麼意思呢?簡單來說,就是CPU對於記憶體最大的支援範圍。32位的CPU最大支援4G記憶體。如果oracle運行在32位linux上時,其預設SGA無法超過1.7G.
執行個體是由參數檔案建立出來的,存在於作業系統的記憶體中。linux上有兩條命令可以檢查執行個體是否開啟:
ps -ef|grep ora_ --檢查後台進程是否開啟;
ipcs -m|grep ora --檢查SGA是否分配
在我的磁碟上,有3個資料庫.任何時刻我都只有一個執行個體,但有多個資料庫,在任何時間點上只能訪問其中的一個資料庫。當一台伺服器上有多個執行個體運行時,每個執行個體都有一個自己專用的SGA。
每個oracle執行個體都有一個被oracle進程所共用的記憶體結構,稱之為SGA。當執行個體開啟後,各個記憶體區會依照最少的需求分配所需的大小。在ora10g使用自動SGA記憶體管理(ASMM:automatic shared memory management)時,只需把SGA_TARGET參數設定為所需的大小便可,其後會根據工作負載自動擴充每個記憶體塊的大小。在SGA中,空間的最小分配單位是顆粒。它由sga_max_size決定,當sga的總和小於128m時,顆粒為4m,當sga大於128m時,顆粒為16m。
下面我們來看看主要的SGA組件。
database_buffer_cache
緩衝區快取中的塊實質上在一個位置上管理,但有兩個不同的列表指向這些塊:
髒塊列表:其中的塊需要DBWn寫入磁碟
非髒塊列表:8.0以前的版本是LRU演算法,之後採用接觸計數演算法,如果命中緩衝中的一個塊,則會增加與之相關聯的計數器。塊緩衝區不再像以前那樣移到塊列表的最前面,而是原地留在塊列表中,只是遞增它的接觸計數。不過,一段時間,塊會在列表中“移動”。例如,髒塊由髒列表指向,過一段時間要重用塊時,如果緩衝區已滿,就要將接觸計數較小的某個塊釋放,換由非髒塊列表來指向。
緩衝區快取允許有不同的塊大小。可以通過設定DB_nK_CACHE_SIZE參數,並重啟資料庫。但前提要注意SGA的大小。如果採用擴大的方法,比如,你的SGA大小是128m,你想再為緩衝區增加另外的64m,就必須把SGA_MAX_SIZE設定為192m或者更大。另外,你也可以採用收縮的辦法,即縮小DB_CACHE_SIZE,因為9i之後,database_buffer_cache的大小可以直接修改參數db_cache_size,那麼:
show parameter db_cache_size; --看一下目前有多大
alter system set db_cache_size=xxm; --將其縮小
alter system set db_16k_cache_size=xxm; --設定16k的資料區塊大小的緩衝區快取
這樣我在database_buffer_cache中就有兩種資料區塊大小了。這兩個緩衝是互斥的。只是為了可傳輸資料表空間。比如,OLTP和OLAP就可以共存於一個資料庫中。
cache hit(快取命中):使用者請求查詢時,oracle在緩衝區快取找到使用者所需的資料時,就直接從緩衝區返回給使用者。如果在緩衝區找不到,則稱之為cache miss(緩衝失誤)。
database_buffer_cache命中率公式是
cache hit ratio=1-(physical reads/(db block gets+consistent gets))
db block gets:是指DML語句所得到的資料區塊個數
consistent gets:是指select語句所得到的資料區塊個數
logical reads:將db_block gets與consistent gets相加得到的資料區塊個數。
physical reads:從硬碟上讀出的資料
hit ratio最好大於90%
database_buffer_cache中包含三種不同性質的緩衝:
dirty buffer:已修改,但尚未寫入資料庫的資料
free buffer:這裡的內容和資料檔案的內容一模一樣,也就是這些buffer已經寫入資料庫內了,隨時可以拿來覆蓋使用。
pinned buffer:正在被使用的buffer
可以把database_buffer_cache卻分為三種不同性質的分區:
回收池:放在回收池的資料,只在事務還存在時才會被用到,一旦事務結束,就會被釋放掉。
保留池:頻繁重複用到的資料
預設池:沒有指定時,資料就會被放在預設池。
shared pool
設計共用池是為了重用查詢計劃.破壞共用池,最容易的辦法是不使用綁定變數。oracle提供一個參數cursor_sharing可對sql語句做強制綁定變數,其中有個參數值叫similar。在10g中,shared_pool_size參數控制了共用池的大小。裡面的主要主件是庫緩衝和字典緩衝。對於這兩個的關係,參見的我的部落格:http://blog.csdn.net/linwaterbin/article/details/7651038
在共用池內分析sql語句可分為hard parse和soft parse,。當sql語句一進入oracle資料庫時,oracle首先會檢查一下共用池有沒有完全相同的sql語句,如果沒有,就會進行parse作業;如果有,就會跳過parse,只檢查使用者權限等。
可以使用dbms_shared_pool.keep(兩個參數),把sql強制留在shared pool裡面。
1)先找出sql語句的相對位置:
select address,hash_value from v$sqlarea where sql_text='......';
2)將位置保留在共用池內:
exec dbms_shared_pool.keep('address','類型‘);
redo log buffer
重做日誌緩衝區的預設大小由log_buffer參數控制,這個區的最小大小取決於os。將log_buffer設定為1,再重啟資料庫就可以知道最小值。重做日誌緩衝區的空間劃分為多個塊,這些塊基本上都是512k。
和這個區相關的概念,最重要的是檢查點機制。即:DBWn會去檢查某些redo entry是否已經寫入redo log file。檢查點機制是避免在資料庫恢複時,讀取的redo資訊太多,導致恢複的時間過長。大體的檢查點機制有以下幾個步驟:
1)取當前的SCN號為檢查點SCN。
2)檢查相關的redo entry是否寫入online redo log file
3)如果寫入,則DBWn會把redo保護的dirty buffer flush到磁碟
4)如果沒有,則DBWn會去通知LGWR來寫,然後,自己再寫
5)CKPT更新控制檔案和資料檔案的檔案頭
而觸發檢查點的事件有很多,比如:日誌卻,;fast_start_mttr_target等