1. 程式人生 > >Oracle常見的等待事件說明(上)

Oracle常見的等待事件說明(上)

Oracle資料庫系統可移植性好、使用方便、功能強,適用於各類大、中、小、微機環境,因此,它廣受大資料圈相關人士的青睞。但是,在使用過程中,偶爾會遇到一些等待事件,這是為什麼呢?大聖眾包威客平臺為你一一道來。

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