你們可能有些奇怪,爲何說等待事件,先談到了指標體系。其實,正是由於指標體系的發展,才致使等待事件的引入。總結一下,Oracle的指標體系,大體經歷了下面三個階段:sql
以各類命中率爲主要的優化入口依據,常見的有」library cache hit radio「等。但這種方式弊端很大,一個命中率爲99%的系統,不必定就比95%的系統優化的更好。在老的Oracle版本中,每每採用這種方式,如8i、9i等。數據庫
以各類等待事件爲優化入口依據,常見的有"db file sequential read"等。能夠較直觀的瞭解,在一段時間內,數據庫主要經歷了那些等待。這些"瓶頸",每每就是咱們優化的着手點。在10g、11g版本中,普遍使用。安全
以各類資源總體消耗爲優化入口依據。能夠從總體角度瞭解數據庫在一段時間內的消耗狀況。較等待事件的方式,更有歸納性。常見的如"DB Time"。Oracle在不斷增強這個方面的工做。服務器
從上面三個階段可見,等待事件的引入,正是爲了解決以命中率爲指標的諸多弊端。與後面的時間模型相比,等待事件以更加直觀、細粒度的方式觀察Oracle的行爲,每每做爲優化的重要入口。而時間模型,更側重於總體、系統性的瞭解數據庫運行狀態。二者的側重點不一樣。網絡
讓咱們首先從等待事件的分類入手,認識等待事件。從大的分類上來看,等待事件可分爲空閒的、非空閒的兩大部分。在非空閒的等待事件,又可進一步劃分細的類別。session
能夠經過下面的方法,觀察系統包含的等待事件數量及大體分類(如下語句在11g環境運行)。併發
其中WAIT_CLASS爲「Idle」的等待事件就是空閒的,其餘的都是非空閒的等待事件。oracle
空閒等待事件,是指Oracle正等待某種工做,好比用sqlplus登陸以後,但沒有進一步發出任何命令,此時該session就處於SQL*Net message from/to client等待事件狀態,等待用戶發出命令,任何的在診斷和優化數據庫的時候,通常不用過多注意這部分事件。ide
非空閒等待事件,專門針對Oracle的活動,指數據庫任務或應用運行過程當中發生的等待,這些等待事件是調整數據庫的時候應該關注與研究的。性能
此類等待事件是因爲DBA的管理命令引發的,這些命令要求用戶處於等待狀態(好比,重建索引) 。
此類等待事件是因爲用戶應用程序的代碼引發的(好比,鎖等待) 。
此類等待事件和真正應用羣集RAC的資源有關(好比,gc cr block busy等待事件) 。
此類等待事件只包含一種等待事件——在執行了一個commit命令後,等待一個重作日誌寫確認(也就是log file sync) 。
此類等待事件是由內部數據庫資源引發的(好比閂鎖) 。
此類等待事件是由數據庫或實例的不當配置形成的(好比,重作日誌文件尺寸過小,共享池的大小等) 。
此類等待事件意味着會話不活躍,等待工做(好比,sql * net messages from client) 。
和網絡環境相關的一些等待事件(好比sql* net more data to dblink) 。
此類等待事件一般比較少見(好比wait for EMON to spawn) 。
此類等待事件和資源管理相關(好比resmgr: become active') 。
此類等待事件經過是由後臺進程的I/O操做引發的(好比DBWR等待-db file paralle write) 。
此類等待事件一般是由用戶I/O操做引發的(好比db file sequential read) 。
每個等待事件,都代表數據庫的一種活動狀態。從上面的查詢可見,系統內置了不少等待事件,能夠經過數據字典V$EVENT_NAME去了解每一個等待事件。下面經過一個最爲常見的等待事件進行說明。
這個等待事件「db file sequential read」,直譯過來爲「數據文件順序讀取」,是屬於「User I/O」類的等待事件。它一般是與單個數據塊相關的讀取操做,大多數狀況下讀取一個索引塊或者經過索引讀取一個數據塊,會記錄這個等待。該事件說明在單個數據塊上大量等待,該值太高一般是因爲表間鏈接順序很糟糕,或者使用了非選擇性索引。經過將這種等待與statspack報表中已知其它問題聯繫起來(如效率不高的sql),經過檢查確保索引掃描是必須的,並確保多表鏈接的鏈接順序來調整,DB_CACHE_SIZE能夠決定該事件出現的頻率。
該等待事件包含了三個參數,分別爲:
file#: 表明oracle要讀取的文件的絕對文件號
block#: 從這個文件中開始讀取的起始數據塊塊號
blocks: 讀取的block數量。一般是1,表示單個block讀取。
經過上面這些參數,關聯數據字典能夠肯定發生等待事件的對象(即找到了熱點對象)。而後針對不一樣的狀況,有針對性的進行解決。
對等待事件的瞭解越多,可更加深刻理解數據庫運行機制,進而提升總體優化能力。後面,我會介紹一下常見的等待事件。
系統內置了一些視圖,經過這些視圖能夠了解總體(系統級)、局部(會話級)的等待事件發生狀況及各種別事件的分類統計。下面針對一些主要的視圖,說明一下。
系統支持的等待事件,能夠查看等待事件所屬類別、參數的含義等信息。
displays the instance-wide time totals for each registered wait class.
等待事件類別的統計信息(系統級)。經過這一視圖,可從全局角度瞭解系統那類操做等待較多。
等待事件的統計信息(系統級)。展開來講,是提供了自實例啓動後各個等待事件的歸納。經常使用於獲取系統等待信息的歷史影象。而經過兩個snapshot獲取等待項增量,則能夠肯定這段時間內系統的等待項。
主要的字段包括:
自數據庫啓動到如今,此等待事件總等待次數。
此等待事件的總等待時間(單位:百分之一秒)。這個數據表示從數據庫啓動以來這個等待事件在全部會話(包括已經結束和正保持鏈接狀態的會話)總的等待事件之和。
此等待事件的平均等待用時(單位:百分之一秒)。
time_waited/total_waits
此等待事件總等待超時次數。
SQL – 按等待時長查看頂級事件
和v$system_event相相似,記錄的是會話在其生命週期中各個等待事件的累計值。跟前者相比,增長了session_id信息。這些信息也會被同時累積到v$system_event中。須要注意的是,當一個會話從新創建時,統計信息將被設置爲0。
活動會話正在等待的資源或事件信息。在10g將這個視圖和v$session視圖進行了合併。這是一個尋找性能瓶頸的關鍵視圖。它提供了任何狀況下session在數據庫中當前正在等待什麼。當系統存在性能問題時,本視圖能夠作爲一個起點指明探尋問題的方向。
須要注意的是,當等待再也不存在時,會話先前出現的那些等待的歷史也將消失,從而使得過後診斷很是困難。V$SESSION_EVENT提供了累積的但不是很是詳細的數據。能夠經過歷史視圖v$session_wait_history得到歷史信息。
主要的字段包括:
會話當前等待的事件,或者最後一次等待事件。
會話等待事件的時間(單位:百分之一秒)。
值>0: 最後一次等待時間(單位:10ms),當前未在等待狀態。
值=0: session正在等待當前的事件。
值=-1: 最後一次等待時間小於1個統計單位,當前未在等待狀態。
值=-2: 時間統計狀態未置爲可用,當前未在等待狀態。
等待狀態(提供對wait_time和second_in_wait字段的解釋)
SESSION正等待這個事件。
因爲設置了timed_statistics值爲false,致使不能獲得時間信息。表示發生了等待,但時間很短。
3)wait short time:
表示發生了等待,但因爲時間很是短不超過一個時間單位,因此沒有記錄。
4)waited knnow time:
若是session等待而後獲得了所需資源,那麼將從waiting進入本狀態。
Wait_time和Second_in_wait字段值與state相關。
1)state=waiting
wait_time無用,second_in_wait值是實際的等待時間(單位:秒)。
2)state=wait unknow time
wait_time和second_in_wait都無用。
3)state=wait short time
wait_time和second_in_wait都無用。
4)state=waiting known time
wait_time值就是實際等待時間(單位:秒),second_in_wait值無用。
記錄會話最近n次等待事件,即v$session_wait的歷史記錄。默認是記錄10次,可進行修改。
這個視圖記錄了等待事件的柱狀圖分佈,從而能夠對一個等待事件具體分佈有進一步瞭解。在v$session_event或v$system_event視圖記錄的是累積信息以及關於等待的平均值,沒法得知個別等待消耗的時間。
下面將會話等待事件與各視圖之間的關係,總結整理以下:
一個會話一次只發生一個等待事件。若是看到了其餘的等待事件,那僅僅表示在下一個時間片上發生了等待。在某個時刻只存在一個等待。
v$session_wait中的wait_time和second_in_wait字段以秒爲單位,而v$session_event中的time_waited和average_wait字段是以百分之一秒爲單位。
v$session_wait的等待事件結束後,v$session_event的統計信息將會發生改變。
v$session_wait的統計信息意義不大,由於信息是實時變化的。
當v$session_wait裏面的等待事件結束時,v$session_wait中的seconds_in_wait字段值被複制到v$session_event中time_waited字段,而v$session_event視圖的average_time字段同時也被修改。
Oracle的等待事件很是多,不一樣的版本也有些差別。下面對一些常見的等待事件進行說明。但願對你們的平常工做能帶來幫助。
發生緣由:
當一個會話將數據塊從磁盤讀到內存中時,它須要到內存中找到空閒的內存空間來存放這些數據塊,當內存中沒有空閒的空間時,就會產生這個等待。除此以外,還有一種狀況就是會話在作一致性讀時,須要構造數據塊在某個時刻的前映像。此時須要申請內存塊來存放這些新構造的數據塊,若是內存中沒法找到這樣的內存塊,也會發生這個等待事件。
參數含義:
等待訪問數據塊所在的文件id號
等待訪問的數據塊號
10g以前,這個值表示等待事件緣由;10g以後則表示等待事件的類別。
優化方向:根據產生此等待事件的類別不一樣,優化方向也不太同樣。
通常優化方向是優化SQL,減小邏輯讀、物理讀;或者是減小單塊的存儲數據規模。
通常優化方向是增長FREELISTS和FREELIST GROUPS。確保FCTFREE和PCTUSED之間的間隙不是過小,從而能夠最小化FREELIST的塊循環。
通常優化方向爲應用程序,錯峯使用數據對象。
若是是數據庫系統管理UNDO段,通常不須要干預。若是是自行管理的,能夠減小每一個回滾段的事務個數。
發生緣由:
內存中數據塊的存放位置是記錄在一個Hash列表當中的。當一個會話須要訪問某個數據塊時,它首先要搜索這個Hash列表,從列表中得到數據塊的地址,而後經過這個地址去訪問須要的數據塊,這個列表oracle會使用一個latch來保護它的完整性。當一個會話須要訪問這個列表時,須要獲取一個latch,只有這樣,才能保證這個列表在這個會話的瀏覽當中不會發生改變。若是列表過長,致使會話搜索這個列表花費的時間太長,使其餘的會話處於等待狀態。一樣的數據塊被頻繁訪問,就是咱們一般說的熱塊問題。
參數含義:
會話申請的latch在SGA中的虛擬地址。
buffer chains hash列表中的索引值。當這個參數的值等於0xffffff時,說明當前的會話正在等待一個LRU latch。
優化方向:
能夠考慮的優化方向有使用多個buffer pool的方式來建立更多的buffer chains或者使用參數db_block_lru_latches來增長latch的數量,以便於更多的會話能夠得到latch,這兩種方法能夠同時使用。
發生緣由:
一般是與單個數據塊相關的讀取操做,大多數狀況下讀取一個索引塊或者經過索引讀取一個數據塊,會記錄這個等待。可能顯示錶的鏈接順序不佳,或者不加選擇地進行索引。對於大量事務處理、調整良好的系統,這一數值大可能是很正常的,但在某些狀況下,它可能暗示着系統中存在問題。應當將這一等待統計量與性能報告中的已知問題(如效率較低的SQL)聯繫起來。檢查索引掃描,以保證每一個掃描都是必要的,並檢查多表鏈接的鏈接順序。
DB_CACHE_SIZE 也是這些等待出現頻率的決定因素。有問題的散列區域(Hash-area)鏈接應當出如今PGA 內存中,但它們也會消耗大量內存,從而在順序讀取時致使大量等待。它們也可能以直接路徑讀/寫等待的形式出現。
參數含義:
表明oracle要讀取的文件的絕對文件號
從這個文件中開始讀取的起始數據塊塊號
讀取的block數量。一般是1,表示單個block讀取。
優化方向:
這個等待事件,不必定表明必定有問題。若是能肯定是有問題,能夠按照下面優化思路。
修改應用,避免出現大量IO的sql,或者減小其頻率。
增長data buffer,提升命中率。
採用更好的磁盤子系統,減小單個IO的響應時間,防止物理瓶頸的出現。
發生緣由:
這是一個用戶操做引發的等待事件,當用戶發出每次I/O須要讀取多個數據塊這樣的SQL操做時,會產生這個等待事件,最多見的兩種狀況全表掃描和索引快速掃描。這個名稱中的scattered(發散)可能會致使不少人認爲它是以scattered的方式來讀取數據塊的,其實偏偏相反,當發生這種等待事件時,SQL的操做都是順序地讀取數據塊的,好比FTS或IFFS方式。其實這裏scattered指的是讀取的數據塊在內存中的存放方式。它們被讀取到內存中後,是以分散的方式存放在內存中,而不是連續的。
參數含義:
表明oracle要讀取的文件的絕對文件號。
從這個文件中開始讀取的起始數據塊塊號。
讀取的block數量。
優化方向:
這種狀況一般顯示與全表掃描相關的等待。當全表掃描被限制在內存時,它們不多會進入連續的緩衝區內,而是分散於整個緩衝存儲器中。若是這個數目很大,就代表該表找不到索引,或者只能找到有限的索引。儘管在特定條件下執行全表掃描可能比索引掃描更有效,但若是出現這種等待時,最好檢查一下這些全表掃描是否必要。
發生緣由:
這個等待事件發生在會話將數據塊直接讀取到PGA當中而不是SGA中的狀況,這些被讀取的數據一般是這個會話私有的數據,因此不須要放到SGA做爲共享數據,由於這樣作沒有意義。這些數據一般是來自於臨時段上的數據,好比一個會話中SQL的排序數據,並行執行過程當中間產生的數據,以及Hash join、Merge join產生的排序數據,由於這些數據只對當前會話的SQL操做有意義,因此不須要放到SGA當中。當發生direct path read等待事件時,意味着磁盤上有大量的臨時數據產生,好比排序、並行執行等操做,或者意味着PGA中空閒空間不足。
在11g中,全表掃描可能使用direct path read方式,繞過buffer cache,這樣的全表掃描就是物理讀了。在10g中,都是經過gc buffer來讀的,因此不存在direct path read的問題。
參數含義:
文件號
讀取的起始塊號
以first block爲起點,連續讀取的物理塊數
優化方向:
有了這個等待事件,須要區分幾種狀況。一個方向是增大排序區等手段,一個方向是減小讀取IO量或判斷是否經過緩衝區讀的方式更加高效。
發生緣由:
發生在oracle直接從PGA寫數據到數據文件或臨時文件,這個操做能夠繞過SGA。在磁盤排序中最爲常見。對於這種狀況應該找到操做最爲頻繁的數據文件(若是是排序,頗有多是臨時文件),分散負載。
參數含義:
文件號
讀取的起始塊號
以first block爲起點,連續寫入的物理塊數
優化方向:減小IO寫入規模。
發生緣由:
這個等待事件發生在不一樣用戶在共享池中因爲併發操做同一個數據庫對象致使的資源爭用的時候。好比當一個用戶正在對一個表作DDL操做時,其餘的用戶若是要訪問這張表,就會發生library cache lock等待事件,它要一直等到DDL操做完畢後,才能繼續操做。
參數含義:
被加載的對象的地址。
鎖的地址。
被加載對象的數據片斷。
被加載對象在v$db_object_cache視圖中的namespace的名稱。
優化方向:優化方向是查看鎖定對象,減小爭用。
發生緣由:
這個等待事件和library cache lock同樣是發生在共享池中併發操做引發的等待事件。一般來說,若是oracle要對一些pl/sql或視圖這樣的對象作從新編譯,須要將這些對象pin到共享池中。若是此時這個對象被其餘的對象持有,就會產生一個library cache pin的等待。
參數含義:
被加載的對象的地址。
鎖的地址。
被加載對象的數據片斷。
被加載對象在v$db_object_cache視圖中的namespace的名稱。
優化方向:優化方向是查看鎖定對象,減小爭用。
發生緣由:
這是一個用戶會話行爲致使的等待事件。當一個會話發出一個commit命令時,LGWR進程會將這個事務產生的redo log從log buffer裏寫到磁盤上,以保證用戶提交的信息被安全地記錄到數據庫中。會話發出commit指令後,須要等待LGWR將這個事務產生的redo成功寫入到磁盤以後,才能夠繼續進行後續的操做,這個等待事件就叫作log file sync。當系統中出現大量的log file sync等待事件時,應該檢查數據庫中是否有用戶在作頻繁的提交操做。這種等待事件一般發生在OLTP系統上。OLTP系統中存在不少小的事務,若是這些事務頻繁被提交,可能引發大量log file sync的等待事件。
優化方向:
提升LGWR性能,儘可能使用快速磁盤
使用批量提交
適當使用nologging/unrecoverable等選項
發生緣由:
代表前臺服務器進程等待客戶進行響應。這個等待事件是因爲等待用戶進程的響應所引發的,它並不代表數據庫就存在什麼不正常。若是網絡出現故障時,這種等待時間就會常常發生。
發生緣由:
這個等待事件發生在服務器端向客戶端發送消息的時候。當服務器端向客戶端發送消息產生等待時,可能的緣由是用戶端太繁忙,沒法及時接收服務器端送來的消息,也多是網絡問題致使消息沒法從服務器端發送給客戶端。
做者:韓鋒
來源:宜信技術學院