還是想嘮叨一下,要想把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信息太多,導致恢復的時間過長。大體的檢查點機制有以下幾個步驟:
原文轉自:http://www.anti-gravitydesign.com