空閒事件指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 秒的)運行的事物,可能很多是全表掃描操作(不管怎樣,這部分信息都是值得我們注意的)。
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 不再常見!
5. latch free-latch 釋放
latch是一種低級排隊機制,用於保護SGA中共享內存結構。latch就像是一種快速地被獲取和釋放的內存鎖。用於防止共享內存結構被多個用戶同時訪問。如果latch不可用,就會記錄latch釋放失敗(latch free miss )。有兩種與闩有關的類型:
■ 立刻。
■ 可以等待。
假如一個進程試圖在立刻模式下獲得闩,而該闩已經被另外一個進程所持有,如果該闩不能立可用的話,那麼該進程就不會為獲得該闩而等待。它將繼續執行另一個操作。
大多數latch問題都與以下操作相關:
沒有很好的是用綁定變量(library cache latch)、重作生成問題(redo allocation latch)、緩沖存儲競爭問題(cache buffers LRU chain),以及buffer cache中的存在"熱點"塊(cache buffers chain)。
通常我們說,如果想設計一個失敗的系統,不考慮綁定變量,這一個條件就夠了,對於異構性強的系統,不使用綁定變量的後果是極其嚴重的。
另外也有一些latch等待與bug有關,應當關注Metalink相關bug的公布及補丁的發布。當latch miss ratiOS大於0.5%時,就應當研究這一問題。
Oracle的latch機制是競爭,其處理類似於網絡裡的CSMA/CD,所有用戶進程爭奪latch, 對於願意等待類型(willing-to-wait)的latch,如果一個進程在第一次嘗試中沒有獲得latch,那麼它會等待並且再嘗試一次,如果經過_spin_count次爭奪不能獲得latch, 然後該進程轉入睡眠狀態,持續一段指定長度的時間,然後再次醒來,按順序重復以前的步驟.在8i/9i中默認值是_spin_count=2000。
如果SQL語句不能調整,在8.1.6版本以上,Oracle提供了一個新的初始化參數: CURSOR_SHARING可以通過設置CURSOR_SHARING = force 在服務器端強制綁定變量。設置該參數可能會帶來一定的副作用,對於Java的程序,有相關的bug,具體應用應該關注Metalink的bug公告。
7. Log Buffer Space-日志緩沖空間
當你將日志緩沖(log buffer)產生重做日志的速度比LGWR 的寫出速度快,或者是當日志切換(log switch)太慢時,就會發生這種等待。這個等待出現時,通常表明redo log buffer 過小,為解決這個問題,可以考慮增大日志文件的大小,或者增加日志緩沖器的大小。
另外一個可能的原因是磁盤I/O 存在瓶頸,可以考慮使用寫入速度更快的磁盤。在允許的條件下設置可以考慮使用裸設備來存放日志文件,提高寫入效率。在一般的系統中,最低的標准是,不要把日志文件和數據文件存放在一起,因為通常日志文件只寫不讀,分離存放可以獲得性能提升。
8. Log File Switch-日志文件切換
當這個等待出現時,表示所有的提交(commit)的請求都需要等待"日志文件切換"的完成。
Log file Switch 主要包含兩個子事件:
log file switch (archiving needed)
log file switch (checkpoint incomplete)
log file switch (archiving needed)
這個等待事件出現時通常是因為日志組循環寫滿以後,第一個日志歸檔尚未完成,出現該等待。出現該等待,可能表示io 存在問題。解決辦法:
可以考慮增大日志文件和增加日志組
移動歸檔文件到快速磁盤
調整log_archive_max_processes .
log file switch (checkpoint incomplete)-日志切換(檢查點未完成)
當你的日志組都寫完以後,LGWR 試圖寫第一個log file,如果這時數據庫沒有完成寫出記錄在第一個log file 中的dirty 塊時(例如第一個檢查點未完成),該等待事件出現。
該等待事件通常表示你的DBWR 寫出速度太慢或者IO 存在問題。
為解決該問題,你可能需要考慮增加額外的DBWR 或者增加你的日志組或日志文件大小。
9. log file sync-日志文件同步
當一個用戶提交或回滾數據時,LGWR 將會話期的重做由日志緩沖器寫入到重做日志中。日志文件同步過程必須等待這一過程成功完成。為了減少這種等待事件,可以嘗試一次提交更多的記錄(頻繁的提交會帶來更多的系統開銷)。將重做日志置於較快的磁盤上,或者交替使用不同物理磁盤上的重做日志,以降低歸檔對LGWR的影響。
對於軟RAID,一般來說不要使用RAID 5,RAID5 對於頻繁寫入得系統會帶來較大的性能損失,可以考慮使用文件系統直接輸入/輸出,或者使用裸設備(raw device),這樣可以獲得寫入的性能提高。
10. log file single write該事件僅與寫日志文件頭塊相關,通常發生在增加新的組成員和增進序列號時。
頭塊寫單個進行,因為頭塊的部分信息是文件號,每個文件不同。更新日志文件頭這個操作在後台完成,一般很少出現等待,無需太多關注。
11. log file parallel write
從log buffer 寫redo 記錄到redo log 文件,主要指常規寫操作(相對於log file sync)。如果你的Log group 存在多個組成員,當flush log buffer 時,寫操作是並行的,這時候此等待事件可能出現。
盡管這個寫操作並行處理,直到所有I/O 操作完成該寫操作才會完成(如果你的磁盤支持異步IO或者使用IO SLAVE,那麼即使只有一個redo log file member,也有可能出現此等待)。
這個參數和log file sync 時間相比較可以用來衡量log file 的寫入成本。通常稱為同步成本率。
12. control file parallel write-控制文件並行寫
當server 進程更新所有控制文件時,這個事件可能出現。如果等待很短,可以不用考慮。如果等待時間較長,檢查存放控制文件的物理磁盤I/O 是否存在瓶頸。
多個控制文件是完全相同的拷貝,用於鏡像以提高安全性。對於業務系統,多個控制文件應該存放在不同的磁盤上,一般來說三個是足夠的,如果只有兩個物理硬盤,那麼兩個控制文件也是可以接受的。在同一個磁盤上保存多個控制文件是不具備實際意義的。減少這個等待,可以考慮如下方法:
減少控制文件的個數(在確保安全的前提下)
如果系統支持,使用異步IO
轉移控制文件到IO 負擔輕的物理磁盤
13. control file sequential read/ control file single write 控制文件連續讀/控制文件單個寫對單個控制文件I/O 存在問題時,這兩個事件會出現。如果等待比較明顯,檢查單個控制文件,看存放位置是否存在I/O 瓶頸。
14. direct path write-直接路徑寫該等待發生在,系統等待確認所有未完成的異步I/O 都已寫入磁盤。對於這一寫入等待,我們應該找到I/O 操作最為頻繁的數據文件(如果有過多的排序操作,很有可能就是臨時文件),分散負載,加快其寫入操作。
如果系統存在過多的磁盤排序,會導致臨時表空間操作頻繁,對於這種情況,可以考慮使用Local管理表空間,分成多個小文件,寫入不同磁盤或者裸設備。
16. Idle Event-空閒事件
最後我們來看幾個空閒等待事件。一般來說,空閒等待是指系統因為無事可做的等待,或者等待用戶的請求或響應等,通常我們可以忽略這些等待事件。空閒事件可以通過stats$idle_event 表查詢得到。
我們看一下系統的主要空閒等待事件,對這些事件大家應該有個大致的印象,如果你的Top 5 等待事件中,主要都是這些事件,那麼一般來說你的系統是比價清閒的。