oracle常見的等待事件說明

達芬奇的夢發表於2017-04-18

1. Buffer busy waits

從本質上講,這個等待事件的產生僅說明了一個會話在等待一個Buffer(資料塊),但是導致這個現象的原因卻有很多種。常見的兩種是:
--當一個會話檢視修改一個資料塊,但這個資料塊正在被另一個會話修改時。
--當一個會話需要讀取一個資料塊,但這個資料塊正在被另一個會話讀取到記憶體中時。
在新的版本中,第二種情況已經被獨立出來,以read by other session取代~
Buffer busy waits等待事件常見於資料庫中存在的熱快的時候,當多個使用者頻繁地讀取或者修改同樣的資料塊時,這個等待事件就會產生。 如果等待的時間很長,我們在AWR或者statspack 報告中就可以看到。
這個等待事件有三個引數。 檢視有幾個引數我們可以用以下SQL:

SQL> select name, parameter1, parameter2, parameter3 from v$event_name where name='buffer busy waits';

NAME         PARAMETER1  PARAMETER2  PARAMETER3

--------------------  ----------   ----------  ----------

buffer busy waits    file#      block#     class#

2.Buffer  latch

記憶體中資料塊的存放位置是記錄在一個hash列表(cache buffer chains)當中的。 當一個會話需要訪問某個資料塊時,它首先要搜尋這個hash 列表,從列表中獲得資料塊的地址,然後透過這個地址去訪問需要的資料塊,這個列表Oracle會使用一個latch來保護它的完整性。 當一個會話需要訪問這個列表時,需要獲取一個Latch,只有這樣,才能保證這個列表在這個會話的瀏覽當中不會發生變化。
 
產生buffer latch的等待事件的主要原因是:
Buffer chains太長,導致會話搜尋這個列表花費的時間太長,使其他的會話處於等待狀態。
同樣的資料塊被頻繁訪問,就是我們通常說的熱快問題。

這個等待事件有兩個引數:
Latch addr: 會話申請的latch在SGA中的虛擬地址,透過以下的SQL語句可以根據這個地址找到它對應的Latch名稱:
select * from v$latch a,v$latchname b where addr=latch addr and a.latch#=b.latch#;    

chain#: buffer chains hash 列表中的索引值,當這個引數的值等於s 0xfffffff時,說明當前的會話正在等待一個LRU latch。
 
3.Control file parallel write

當資料庫中有多個控制檔案的複製時,Oracle 需要保證資訊同步地寫到各個控制檔案當中,這是一個並行的物理操作過程,因為稱為控制檔案並行寫,當發生這樣的操作時,就會產生control file parallel write等待事件。
控制檔案頻繁寫入的原因很多,比如:
--日誌切換太過頻繁,導致控制檔案資訊相應地需要頻繁更新。
--系統I/O 出現瓶頸,導致所有I/O出現等待。
 
這個等待事件包含三個引數:
--Files: Oracle 要寫入的控制檔案個數。
--Blocks: 寫入控制檔案的資料塊數目。
--Requests:寫入控制請求的I/O 次數。
 
4.Control file sequential read

當資料庫需要讀取控制檔案上的資訊時,會出現這個等待事件,因為控制檔案的資訊是順序寫的,所以讀取的時候也是順序的,因此稱為控制檔案順序讀,它經常發生在以下情況:
--備份控制檔案
--RAC 環境下不同例項之間控制檔案的資訊共享
--讀取控制檔案的檔案頭資訊
--讀取控制檔案其他資訊
 
這個等待事件有三個引數:
--File#:要讀取資訊的控制檔案的檔案號。
--Block#: 讀取控制檔案資訊的起始資料塊號。
--Blocks:需要讀取的控制檔案資料塊數目。

5.Db file parallel read

這是一個很容易引起誤導的等待事件,實際上這個等待事件和並行操作(比如並行查詢,並行DML)沒有關係。 這個事件發生在資料庫恢復的時候,當有一些資料塊需要恢復的時候,Oracle會以並行的方式把他們從資料檔案中讀入到記憶體中進行恢復操作。

這個等待事件包含三個引數:
--Files: 操作需要讀取的檔案個數。
--Blocks: 操作需要讀取的資料塊個數。
--Requests:操作需要執行的I/O次數。

6.Db file parallel write

這是一個後臺等待事件,它同樣和使用者的並行操作沒有關係,它是由後臺程式DBWR產生的,當後臺程式DBWR想磁碟上寫入髒資料時,會發生這個等待。DBWR會批次地將髒資料並行地寫入到磁碟上相應的資料檔案中,在這個批次作業完成之前,DBWR將出現這個等待事件。 如果僅僅是這一個等待事件,對使用者的操作並沒有太大的影響,當伴隨著出現free buffer waits等待事件時,說明此時記憶體中可用的空間不足,這時候會影響到使用者的操作,比如影響到使用者將髒資料塊讀入到記憶體中。當出現db file parallel write等待事件時,可以透過啟用作業系統的非同步I/O的方式來緩解這個等待。 當使用非同步I/O時,DBWR不在需要一直等到所有資料塊全部寫入到磁碟上,它只需要等到這個資料寫入到一個百分比之後,就可以繼續進行後續的操作。

這個等待事件有兩個引數:
--Requests: 操作需要執行的I/O次數。
--Timeouts:等待的超時時間。

7.Db file scattered read

這個等待事件在實際生產庫中經常可以看到,這是一個使用者操作引起的等待事件,當使用者發出每次I/O需要讀取多個資料塊這樣的SQL 操作時,會產生這個等待事件,最常見的兩種情況是全表掃描(FTS: Full Table Scan)和索引快速掃描(IFFS: index fast full scan)。
這個名稱中的scattered( 發散),可能會導致很多人認為它是以scattered 的方式來讀取資料塊的,其實恰恰相反,當發生這種等待事件時,SQL的操作都是順序地讀取資料塊的,比如FTS或者IFFS方式(如果忽略需要讀取的資料塊已經存在記憶體中的情況)。這裡的scattered指的是讀取的資料塊在記憶體中的存放方式,他們被讀取到記憶體中後,是以分散的方式存在在記憶體中,而不是連續的。

這個等待事件有三個引數:
--File#: 要讀取的資料塊所在資料檔案的檔案號。
--Block#: 要讀取的起始資料塊號。
--Blocks:需要讀取的資料塊數目。

8.Db file sequential read

這個等待事件在實際生產庫也很常見,當Oracle 需要每次I/O只讀取單個資料塊這樣的操作時,會產生這個等待事件。 最常見的情況有索引的訪問(除IFFS外的方式),回滾操作,以ROWID的方式訪問表中的資料,重建控制檔案,對檔案頭做DUMP等。這裡的sequential也並非指的是Oracle 按順序的方式來訪問資料,和db file scattered read一樣,它指的是讀取的資料塊在記憶體中是以連續的方式存放的。

這個等待事件有三個引數:
--File#: 要讀取的資料塊鎖在資料檔案的檔案號。
--Block#: 要讀取的起始資料塊號。
--Blocks:要讀取的資料塊數目(這裡應該等於1)。

9.Db file single write

這個等待事件通常只發生在一種情況下,就是Oracle 更新資料檔案頭資訊時(比如發生Checkpoint)。當這個等待事件很明顯時,需要考慮是不是資料庫中的資料檔案數量太大,導致Oracle 需要花較長的時間來做所有檔案頭的更新操作(checkpoint)。

這個等待事件有三個引數:
--File#: 需要更新的資料塊所在的資料檔案的檔案號。
--Block#:需要更新的資料塊號。
--Blocks:需要更新的資料塊數目(通常來說應該等於1)。

10.Direct path read

這個等待事件發生在會話將資料塊直接讀取到PGA當中而不是SGA中的情況,這些被讀取的資料通常是這個會話私有的資料,所以不需要放到SGA作為共享資料,因為這樣做沒有意義。 這些資料通常是來自與臨時段上的資料,比如一個會話中SQL的排序資料,並行執行過程中間產生的資料,以及Hash Join,merge join產生的排序資料,因為這些資料只對當前的會話的SQL操作有意義,所以不需要放到SGA當中。當發生direct path read等待事件時,意味著磁碟上有大量的臨時資料產生,比如排序,並行執行等操作。 或者意味著PGA中空閒空間不足。
 
這個等待事件有三個引數:
--Descriptor address:       一個指標,指向當前會話正在等待的一個direct read I/O。
--First dba: descriptor address 中最舊的一個I/O資料塊地址。
--Block cnt: descriptor address上下文中涉及的有效的buffer 數量。

11.Direct path write

這個等待事件和direct path read 正好相反,是會話將一些資料從PGA中直接寫入到磁碟檔案上,而不經過SGA。

這種情況通常發生在:
--使用臨時表空間排序(記憶體不足)
--資料的直接載入(使用append方式載入資料)
--並行DML操作。
 
這個等待事件有三個引數:
--Descriptor address: 一個指標,指向當前會話正在等待的一個direct I/O.
--First dba: descriptor address 中最舊的一個I/O資料塊地址。
--Block cnt: descriptor address 上下文中涉及的有效地 buffer 數量。

12.Enqueue

Enqueue 這個詞其實是lock 的另一種描述語。當我們在AWR 報告中發現長時間的enqueue 等待事件時,說明資料庫中出現了阻塞和等待,可以關聯AWR報告中的enqueue activity部分來確定是哪一種鎖定出現了長時間等待。

這個等待事件有2個引數:
--Name: enqueue 的名稱和型別。
--Mode: enqueue的模式。

13.Free buffer waits

當一個會話將資料塊從磁碟讀到記憶體中時,它需要到記憶體中找到空閒的記憶體空間來存放這些資料塊,當記憶體中沒有空閒的空間時,就會產生這個等待;除此之外,還有一種情況就是會話在做一致性讀時,需要構造資料塊在某個時刻的前映像(image),此時需要申請記憶體來存放這些新構造的資料塊,如果記憶體中無法找到這樣的記憶體塊,也會發生這個等待事件。
 
當資料庫中出現比較嚴重的free buffer waits等待事件時,可能的原因是:
--data buffer 太小,導致空閒空間不夠
--記憶體中的髒資料太多,DBWR無法及時將這些髒資料寫到磁碟中以釋放空間
 
這個等待事件包含2個引數:
--File#: 需要讀取的資料塊所在的資料檔案的檔案號。
--Block#: 需要讀取的資料塊塊號。

--查詢阻塞的語句:
SELECT /*+ ORDERED USE_HASH(H,R) */
 h.sid hold_sid, holds.username h_user, holds.lockwait h_lockwait, holds.status h_status, holds.module h_module, holds.row_wait_obj# h_obj, holds.row_wait_row# h_row,
 r.sid wait_sid, waits.username w_user, waits.lockwait w_lockwait, waits.status w_status, waits.module w_module, waits.row_wait_obj# w_obj, waits.row_wait_row# w_row,
 h.type h_type, h.id1 h_id1, h.id2 h_id2, h.lmode h_lmode, h.request h_request, h.ctime h_ctime, h.block h_block,
 r.type r_type, r.id1 r_id1, r.id2 r_id2, r.lmode r_lmode, r.request r_request, r.ctime r_ctime, r.block r_block,
 'alter system kill session ''' || holds.sid || ',' || holds.serial# ||
 '''; -- kill -9 ' || nvl(holdp.spid, 'null') killhold,
 holdsql.sql_text hsql,
 waitsql.sql_text wsql
  FROM v$lock    h,
       v$lock    r,
       v$session holds,
       v$session waits,
       v$process holdp,
       v$sqlarea holdsql,
       v$sqlarea waitsql
 WHERE h.BLOCK = 1 AND
       r.BLOCK = 0 AND
       h.TYPE <> 'MR' AND
       r.TYPE <> 'MR' AND
       h.id1 = r.id1 AND
       h.id2 = r.id2 AND
       h.sid = holds.sid AND
       r.sid = waits.sid AND
       holds.paddr = holdp.addr(+) AND
       holds.sql_address = holdsql.address(+) AND
       holds.sql_hash_value = holdsql.hash_value(+) AND
       waits.sql_address = waitsql.address(+) AND
       waits.sql_hash_value = waitsql.hash_value(+);

14.Latch free

在10g之前的版本里,latch free 等待事件代表了所有的latch等待,在10g以後,一些常用的latch事件已經被獨立了出來:

這個等待事件有三個引數:
--Address: 會話等待的latch 地址。
--Number: latch號,透過這個號,可以從v$latchname 檢視中找到這個latch 的相關的資訊。

15.Library cache lock

這個等待時間發生在不同使用者在共享中由於併發操作同一個資料庫物件導致的資源爭用的時候,比如當一個使用者正在對一個表做DDL 操作時,其他的使用者如果要訪問這張表,就會發生library cache lock等待事件,它要一直等到DDL操作完成後,才能繼續操作。
 
這個事件包含四個引數:
--Handle address: 被載入的物件的地址。
--Lock address: 鎖的地址。
--Mode: 被載入物件的資料片段。
--Namespace: 被載入物件在v$db_object_cache 檢視中namespace名稱。
 
16.Library cache pin

這個等待事件和library cache lock 一樣是發生在共享池中併發操作引起的事件。通常來講,如果Oracle 要對一些PL/SQL 或者檢視這樣的物件做重新編譯,需要將這些物件pin到共享池中。 如果此時這個物件被其他的使用者特有,就會產生一個library cache pin的等待。

這個等待事件也包含四個引數:
--Handle address: 被載入的物件的地址。
--Lock address: 鎖的地址。
--Mode: 被載入物件的資料片段。
--Namespace: 被載入物件在v$db_object_cache 檢視中namespace名稱。

17.Log file parallel write

後臺程式LGWR 負責將log buffer當中的資料寫到REDO 檔案中,以重用log buffer的資料。 如果每個REDO LOG組裡面有2個以上的成員,那麼LGWR程式會並行地將REDO 資訊寫入這些檔案中。
如果資料庫中出現這個等待事件的瓶頸,主要的原因可能是磁碟I/O效能不夠或者REDO 檔案的分佈導致了I/O爭用,比如同一個組的REDO 成員檔案放在相同的磁碟上。

這個等待事件有三個引數:
--Files: 操作需要寫入的檔案個數。
--Blocks: 操作需要寫入的資料塊個數。
--Requests:操作需要執行的I/O次數。

18.Log buffer space

當log buffer 中沒有可用空間來存放新產生的redo log資料時,就會發生log buffer space等待事件。 如果資料庫中新產生的redo log的數量大於LGWR 寫入到磁碟中的redo log 數量,必須等待LGWR 完成寫入磁碟的操作,LGWR必須確保redo log寫到磁碟成功之後,才能在redo buffer當中重用這部分資訊。
 
如果資料庫中出現大量的log buffer space等待事件,可以考慮如下方法:
--增加redo buffer的大小。
--提升磁碟的I/O效能
 
19.Log file sequential read

這個等待事件通常發生在對redo log資訊進行讀取時,比如線上redo 的歸檔操作,ARCH程式需要讀取redo log的資訊,由於redo log的資訊是順序寫入的,所以在讀取時也是按照順序的方式來讀取的。
 
這個等待事件包含三個引數:
--Log#: 發生等待時讀取的redo log的sequence號。
--Block#: 讀取的資料塊號。
--Blocks: 讀取的資料塊個數。

20.Log file single write

這個等待事件發生在更新redo log檔案的檔案頭時,當為日誌組增加新的日誌成員時或者redo log的sequence號改變時,LGWR 都會更新redo log檔案頭資訊。
 
這個等待事件包含三個引數:
--Log#: 寫入的redo log組的編號。
--Block#:寫入的資料塊號。
--Blocks:寫入的資料塊個數。

21.Log file switch(archiving needed)

在歸檔模式下,這個等待事件發生在線上日誌切換(log file switch)時,需要切換的線上日誌還沒有被歸檔程式(ARCH)歸檔完畢的時候。 當線上日誌檔案切換到下一個日誌時,需要確保下一個日誌檔案已經被歸檔程式歸檔完畢,否則不允許覆蓋那個線上日誌資訊(否則會導致歸檔日誌資訊不完整)。出現這樣的等待事件通常是由於某種原因導致ARCH 程式死掉,比如ARCH程式嘗試向目的地寫入一個歸檔檔案,但是沒有成功(介質失效或者其他原因),這時ARCH程式就會死掉。 如果發生這種情況,在資料庫的alert log檔案中可以找到相關的錯誤資訊。

這個等待事件沒有引數。

22.Log file switch(checkpoint incomplete)

當一個線上日誌切換到下一個線上日誌時,必須保證要切換到的線上日誌上的記錄的資訊(比如一些髒資料塊產生的redo log)被寫到磁碟上(checkpoint),這樣做的原因是,如果一個線上日誌檔案的資訊被覆蓋,而依賴這些redo 資訊做恢復的資料塊尚未被寫到磁碟上(checkpoint),此時系統down掉的話,Oracle將沒有辦法進行例項恢復。

在v$log 檢視裡記錄了線上日誌的狀態。 通常來說,線上日誌有三種狀態。
--Active: 這個日誌上面保護的資訊還沒有完成checkpoint。
--Inactive: 這個日誌上面保護的資訊已完成checkpoint。
--Current: 當前的日誌。
 
如果系統中出現大量的log file switch(checkpoint incomplete)等待事件,原因可能是日誌檔案太小或者日誌組太少,所以解決的方法是,增加日誌檔案的大小或者增加日誌組的數量。

這個等待事件沒有引數。

23.Log file sync

這是一個使用者會話行為導致的等待事件,當一個會話發出一個commit命令時,LGWR程式會將這個事務產生的redo log從log buffer裡面寫到磁碟上,以確保使用者提交的資訊被安全地記錄到資料庫中。會話發出的commit指令後,需要等待LGWR將這個事務產生的redo 成功寫入到磁碟之後,才可以繼續進行後續的操作,這個等待事件就叫作log file sync。

以下幾種情況,可能產生這個等待:
--高提交頻率
解決方法是簡單的消除不必要的提交,事務是工作單元。工作單元應該是全部成功或全部失敗。
--緩慢的I/O子系統
較高的IO吞吐良可以改善log file sync和log file parallel write事件的平均等待時間。頻繁的提交會弄亂資料庫佈局和IO子系統。解決辦法是將日誌檔案放裸裝置上或繫結在RAID 0或RAID 0+1中,而不是繫結在RAID 5中。
--過大的日誌緩衝區
過大的日誌緩衝區也可能延長log file sync等待。大型的日誌緩衝區減少後臺寫入的數量,允許LGWR變得懶惰,並導致更多的重做條目堆積在日誌緩衝區中。同時可以調整引數_LOG_IO_SIZE引數,其預設值是LOG_BUFFER的1/3或1MB,取兩者之中較小的值。換句話說,你可以具有較大的日誌緩衝區,但較小的_LOG_IO_SIZE將增加後臺寫入,從而減少log file sync的等待時間.
--過小的日誌緩衝區
過小的日誌緩衝區,還會導致log buffer space等待
--日誌組多少與日誌大小不合適

這個等待事件包含一個引數:
Buffer#: redo buffer 中需要被寫入到磁碟中的buffer。

24.SQL*Net break/reset to client

當出現這個等待事件時,說明伺服器端在給客戶端傳送一個斷開連線或者重置連線的請求,正在等待客戶的響應,通常的原因是伺服器到客戶端的網路不穩定導致的。

這個等待事件包含兩個引數:
--Driver id: 伺服器和客戶端連線使用的協議資訊。
--Breaks:零表示服務端向客戶端傳送一個重置(reset)資訊,非零表示伺服器端向客戶端傳送一個斷開(break)訊息。

25.SQL*Net break/reset to dblink

這個等待事件和SQL*Net break/reset to client 相同。 不過它表示的是資料庫透過dblink訪問另一臺資料庫時,他們之間建立起一個會話,這個等待事件發生在這個會話之間的通訊過程中,同樣如果出現這個等待事件,需要檢查兩臺資料庫之間的通訊問題。

這個等待事件有兩個引數:
--Driver id: 伺服器和客戶端連線使用的協議資訊。
--Breaks:零表示服務端向客戶端傳送一個重置(reset)資訊,非零表示伺服器端向客戶端傳送一個斷開(break)訊息。

26.SQL*Net message from client

這個等待事件基本上是最常見的一個等待事件。 當一個會話建立成功後,客戶端會向伺服器端傳送請求,伺服器端處理完客戶端請求後,將結果返回給客戶端,並繼續等待客戶端的請求,這時候會產生SQL*Net message from client 等待事件。很顯然,這是一個空閒等待,如果客戶端不再向伺服器端傳送請求,伺服器端將一直處於這個等待事件狀態。
 
這個等待事件包含兩個引數:
--Driver id: 伺服器端和客戶端連線使用的協議資訊。
--#bytes: 伺服器端接收到的來自客戶端訊息的位元組數。
 
27.SQL*Net message from dblink

這個等待事件和SQL*Net message from client相同,不過它表示的是資料庫透過dblink 訪問另一個資料庫時,他們之間會建立一個會話,這個等待事件發生在這個會話之間的通訊過程中。
 
這個等待事件也是一個空閒等待事件。

這個事件包含兩個引數:
--Driver id: 伺服器端和客戶端連線使用的協議資訊。
--#bytes: 伺服器端透過dblink 收到的來自另一個伺服器端訊息的位元組數。

28.SQL*Net message to client

這個等待事件發生在伺服器端向客戶端傳送訊息的時候。 當伺服器端向客戶端傳送訊息產生等待時,可能的原因是使用者端太繁忙,無法及時接收伺服器端送來的訊息,也可能是網路問題導致訊息無法從伺服器端傳送到客戶端。
 
這個等待事件有兩個引數:
--Driver id: 伺服器端和客戶端連線使用的協議資訊。
--#bytes: 伺服器端向客戶端傳送訊息的位元組數。

29.SQL*Net message to dblink

這個等待事件和SQL*Net message to client 相同,不過是發生在資料庫伺服器和伺服器之間的等待事件,產生這個等待的原因可能是遠端伺服器繁忙,而無法及時接收傳送過來的訊息,也可能是伺服器之間網路問題導致訊息無法傳送過來。

這個等待時間包含兩個引數:
--Driver id: 伺服器端和客戶端連線使用的協議資訊。
--#bytes: 伺服器端透過dblink傳送給另一個伺服器訊息的位元組數。
 
30.SQL*Net more data from client

伺服器端等待使用者發出更多的資料以便完成操作,比如一個大的SQL文字,導致一個SQL*Net 資料包無法完成傳輸,這樣伺服器端會等待客戶端把整個SQL 文字發過來在做處理,這時候就會產生一個SQL*Net more data from client 等待事件。

這個等待時間包含兩個引數:
--Driver id: 伺服器端和客戶端連線使用的協議資訊。
--#bytes: 伺服器端從客戶端接收到訊息的位元組數。

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

相關文章