Oracle的等待事件是衡量Oracle健全狀態的重要依據及指標。等待事件的概念是在Oracle7.0.1.2中引入的,大致有100個等待事件。在Oracle 8.0中這個數目增加到了大約150個,在Oracle8i中大約有200個事件,在Oracle9i中大約有360個等待事件。主要有兩種類別的等待事件,即空閑(idle)等待事件和非空閑(non-idle)等待事件。
空閑事件指Oracle正等待某種工作,在診斷和最佳化資料庫的時候,我們不用過多注意這部分事件。
常見的空閑事件有:
• dispatcher timer
• lock element cleanup
• Null event
• parallel query dequeue wait
• parallel query idle wait - Slaves
• pipe get
• PL/SQL lock timer
• pmon timer- pmon
• rdbms ipc message
• slave wait
• smon timer
• SQL*Net break/reset to client
• SQL*Net message from client
• SQL*Net message to client
• SQL*Net more data to client
• virtual circuit status
• client message
非空閑等待事件專門針對Oracle的活動,指資料庫任務或應用運行過程中發生的等待,這些等待事件是我們在調整資料庫的時候應該關注與研究的。
一些常見的非空閑等待事件有:
• db file scattered read
• db file sequential read
• buffer busy waits
• free buffer waits
• enqueue
• latch free
• log file parallel write
• log file sync
1. db file scattered read-DB 檔案分散讀取
這種情況通常顯示與全表掃描相關的等待。當資料庫進行全表掃時,基於效能的考慮,資料會分散(scattered)讀入Buffer Cache。如果這個等待事件比較顯著,可能說明對於某些全表掃描的表,沒有建立索引或者沒有建立合適的索引,我們可能需要檢查這些資料表已確定是否進行了正確的設定。
然而這個等待事件不一定意味著效能低下,在某些條件下Oracle 會主動使用全表掃描來替換索引掃描以提高效能,這和訪問的資料量有關,在CBO 下Oracle 會進行更為智能的選擇,在RBO 下Oracle 更傾向於使用索引。
因為全表掃描被置於LRU(Least Recently Used,最近最少適用)列表的冷端(cold end),對於頻繁訪問的較小的資料表,可以選擇把他們Cache 到記憶體中,以避免反覆讀取。
當這個等待事件比較顯著時,可以結合v$session_longops 動態效能檢視來進行診斷,該視圖中記錄了長時間(已耗用時間超過6 秒的)啟動並執行事物,可能很多是全表掃描操作(不管怎樣,這部分資訊都是值得我們注意的)。
2. db file sequential read-DB 檔案順序讀取。
這一事件通常顯示與單個資料區塊相關的讀取操作(如索引讀取)。如果這個等待事件比較顯著,可能表示在多表串連中,表的串連順序存在問題,可能沒有正確的使用驅動表;或者可能說明不加選擇地進行索引。
在大多數情況下我們說,通過索引可以更為快速的擷取記錄,所以對於一個編碼規範、調整良好的資料庫,這個等待很大是很正常的。但是在很多情況下,使用索引並不是最佳的選擇,比如讀取較大表中大量的資料,全表掃描可能會明顯快於索引掃描,所以在開發中我們就應該注意,對於這樣的查詢應該進行避免使用索引掃描。
3. Free Buffer-釋放緩衝區
這個等待事件表明系統正在等待記憶體中的可用空間,這說明當前Buffer 中已經沒有Free 的記憶體空間。如果應用設計良好,SQL 書寫規範,充分綁定變數,那這種等待可能說明Buffer Cache 設定的偏小,你可能需要增大DB_BUFFER_CACHE。
Free Buffer 等待可能說明DBWR 的寫出速度不夠,或者磁碟存在嚴重的競爭,可以需要考慮增加檢查點、使用更多的DBWR 進程,或者增加物理磁碟的數量,分散負載,平衡IO。
4. Buffer Busy-緩衝區忙
該等待事件表示正在等待一個以unshareable方式使用的緩衝區,或者表示當前正在被讀入buffer cache。一般來說Buffer Busy Wait不應大於1%。檢查緩衝等待統計部分(或V$WAITSTAT),看一下等待是否位於段頭(Segment Header)。如果是,可以考慮增加自由列表(freelist,對於Oracle8i DMT)或者增加freelist groups(在很多時候這個調整是立竿見影的,在8.1.6之前,這個freelists參數不能動態修改;在8.1.6及以後版本,動態修改feelists需要設定COMPATIBLE至少為8.1.6).
如果這一等待位於undo header,可以通過增加復原段(rollback segment)來解決緩衝區的問題。如果等待位於undo block上,我們可能需要檢查相關應用,適當減少大規模的一致性讀取,或者降低一致性讀取(consistent read)的表中的資料密度或者增大DB_CACHE_SIZE。
如果等待處於data block,可以考慮將頻繁並發訪問的表或資料移到另一資料區塊或者進行更大範圍的分布(可以增加pctfree值 ,擴大資料分布,減少競爭),以避開這個"熱點"資料區塊,或者可以考慮增加表中的自由列表或使用本地化管理的資料表空間(Locally Managed Tablespaces)。
如果等待處於索引塊,應該考慮重建索引、分割索引或使用反向鍵索引。為了防止與資料區塊相關的緩衝忙等待,也可以使用較小的塊:在這種情況下,單個塊中的記錄就較少,所以這個塊就不是那麼"繁忙";或者可以設定更大的pctfree,使資料擴大物理分布,減少記錄間的熱點競爭。
在執行DML (insert/update/ delete)時,Oracle向資料區塊中寫入資訊,對於多事務並發訪問的資料表,關於ITL的競爭和等待可能出現,為了減少這個等待,可以增加initrans,使用多個ITL槽。在Oracle9i 中,引入了一個新概念:ASSM(Segment Space Management Auto)。通過這個新特性Oracle 使用位元影像來管理空間使用。
ASSM 結合LMT 徹底改變了Oracle 的儲存機制,位元影像freelist 能夠減輕緩衝區忙等待(buffer busy wait),這個問題在Oracle9i 以前的版本裡曾是一個嚴重的問題。
Oracle 宣稱ASSM 顯著地提高了DML 並行作業的效能,因為(同一個)位元影像的不同部分可以被同時使用,這樣就消除了尋找剩餘空間的序列化。根據Oracle 的測試結果,使用位元影像freelist 會消除所有分段頭部(對資源)的爭奪,還能獲得超快的並發插入操作。在Oracle9i 之中,Buffer Busy wait 不再常見!