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