讀書筆記-高階owi與oracle效能調整-oracle internal

selectshen發表於2014-09-05
--buffer cache
oracle為了有效管理高速緩衝區,使用hash chain結構.hash chain位於共享池內,使用oracle典型記憶體結構的管理方法
bucket->chain->header結構.
hash chain位於共享池內,而實際緩衝區資訊則位於高速緩衝區.
Oracle使用兩種LRU列.LRU列作為最近被使用和未被使用的緩衝區列,包括空閒緩衝區,正使用或已使用緩衝區,未移到LRUW列的髒緩衝區等.LRUW列管理未記錄到硬碟的已修改緩衝區列,高速緩衝區上所有緩衝區列一定屬於LRU列或LRUW列兩者中的一個.
LRU列主列:已使用的緩衝區列,以hot區域和cold區域區分管理.
LRU輔助列:空閒緩衝區列,更準確的表示同是未使用的緩衝區或透過DBWR寫入的緩衝區列.
LRUW列主列:已修改的緩衝區列.
LRUW列輔助列:當前透過DBWR寫入中的緩衝區列.
oracle 檢索空閒緩衝區時,首先在lru列的輔助列上檢索空閒緩衝區.若輔助列的緩衝區都被使用,在主列的cold區域檢索空閒緩衝區.例項初次啟動時,所有緩衝區在輔助列上管理.而且,已修改的緩衝區利用DBWR寫入後重新轉換成空閒
緩衝區,新增到lru列的輔助列.
lru列和lruw列總是成對出現,這一對列被稱作工作組.oracle使用多個工作組,而一個cache buffers lru chain鎖存器管理一個工作組.
single block i/o讀取的塊將插入到mid-point.mid-point的位置是cold區域頭部.multi block i/o讀取的塊將插入到mid-point後移到cold區域的尾部.
檢索緩衝區的步驟:
(1)對於使用者請求的塊DBA和類利用hash函式建立hash值,然後檢索hash值相應的hash bucket.
(2)獲得保護hash bucket的cache buffers chains鎖存器.若是讀取工作,就以shared模式獲得鎖存器;若是修改工作,就以exclusive模式獲得鎖存器.如果在這個過程中發生爭用, 則等待latch:cache buffers chains事件.檢索hash bucket上的chain後,確認塊相應buffer header存在與否.如果buffer header已經存在,並且相應塊已經位於高速緩衝區時,對相應緩衝區以shared模式或exclusive模式獲得buffer lock,然後執行所希望的工作.一般情況下,若在獲得buffer lock過程中發生爭用,則等待buffer busy wait事件.對正在透過dbwr寫入的緩衝區,在獲得buffer lock的過程中發生爭用,則等待write complete waits事件.
(3)若高速緩衝區上不存在塊,將先獲得管理工作組的cache buffers lur chain鎖存器.這個過程如果發生爭用,則等待latch:cache buffers lru chains事件.獲得鎖存器後,在lru列的輔助列上檢索空閒緩衝區.若輔助列沒有可用的空閒緩衝區,就在主列上按最少使用的順序檢索空閒緩衝區(在此 過程中,如果發現髒緩衝區,則將它移動到lruw列),找到空閒緩衝區後,對於相應緩衝區以exclusive模式獲得buffer lock,並從資料檔案將塊讀取到相應的緩衝區.此時,在獲得buffer lock過程中若發生爭用,則等待read by other session事件.高速緩衝區的正確的物理讀取值是從physical reads統計值上減去physical read direct,physical read direct(lob)統計值.
(4)lru列上檢索空閒緩衝區時,掃描與_db_block_scan_max_pct(預設值是40)引數值相同的lru列部份後,若還沒有找到空閒 緩衝區,則伺服器程式將停止lru列的掃描.伺服器程式請求dbwr將髒緩衝區記錄到資料檔案裡,以確保空閒緩衝區.透過dbwr保證擁有空閒緩衝區為 止,伺服器程式將等待free buffer waits事件.

--shared pool
共享池在SGA區域上屬於變數區域.變數區域由shared pool,java pool,large pool,streams pool組成.
共享池可以再分為多種記憶體區域,其中具有代表的是library cache和row cache.
共享池中最關鍵的部份是庫高速緩衝區,它是管理與sql語句的執行相關的所有資訊的區域.庫快取記憶體是被kernel generic librarycache管理的,kgl利用kgh分配得到必要的記憶體chunk.
庫快取記憶體是hashtable->bucket->chain->handle->object的結構.
oracle 利用應用於物件名稱上的hash函式生成的hash值,分配適當的hashbucket,擁有相同hash值的物件透過chain管理.一個 librarycache handle管理一個library cache object.handle對實際lco起到meta資訊和指標的作用,lco儲存著實際資訊.
lco所包含的資訊中重要資訊如下:
dependency table:當前lco依賴的其它lco的資訊.比如sql語句對所參照的表,檢視等具有依賴性.
child table:關於當前lco的子lco的資訊.如procedure,表這樣只賦予了唯一名稱的lco不具有子lco,oracle對於 procedure,表這樣的物件,總是將方案名儲存在一起,所以能保障唯一性.但若是sql語句,將sql文字本身作為名稱,所以不能保障唯一性.因此 oracle會建立擁有sql文字名稱的父lco,將實際sql cursor資訊儲存到子lco.如果兩個不同的方案a和b,文字雖然相同,但是實際上所參照物件執行不同的sql語句時,oracle將建立sql語句 相應的父lco和方案a執行的sql cursor所對應的子lco,方案b執行的sql cursor所對應的子lco,總共建立三個lco,這時,v$sqlarea,version_count值是3.子lco儲存在庫高速緩衝的匿名列.
data blocks:lco包含的實際資訊所儲存的chunk區域的指標資訊.如果是sql cursor,sql語句,執行計劃,執行文字資訊等會被儲存到特定記憶體區域,這些chunk的地址值被lco的data blocks區域管理.
欲檢索庫快取記憶體的所有程式,就必須獲得保護相應hash bucket的library cache鎖存器.oracle使用的library cache鎖存器,其使用數量與大於cpu數量的質數中的最小值相同.
sql的執行:
(1)使用者請求執行新sql時,oracle在執行基本語法和許可權檢查等步驟後,獲得hash bucket的library cache鎖存器,然後確認庫高速緩衝區上是否存在相同的sql,即相同的lco.若在獲得library cache鎖存器過程中發生爭用,則等待latch:library cache事件.存在相同lco存在時直接跳至第8階段執行,此過程稱之為soft parsing.
(2)若不存在相同sql,在獲得shared pool鎖存器後,從空閒列上查詢最適合大小的空閒chunk.如果在獲得shared pool鎖存器
過程中發生爭用,則等待latch:shared pool事件.oracle一直會擁有shared pool鎖存器,直到確保chunk為止.
(3)若不存在最適大小的空閒chunk,則查詢更大的空閒chunk後分割使用,分割後剩下記憶體區域重新登記到適當的空閒列.
(4)若檢索了所有空閒列也沒有找到恰當的空閒chunk,則檢索lru列.lru列上的chunk是重建的,而且是當前不使用的.
(5)若在lru列上檢索也不能確保適當大小的chunk,則追加分配共享池內的剩餘記憶體空間.
(6)以上過程如果均失敗,則發生錯誤ora-4031.
(7)若找到適當的chunk,對sql相應的handle以exclusive模式獲得library cache lock,並建立lco資訊.建立lco後,library cache lock變換為null模式,將library cache pin以exclusive模式獲得後,建立執行計劃.第2~7號過程稱為hard parsing.
(8)oracle對sql cursor以shared模式獲得library cache lock和library cache pin,並執行sql.這個階段稱為執行階段.
sql cursor所參考的lco,基本上與sql cursor相同的模式獲得library cache lock和library cache pin.但是執行修改物件資訊工作時,對相應的物件所對應的lco以exclusive模式獲得library cache lock和library cache pin.
(9)oracle對執行結束的sql cursor fetch資料.這個過程就是fetch階段.在fetch階段裡,sql cursor將library cache lock變換為null模式,並解除library cache pin.

--transaction
使用者所執行dml操作在oracle內部按如下順序進行:
(1)相應事務分配回滾段,這時優先使用當前聯機狀態的回滾段中一個.回滾段的選擇是隨機的,若另外的事務正在使用則重試3次,在此過程中失敗,則將未聯 機的回滾段聯機後使用.如果此過程也失敗,就會建立新的回滾段,透過這個過程也沒有分配到回滾段,使用另外事務使用中的回滾段中用量最少的回滾段.如果服 務器程式在獲得回滾段時沒有適當的聯機狀態的回滾段,則等待enq:us-contention事件,直到有適當的聯機狀態的回滾段為止.
(2)分配回滾段後,在回滾段上建立事務表slot.
(3)建立事務表後會生成txid(transaction id),再將此txid分配給當前事務.txid透過v$transaction檢視的xidusn,xidslot,xidsqn表現,這個值指向分給 事務的回滾段頭上存在的事務表的準確位置.事務必須在分配撤銷區後得到txid.
(4)事務物件的資料塊載入到高速緩衝區,在塊頭的itl(interested transaction list)上登記事務條目(transaction entry).如果itl上沒有登記條目所需的空間,直到有空間為止,一直等待enq:tx-allocate itl entry事件.
(5)按需要修改的塊的修改資訊儲存到pga,儲存名為change vector.修改一行時,一般分別建立撤銷頭塊(change vector#1),撤銷塊(change vetcor#2),資料塊(change vector#3)相應的change vector.程式將pga的change vector以名為redo record(或redo entry)複製到重做緩衝區.在複製到重做緩衝區的過程中,需獲得redo copy鎖存器,redo allocation鎖存器,redo writing鎖存器,在此過程中若發生鎖存器爭用,分別等待latch:redo copy,latch:redo allocation,latch:redo writing事件.
(6)將之前映像資訊(before image)記錄到撤銷塊,繼而修改資料塊,被修改的資料塊變為髒狀態.而且,高速緩衝區上建立關於已修改的資料塊的cr(consistent read)塊.如果需修改的行正在被另外事務所改變,就要等待事務結束,此時會等待enq:tx-row lock
contention事件.
(7)執行提交後給事務分配scn,提交資訊儲存在重做緩衝區.
(8)回滾段頭的事務表中儲存已成功提交的資訊,解除包括tx鎖在內的所有資源佔有.
(9)重做緩衝區的內容記錄在重做日誌檔案上,修改的塊之後被dbwr記錄到資料檔案中.

--segments
oracle並沒有全部使用透過區新分配的所有空間實際上,所以需要區分已用空間和未用空間的標誌,這個標誌就稱為高水位線(hwm).
oracle提供的段空間管理方法分為flm(手動管理)和assm(自動管理).表空間建立時賦予的segment space management屬性決定flm
和assm的使用與否.
手動模式的空間管理一般稱為flm.使用flm時,oracle利用空閒列方法管理段空間.空閒列就是linked list形式管理空閒塊的方法.段頭塊上管理空閒列的頭和尾的位置.個別資料塊上具有塊是否存在於空閒列和下一個空閒塊的位置資訊,這些資訊的組合構成了 空閒列.使用flm時判斷空閒塊與否,取決於建立表時賦予的pctfree和fctused屬性.oracle給每個段基本上分配一個主空閒列,建立幾個 程式空閒列,數量與建立段時freelists屬性值相同.如果freelist屬性值賦予1(1為預設值),則主空閒列起到程式空閒列的作用.
使用assm後就不有必要指定空閒列屬性,各塊的狀態是透過點陣圖值管理的,從而實現空間管理的自動化.assm對一個段管理兩個hwm.
low hwm以下的塊保證都是已格式化的狀態;high hwm以上的塊都是未格式化的狀態.lhwm和hhwm之間的塊部份被格式化,部份沒有格式化.使用assm基本上是透過oracle管理段空間的,所以 從根本上杜絕了dba因賦予錯誤的storage屬性而引起效能問題的可能性.而且,塊自然地被分散,所以不會出現flm上的空閒列爭用之類的效能問題.

--i/o
i/o效能問題的原因和尋找解決方法的過程:
(1)應用程式層:select,insert,update,delete,truncate...
oracle提供了多種有效i/o處理的方法.其中,parallel query,parallel dml,nologging,direct load,direct read就是最具代表性的例子.根據資料性質,恰當使用cluster,iot,partitioning,bitmap index等功能,有效使用i/o也是應用程式所要承擔的任務.
(2)oracle 記憶體層:buffer cache|pga
a.提供touch count為基礎的有效的lru演算法.
b.透過buffer pinning方法,減少不必要的鎖存器爭用,使得當前讀取工作中使用機率高的塊不至於從記憶體中擠出.
c.利用多重緩衝池功能,區分臨時性塊和記憶體常駐塊進行有效管理.
d.利用不同的塊大小.
e.處理沒必要存於記憶體的大量資料時,可以使用direct path i/o
(3)oracle 段層:datafile,tempfile,tablespace,segment使用臨時表空間.合理使用oracle 8i開始提供的lmt和oracle 9i起提供的assm,可解決因區及段空間的不當管理引發的大部份效能
問題.
(4)os/裸裝置層:asynch i/o,direct i/o,raw device,raid...
oracle建議儘量使用非同步i/o.非同步i/o不僅在讀取工作中執行,而且在執行dbwr或lgwr等寫入工作的程式上也可以非同步地處理工作,因而從整 體上改善了i/o工作的速度.若不能使用非同步i/o,應該使用os級的direct i/o.使用多個dbwr程式也可成為一種方法.

--redo
建立重做資料的原因是為了恢復.oracle透過write ahead rule和log force at commit兩種機制保障資料的恢復.write ahead rule表示在修改資料之前必須建立重做.將dml引起的變化存於高速緩衝區之前,事先存到重做緩衝區.log force at commit表示使用者請求提交後,必須將相關的所有重做記錄存於日誌檔案才能使提交結束.透過這兩種機制,oracle保障使用者修改的所有資料能成功地存 儲在資料重做區域,發生例項故障時能從重做日誌檔案恢復資料.
重做區域上儲存四種區域的修改資料:撤銷段頭,撤銷塊,資料段頭,資料塊.
重做緩衝區的內容會以顯式或隱式的記錄到重做日誌上,LGWR滿足如下條件,將做緩衝區內容存於重做日誌上:
(1)每隔3秒
(2)達到重做緩衝區的1/3或1mb時
(3)使用者執行提交或回滾時
(4)dbwr向lgwr請求寫入工作時(write ahead rule)

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

相關文章