Oracle常見等待事件


1Buffer 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#

2Buffer  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。

3Control file parallel write當數據庫中有多個控制文件的拷貝時,Oracle 需要保證信息同步地寫到各個控制文件當中,這是一個並行的物理操作過程,因為稱為控制文件並行寫,當發生這樣的操作時,就會產生control file parallel write等待事件。

控制文件頻繁寫入的原因很多,比如:

·         日志切換太過頻繁,導致控制文件信息相應地需要頻繁更新。

·         系統I/O 出現瓶頸,導致所有I/O出現等待。

 

這個等待事件包含三個參數:

·         Files: Oracle 要寫入的控制文件個數。

·         Blocks: 寫入控制文件的數據塊數目。

·         Requests:寫入控制請求的I/O 次數。

4Control file sequential read當數據庫需要讀取控制文件上的信息時,會出現這個等待事件,因為控制文件的信息是順序寫的,所以讀取的時候也是順序的,因此稱為控制文件順序讀,它經常發生在以下情況:

·         備份控制文件

·         RAC 環境下不同實例之間控制文件的信息共享

·         讀取控制文件的文件頭信息

·         讀取控制文件其他信息
 

這個等待事件有三個參數:

·         File#:要讀取信息的控制文件的文件號。

·         Block#: 讀取控制文件信息的起始數據塊號。

·         Blocks:需要讀取的控制文件數據塊數目。

5Db file parallel read這是一個很容易引起誤導的等待事件,實際上這個等待事件和並行操作(比如並行查詢,並行DML)沒有關系。 這個事件發生在數據庫恢復的時候,當有一些數據塊需要恢復的時候,Oracle會以並行的方式把他們從數據文件中讀入到內存中進行恢復操作。這個等待事件包含三個參數:

·         Files: 操作需要讀取的文件個數。

·         Blocks: 操作需要讀取的數據塊個數。

·         Requests:操作需要執行的I/O次數。

6Db file parallel write這是一個后台等待事件,它同樣和用戶的並行操作沒有關系,它是由后台進程DBWR產生的,當后台進程DBWR想磁盤上寫入臟數據時,會發生這個等待。DBWR會批量地將臟數據並行地寫入到磁盤上相應的數據文件中,在這個批次作業完成之前,DBWR將出現這個等待事件。 如果僅僅是這一個等待事件,對用戶的操作並沒有太大的影響,當伴隨着出現free buffer waits等待事件時,說明此時內存中可用的空間不足,這時候會影響到用戶的操作,比如影響到用戶將臟數據塊讀入到內存中。當出現db file parallel write等待事件時,可以通過啟用操作系統的異步I/O的方式來緩解這個等待。 當使用異步I/O時,DBWR不在需要一直等到所有數據塊全部寫入到磁盤上,它只需要等到這個數據寫入到一個百分比之后,就可以繼續進行后續的操作。

這個等待事件有兩個參數:

·         Requests: 操作需要執行的I/O次數

·         Timeouts:等待的超時時間。

7Db file scattered read這個等待事件在實際生產庫中經常可以看到,這是一個用戶操作引起的等待事件,當用戶發出每次I/O需要讀取多個數據塊這樣的SQL 操作時,會產生這個等待事件,最常見的兩種情況是全表掃描(FTS: Full Table Scan)和索引快速掃描(IFFS: index fast full scan)。

 

這個名稱中的scattered( 發散),可能會導致很多人認為它是以scattered 的方式來讀取數據塊的,其實恰恰相反,當發生這種等待事件時,SQL的操作都是順序地讀取數據塊的,比如FTS或者IFFS方式(如果忽略需要讀取的數據塊已經存在內存中的情況)。這里的scattered指的是讀取的數據塊在內存中的存放方式,他們被讀取到內存中后,是以分散的方式存在在內存中,而不是連續的。

這個等待事件有三個參數:

·         File#: 要讀取的數據塊所在數據文件的文件號。

·         Block#: 要讀取的起始數據塊號。

·         Blocks:需要讀取的數據塊數目。

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

這個等待事件有三個參數:

·         File#: 要讀取的數據塊鎖在數據文件的文件號。

·         Block#: 要讀取的起始數據塊號。

·         Blocks:要讀取的數據塊數目(這里應該等於1)。

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

這個等待事件有三個參數:

·         File#: 需要更新的數據塊所在的數據文件的文件號。

·         Block#:需要更新的數據塊號。

·         Blocks:需要更新的數據塊數目(通常來說應該等於1)。

10Direct 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 數量。

11Direct 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 數量。

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

這個等待事件有2個參數:

·         Name: enqueue 的名稱和類型。

·         Mode: enqueue的模式。

13Free 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(+);

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

這個等待事件有三個參數:

·         Address: 會話等待的latch 地址。

·         Number: latch號,通過這個號,可以從v$latchname 視圖中找到這個latch 的相關的信息。

15Library cache lock這個等待時間發生在不同用戶在共享中由於並發操作同一個數據庫對象導致的資源爭用的時候,比如當一個用戶正在對一個表做DDL 操作時,其他的用戶如果要訪問這張表,就會發生library cache lock等待事件,它要一直等到DDL操作完成后,才能繼續操作。

 

這個事件包含四個參數:

·         Handle address: 被加載的對象的地址。

·         Lock address: 鎖的地址。

·         Mode: 被加載對象的數據片段。

·         Namespace: 被加載對象在v$db_object_cache 視圖中namespace名稱。

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

這個等待事件也包含四個參數:

·         Handle address: 被加載的對象的地址。

·         Lock address: 鎖的地址。

·         Mode: 被加載對象的數據片段。

·         Namespace: 被加載對象在v$db_object_cache 視圖中namespace名稱。

17Log 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次數。

18Log 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性能

19Log file sequential read這個等待事件通常發生在對redo log信息進行讀取時,比如在線redo 的歸檔操作,ARCH進程需要讀取redo log的信息,由於redo log的信息是順序寫入的,所以在讀取時也是按照順序的方式來讀取的。

 

這個等待事件包含三個參數:

·         Log#: 發生等待時讀取的redo log的sequence號。

·         Block#: 讀取的數據塊號。

·         Blocks: 讀取的數據塊個數。

20Log file single write這個等待事件發生在更新redo log文件的文件頭時,當為日志組增加新的日志成員時或者redo log的sequence號改變時,LGWR 都會更新redo log文件頭信息。

 

這個等待事件包含三個參數:

·         Log#: 寫入的redo log組的編號。

·         Block#:寫入的數據塊號。

·         Blocks:寫入的數據塊個數。

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

這個等待事件沒有參數。

22Log file switch(checkpoint incomplete)當一個在線日志切換到下一個在線日志時,必須保證要切換到的在線日志上的記錄的信息(比如一些臟數據塊產生的redo log)被寫到磁盤上(checkpoint),這樣做的原因是,如果一個在線日志文件的信息被覆蓋,而依賴這些redo 信息做恢復的數據塊尚未被寫到磁盤上(checkpoint),此時系統down掉的話,Oracle將沒有辦法進行實例恢復。

v$log 視圖里記錄了在線日志的狀態。 通常來說,在線日志有三種狀態。

·         Active: 這個日志上面保護的信息還沒有完成checkpoint。

·         Inactive: 這個日志上面保護的信息已完成checkpoint。

·         Current: 當前的日志。

如果系統中出現大量的log file switch(checkpoint incomplete)等待事件,原因可能是日志文件太小或者日志組太少,所以解決的方法是,增加日志文件的大小或者增加日志組的數量。

這個等待事件沒有參數。

23Log 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。

24SQL*Net break/reset to client當出現這個等待事件時,說明服務器端在給客戶端發送一個斷開連接或者重置連接的請求,正在等待客戶的響應,通常的原因是服務器到客戶端的網絡不穩定導致的。

這個等待事件包含兩個參數:

·         Driver id: 服務器和客戶端連接使用的協議信息。

·         Breaks:零表示服務端向客戶端發送一個重置(reset)信息,非零表示服務器端向客戶端發送一個斷開(break)消息。

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

這個等待事件有兩個參數:

·         Driver id: 服務器和客戶端連接使用的協議信息。

·         Breaks:零表示服務端向客戶端發送一個重置(reset)信息,非零表示服務器端向客戶端發送一個斷開(break)消息。

26SQL*Net message from client這個等待事件基本上是最常見的一個等待事件。 當一個會話建立成功后,客戶端會向服務器端發送請求,服務器端處理完客戶端請求后,將結果返回給客戶端,並繼續等待客戶端的請求,這時候會產生SQL*Net message from client 等待事件。很顯然,這是一個空閑等待,如果客戶端不再向服務器端發送請求,服務器端將一直處於這個等待事件狀態。

 

這個等待事件包含兩個參數:

·         Driver id: 服務器端和客戶端連接使用的協議信息。

·         #bytes: 服務器端接收到的來自客戶端消息的字節數。

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

 

這個等待事件也是一個空閑等待事件。

這個事件包含兩個參數:

·         Driver id: 服務器端和客戶端連接使用的協議信息。

·         #bytes: 服務器端通過dblink 收到的來自另一個服務器端消息的字節數。

28SQL*Net message to client這個等待事件發生在服務器端向客戶端發送消息的時候。 當服務器端向客戶端發送消息產生等待時,可能的原因是用戶端太繁忙,無法及時接收服務器端送來的消息,也可能是網絡問題導致消息無法從服務器端發送到客戶端。 

 

這個等待事件有兩個參數:

·         Driver id: 服務器端和客戶端連接使用的協議信息。

·         #bytes: 服務器端向客戶端發送消息的字節數。

29SQL*Net message to dblink這個等待事件和SQL*Net message to client 相同,不過是發生在數據庫服務器和服務器之間的等待事件,產生這個等待的原因可能是遠程服務器繁忙,而無法及時接收發送過來的消息,也可能是服務器之間網絡問題導致消息無法發送過來。

這個等待時間包含兩個參數:

·         Driver id: 服務器端和客戶端連接使用的協議信息。

·         #bytes: 服務器端通過dblink發送給另一個服務器消息的字節數。

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

這個等待時間包含兩個參數:

·         Driver id: 服務器端和客戶端連接使用的協議信息。

·         #bytes: 服務器端從客戶端接收到消息的字節數。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM