1.Parse 階段常見的等待事件:
- Library cache pin
這個等待事件和library cache lock 一樣是發生在共享池中並發操作引起的事件。通常來講,如果Oracle 要對一些PL/SQL 或者視圖這樣的對象做重新編譯,需要將這些對象pin到共享池中。 如果此時這個對象被其他的用戶特有,就會產生一個library cache pin的等待。
這個等待事件也包含四個參數:
Handle address: 被加載的對象的地址。
Lock address: 鎖的地址。
Mode: 被加載對象的數據片段。
Namespace: 被加載對象在v$db_object_cache 視圖中namespace名稱。
- Library cache pin
這個等待事件和library cache lock 一樣是發生在共享池中並發操作引起的事件。通常來講,如果Oracle 要對一些PL/SQL 或者視圖這樣的對象做重新編譯,需要將這些對象pin到共享池中。 如果此時這個對象被其他的用戶特有,就會產生一個library cache pin的等待。
這個等待事件也包含四個參數:
Handle address: 被加載的對象的地址。
Lock address: 鎖的地址。
Mode: 被加載對象的數據片段。
Namespace: 被加載對象在v$db_object_cache 視圖中namespace名稱
- latch:shared pool
- pin S wait on X
- ibrary cache: mutex X/cursor: pin S
2.Execute階段常見的等待事件:
- db file sequential read
這個等待事件在實際生產庫也很常見,當Oracle 需要每次I/O只讀取單個數據塊這樣的操作時,會產生這個等待事件。 最常見的情況有索引的訪問(除IFFS外的方式),回滾操作,以ROWID的方式訪問表中的數據,重建控制文件,對文件頭做DUMP等。
這里的sequential也並非指的是Oracle 按順序的方式來訪問數據,和db file scattered read一樣,它指的是讀取的數據塊在內存中是以連續的方式存放的。
這個等待事件有三個參數:
File#: 要讀取的數據塊鎖在數據文件的文件號。
Block#: 要讀取的起始數據塊號。
Blocks:要讀取的數據塊數目(這里應該等於1)。
- 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:需要讀取的數據塊數目。
- Free buffer waits
當一個會話將數據塊從磁盤讀到內存中時,它需要到內存中找到空閑的內存空間來存放這些數據塊,當內存中沒有空閑的空間時,就會產生這個等待;除此之外,還有一種情況就是會話在做一致性讀時,需要構造數據塊在某個時刻的前映像(image),此時需要申請內存來存放這些新構造的數據塊,如果內存中無法找到這樣的內存塊,也會發生這個等待事件。
當數據庫中出現比較嚴重的free buffer waits等待事件時,可能的原因是:
(1) data buffer 太小,導致空閑空間不夠
(2) 內存中的臟數據太多,DBWR無法及時將這些臟數據寫到磁盤中以釋放空間
這個等待事件包含2個參數:
File#: 需要讀取的數據塊所在的數據文件的文件號。
Block#: 需要讀取的數據塊塊號。
- latch: cache buffers lru chain
Oracle 的 Buffer Cache 是共享內存,可以為眾多並發進程並發訪問,所以在搜索的過程中必須獲取 Latch(Latch是 Oracle 的一種串行鎖機制,用於保護共享內存結構),鎖定內存結構,防止並發訪問損壞內存中的數據(我們必須認識到對於數據的訪問、Buffer 的存取就意味着多次的 Latch 訪問,而過於嚴重的 Latch 競爭常常是系統的瓶頸所在.
- buffer busy wait
從本質上講,這個等待事件的產生僅說明了一個會話在等待一個Buffer(數據塊),但是導致這個現象的原因卻有很多種。常見的兩種是:當一個會話視圖修改一個數據塊,但這個數據塊正在被另一個會話修改時。當一個會話需要讀取一個數據塊,但這個數據塊正在被另一個會話讀取到內存中時。Oracle 操作的最小單位是塊(Block),即使你要修改一條記錄,也需要對這條記錄所在的這個數據塊做操作。 當你對這個數據塊做修改時,其他的會話將被阻止對這個數據塊上的數據做修改(即使其他用戶修改的不是當前用戶修改的數據),但是可以以一致性的方式讀取這個數據塊(from undo)。當前的用戶修改完這個數據塊后,將會立即釋放掉加在這個數據塊上的排他鎖,這樣另一個會話就可以繼續修改它。 修改操作是一個非常短暫的時間,這種加鎖的機制我們叫Latch。當一個會話修改一個數據塊時,是按照以下步驟來完成的:
以排他的方式獲得這個數據塊(Latch)
-
修改這個數據塊。
-
釋放Latch。
-
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#
-
在下面的示例中,查詢的方法和這個一樣,所以其他事件對參數的查詢將不做過多的說明。
-
File#: 等待訪問數據塊所在的文件id號。
-
Blocks:等待訪問的數據塊號。
-
ID: 在10g之前,這個值表示一個等待時間的原因,10g之后則表示等待事件的類別。
3. Fetch階段常見的等待事件
- SQL*NET more data to client
當服務器端有太多的數據需要發給客戶端時,可能會產生SQL*Net more data to client等待事件,也可能由於網絡問題導致服務器無法及時地將信息或者處理結果發送給客戶端,同樣會產生這個等待。
這個等待時間包含兩個參數:
Driver id: 服務器端和客戶端連接使用的協議信息。
#bytes: 服務器端向客戶端發送消息的字節數。