AWR報告(四)--常見等待事件

     oracle等待事件是衡量oracle運行狀況的重要依據及指示,等待事件分爲兩類:空閒等待事件和非空閒等待事件, TIMED_STATISTICS = TRUE 那麼等待事件按等待的時間排序,= FALSE那麼事件按等待的數量排序。運行statspack期間必須session上設置TIMED_STATISTICS = TRUE,否則統計的數據將失真。空閒等待事件是oracle正等待某種工作,在診斷和優化數據庫時候,不用過多注意這部分事件,非空閒等待事件專門針對oracle的活動,指數據庫任務或應用程序運行過程中發生的等待,這些等待事件是我們在調整數據庫應該關注的

    對於常見的等待事件,說明如下:

1、db file scattered read 文件分散讀取
該事件通常與全表掃描或者fast full index scan有關。因爲全表掃描是被放入內存中進行的進行的,通常情況下基於性能的考慮,有時候也可能是分配不到足夠長的連續內存空間,所以會將數據塊分散(scattered)讀入Buffer Cache中。該等待過大可能是缺少索引或者沒有合適的索引(可以調整optimizer_index_cost_adj) 。這種情況也可能是正常的,因爲執行全表掃描可能比索引掃描效率更高。當系統存在這些等待時,需要通過檢查來確定全表掃描是否必需的來調整。因爲全表掃描被置於LRU(Least Recently Used,最近最少適用)列表的冷端(cold end),對於頻繁訪問的較小的數據表,可以選擇把他們Cache 到內存中,以避免反覆讀取。當這個等待事件比較顯著時,可以結合v$session_longops 動態性能視圖來進行診斷,該視圖中記錄了長時間(運行時間超過6 秒的)運行的事物,可能很多是全表掃描操作(不管怎樣,這部分信息都是值得我們注意的)。
關於參數OPTIMIZER_INDEX_COST_ADJ=n:該參數是一個百分比值,缺省值爲100,可以理解爲FULL SCAN COST/INDEX SCAN COST。當n%* INDEX SCAN COST<FULL SCAN COST時,oracle會選擇使用索引。在具體設置的時候,我們可以根據具體的語句來調整該值。如果我們希望某個statement使用索引,而實際它確走全表掃描,可以對比這兩種情況的執行計劃不同的COST,從而設置一個更合適的值。

2、db file sequential read文件順序讀取整代碼,特別是表連接最常見的等待事件

     該事件說明在單個數據塊上大量等待,該值過高通常是由於表間連接順序很糟糕(沒有正確選擇驅動行源),或者使用了非選擇性索引。通過將這種等待與statspack報表中已知其它問題聯繫起來(如效率不高的sql),通過檢查確保索引掃描是必須的,並確保多表連接的連接順序來調整。

      每事務低於200算正常的,這裏是133。

     何時會出現這種等待:http://www.askmaclean.com/archives/db-file-sequential-read-wait-event.html

3、buffer busy wait 緩衝區忙增大DB_CACHE_SIZE,加速檢查點,調整代碼

當進程需要存取SGA中的buffer的時候,它會依次執行如下步驟的操作:

當緩衝區以一種非共享方式或者如正在被讀入到緩衝時,就會出現該等待。該值不應該大於1%。當出 現等待問題時,可以檢查緩衝等待統計部分(或V$WAITSTAT),確定該等待發生在什麼位置:

如果等待是否位於段頭(Segment Header)。這種情況表明段中的空閒列表(freelist)的塊比較少。可以考慮增加空閒列表(freelist,對於Oracle8i DMT)或者增加freelist groups(在很多時候這個調整是立竿見影的(alter table tablename strorage(freelists 2)),在8.1.6之前,這個freelists參數不能動態修改;在8.1.6及以後版本,動態修改feelists需要設置COMPATIBLE至少爲8.1.6)。也可以增加PCTUSED與PCTFREE之間距離(PCTUSED-to-pctfree gap),其實就是說降低PCTUSED的值,儘快使塊返回freelist列表被重用。如果支持自動段空間管理(ASSM),也可以使用ASSM模式,這是在ORALCE 920以後的版本中新增的特性。

如果這一等待位於undo header,可以通過增加回滾段(rollback segment)來解決緩衝區的問題。

如果等待位於undo block上,我們需要增加提交的頻率,使block可以儘快被重用;使用更大的回滾段;降低一致讀所選擇的表中數據的密度;增大DB_CACHE_SIZE。

如果等待處於data block,表明出現了hot block,可以考慮如下方法解決: ①將頻繁併發訪問的表或數據移到另一數據塊或者進行更大範圍的分佈(可以增大pctfree值 ,擴大數據分佈,減少競爭),以避開這個"熱點"數據塊。②也可以減小數據塊的大小,從而減少一個數據塊中的數據行數,降低數據塊的熱度,減小競爭;③檢查對這些熱塊操作的SQL語句,優化語句。④增加hot block上的initrans值。但注意不要把initrans值設置的過於高了,通常設置爲5就足夠了。因爲增加事務意味着要增加ITL事務槽,而每個ITL事務槽將佔用數據塊中24個字節長度。默認情況下,每個數據塊或者索引塊中是ITL槽是2個,在增加initrans的時候,可以考慮增大數據塊所在的表的PCTFREE值,這樣Oracle會利用PCTFREE部分的空間增加ITL slot數量,最大達到maxtrans指定。

如果等待處於index block,應該考慮重建索引、分割索引或使用反向鍵索引。爲了防止與數據塊相關的緩衝忙等待,也可以使用較小的塊,在這種情況下,單個塊中的記錄就較少,所以這個塊就不是那麼"繁忙"。或者可以設置更大的PCTFREE,使數據擴大物理分佈,減少記錄間的熱點競爭。在執行DML (insert/update/ delete)時,Oracle向數據塊中寫入信息,對於多事務併發訪問的數據表,關於ITL的競爭和等待可能出現,爲了減少這個等待,可以增加initrans,使用多個ITL槽。在Oracle9i 中,可以使用ASSM這個新特性Oracle 使用位圖來管理空間使用,減小爭用。

當進程需要存取SGA中的buffer的時候,它會依次執行如下步驟的操作:
1.獲得cache buffers chains latch,遍歷那條buffer chain直到找到需要的buffer header
2.根據需要進行的操作類型(讀或寫),它需要在buffer header上獲得一個共享或獨佔模式的buffer pin或者buffer lock
3.若進程獲得buffer header pin,它會釋放獲得的cache buffers chains latch,然後執行對buffer block的操作
4.若進程無法獲得buffer header pin,它就會在buffer busy waits事件上等待
進程之所以無法獲得buffer header pin,是因爲爲了保證數據的一致性,同一時刻一個block只能被一個進程pin住進行存取,因此當一個進程需要存取buffer cache中一個被其他進程使用的block的時候,這個進程就會產生對該blockbuffer busy waits事件。
截至Oracle 9ibuffer busy waits事件的p1,p2,p3三個參數分別是file#,block#id分別表示等待的buffer block所在的文件編號塊編號和具體的等待原因編號到了Oracle10g前兩個參數沒變3個參數變成了塊類型編號這一點可以通過查詢v$event_name視圖來進行驗證

PHP code:
Oracle 9i
SQL>select parameter1,parameter2,parameter3 from v$event_name where name='buffer busy waits'
PARAMETER1                  PARAMETER2                 PARAMETER3
------------------------ ------------------------ ------------------------
file#                            block#                          id
Oracle 10g
PARAMETER1                  PARAMETER2                 PARAMETER3
------------------------ ------------------------ ------------------------
file#                            block#                          class#

 

在診斷buffer busy waits事件的過程中獲取如下信息會很有用
1.獲取產生buffer busy waits事件的等待原因編號這可以通過查詢該事件的p3參數值獲得
2.獲取產生此事件的SQL語句可以通過如下的查詢獲得
select sql_text from v$sql t1,v$session t2,v$session_wait t3
where t1.address=t2.sql_address and t1.hash_value=t2.sql_hash_value
and t2.sid=t3.sid and t3.event='buffer busy waits';
3.獲取等待的塊的類型以及所在的segment可以通過如下查詢獲得

PHP code:
select 'Segment Header'class,a.segment_type,a.segment_name,a.partition_name from dba_segments a,v$session_wait b
where a.header_file=b.p1and a.header_block=b.p2and b.event='buffer busy waits'
union
select 'Freelist Groups'class,a.segment_type,a.segment_name,a.partition_name from dba_segments a,v$session_wait b
where a.header_file=b.p1and b.p2 between a.header_block+1and (a.header_block+a.freelist_groups) and a.freelist_groups>1and b.event='buffer busy waits'
union
select a.segment_type||' block'class,a.segment_type,a.segment_name,a.partition_name from dba_extents a,v$session_wait b
where a.file_id=b.p1and b.p2 between a.block_idand a.block_id+a.blocks-1and b.event='buffer busy waits'and not exists(select 1 from dba_segments where
header_file=b.p1and header_block=b.p2);

 

查詢的第一部分如果等待的塊類型是segment header那麼可以直接拿buffer busy waits事件的p1p2參數去dba_segments視圖中匹配header_fileheader_block字段即可找到等待的segment名稱和segment類型進行相應調整
查詢的第二部分如果等待的塊類型是freelist groups也可以在dba_segments視圖中找出對應的segment名稱和segment類型注意這裏的參數p2表示的freelist groups的位置是在segmentheader_block+1header_block+freelist groups組數之間並且freelist groups組數大於1
查詢的第三部分如果等待的塊類型是普通的數據塊那麼可以用p1p2參數和dba_extents進行聯合查詢得到block所在的segment名稱和segment類型

對於不同的等待塊類型我們採取不同的處理辦法
1.data segment header
進程經常性的訪問data segment header通常有兩個原因獲取或修改process freelists信息、擴展高水位標記針對第一種情況進程頻繁訪問process freelists信息導致freelist爭用我們可以增大相應的segment對象的存儲參數freelist或者freelist groups若由於數據塊頻繁進出freelist而導致進程經常要修改freelist則可以將pctfree值和pctused值設置較大的差距從而避免數據塊頻繁進出freelist對於第二種情況由於該segment空間消耗很快而設置的next extent過小導致頻繁擴展高水位標記解決的辦法是增大segment對象的存儲參數next extent或者直接在創建表空間的時候設置extent size uniform
2.data block
某一或某些數據塊被多個進程同時讀寫成爲熱點塊可以通過如下這些辦法來解決這個問題
(1)降低程序的併發度如果程序中使用了parallel查詢降低parallel degree以免多個parallel slave同時訪問同樣的數據對象而形成等待降低性能
(2)調整應用程序使之能讀取較少的數據塊就能獲取所需的數據減少buffer getsphysical reads
(3)減少同一個block中的記錄數使記錄分佈於更多的數據塊中這可以通過若干途徑實現可以調整segment對象的pctfree可以將segment重建到block size較小的表空間中還可以用alter table minimize records_per_block語句減少每塊中的記錄數
(4)若熱點塊對象是類似自增id字段的索引則可以將索引轉換爲反轉索引打散數據分佈分散熱點塊
3.undo segment header
undo segment header爭用是因爲系統中undo segment不夠需要增加足夠的undo segment根據undo segment管理方法若是手工管理模式需要修改rollback_segments初始化參數來增加rollback segment若是自動管理模式可以減小transactions_per_rollback_segment初始化參數的值來使oracle自動增多rollback segment的數量
4.undo block
undo block爭用是由於應用程序中存在對數據的讀和寫同時進行讀進程需要到undo segment中去獲得一致性數據解決辦法是錯開應用程序修改數據和大量查詢數據的時間

小結buffer busy waits事件是oracle等待事件中比較複雜的一個其形成原因很多需要根據p3參數對照Oracle提供的原因代碼表進行相應的診斷10g以後則需要根據等待的block類型結合引起等待時間的具體SQL進行分析採取相應的調整措施

4、latch free

    當閂鎖丟失率高於0.5%時,需要調整這個問題。詳細的我們在後面的Latch Activity for DB部分說明。

latch是一種低級排隊機制,用於保護SGA中共享內存結構。latch就像是一種快速地被獲取和釋放的內存鎖。用於防止共享內存結構被多個用戶同時訪問。如果latch不可用,就會記錄latch釋放失敗(latch free miss )。有兩種與閂有關的類型:

  ■ 立刻。

  ■ 可以等待。

  假如一個進程試圖在立刻模式下獲得閂,而該閂已經被另外一個進程所持有,如果該閂不能立可用的話,那麼該進程就不會爲獲得該閂而等待。它將繼續執行另一個操作。

  大多數latch問題都與以下操作相關:

  沒有很好的是用綁定變量(library cache latch)、重作生成問題(redo allocation latch)、緩衝存儲競爭問題(cache buffers LRU chain),以及buffer cache中的存在"熱點"塊(cache buffers chain)。

  通常我們說,如果想設計一個失敗的系統,不考慮綁定變量,這一個條件就夠了,對於異構性強的系統,不使用綁定變量的後果是極其嚴重的。

  另外也有一些latch等待與bug有關,應當關注Metalink相關bug的公佈及補丁的發佈。當latch miss ratios大於0.5%時,就應當研究這一問題。

  Oracle的latch機制是競爭,其處理類似於網絡裏的CSMA/CD,所有用戶進程爭奪latch,對於願意等待類型(willing-to-wait)的latch,如果一個進程在第一次嘗試中沒有獲得latch,那麼它會等待並且再嘗試一次,如果經過_spin_count次爭奪不能獲得latch, 然後該進程轉入睡眠狀態,持續一段指定長度的時間,然後再次醒來,按順序重複以前的步驟.在8i/9i中默認值是_spin_count=2000。

  如果SQL語句不能調整,在8.1.6版本以上,Oracle提供了一個新的初始化參數: CURSOR_SHARING可以通過設置CURSOR_SHARING = force 在服務器端強制綁定變量。設置該參數可能會帶來一定的副作用,對於Java的程序,有相關的bug,具體應用應該關注Metalink的bug公告。

 

***Latch問題及可能解決辦法
------------------------------
* Library Cache and Shared Pool (未綁定變量---綁定變量,調整shared_pool_size)
每當執行SQL或PL/SQL存儲過程,包,函數和觸發器時,這個Latch即被用到.Parse操作中此Latch也會被頻繁使用.
* Redo Copy (增大_LOG_SIMULTANEOUS_COPIES參數)
重做拷貝Latch用來從PGA向重做日誌緩衝區拷貝重做記錄.
* Redo Allocation (最小化REDO生成,避免不必要提交)
Latch用來分配重做日誌緩衝區中的空間,可以用NOLOGGING來減緩競爭.
* Row Cache Objects (增大共享池)
數據字典競爭.過度parsing.
* Cache Buffers Chains (_DB_BLOCK_HASH_BUCKETS應增大或設爲質數)
"過熱"數據塊造成了內存緩衝鏈Latch競爭.
* Cache Buffers Lru Chain (調整SQL,設置DB_BLOCK_LRU_LATCHES,或使用多個緩衝區池)
掃描全部內存緩衝區塊的LRU(最近最少使用)鏈時要用到內存緩衝區LRU鏈Latch.太小內存緩衝區、過大的內存緩衝區吞吐量、過多的內存中進行的排序操作、DBWR速度跟不上工作負載等會引起此Latch競爭。

 

5、Enqueue

     隊列是一種鎖,保護一些共享資源,防止併發的DML操作。隊列採用FIFO策略,注意latch並不是採用的FIFO機制。比較常見的有3種類型的隊列:ST隊列,HW隊列,TX4隊列。
ST Enqueue的等待主要是在字典管理的表空間中進行空間管理和分配時產生的。解決方法:1)將字典管理的表空間改爲本地管理模式 2)預先分配分區或者將有問題的字典管理的表空間的next extent設置大一些。
HW Enqueue是用於segment的HWM的。當出現這種等待的時候,可以通過手工分配extents來解決。
TX4 Enqueue等待是最常見的等待情況。通常有3種情況會造成這種類型的等待:1)唯一索引中的重複索引。解決方法:commit或者rollback以釋放隊列。 2)對同一個位圖索引段(bitmap index fragment)有多個update,因爲一個bitmap index fragment可能包含了多個rowid,所以當多個用戶更新時,可能一個用戶會鎖定該段,從而造成等待。解決方法同上。3)有多個用戶同時對一個數據塊作update,當然這些DML操作可能是針對這個數據塊的不同的行,如果此時沒有空閒的ITL槽,就會產生一個block-level鎖。解決方法:增大表的initrans值使創建更多的ITL槽;或者增大表的pctfree值,這樣oracle可以根據需要在pctfree的空間創建更多的ITL槽;使用smaller block size,這樣每個塊中包含行就比較少,可以減小衝突發生的機會。

AWR報告分析--等待事件-隊列.doc

6、Free Buffer 釋放緩衝區

    這個等待事件表明系統正在等待內存中的可用空間,這說明當前Buffer 中已經沒有Free 的內存空間。如果應用設計良好,SQL 書寫規範,充分綁定變量,那這種等待可能說明Buffer Cache 設置的偏小,你可能需要增大DB_CACHE_SIZE。該等待也可能說明DBWR 的寫出速度不夠,或者磁盤存在嚴重的競爭,可以需要考慮增加檢查點、使用更多的DBWR 進程,或者增加物理磁盤的數量,分散負載,平衡IO。

7Log file single write

   該事件僅與寫日誌文件頭塊相關,通常發生在增加新的組成員和增進序列號時。頭塊寫單個進行,因爲頭塊的部分信息是文件號,每個文件不同。更新日誌文件頭這個操作在後臺完成,一般很少出現等待,無需太多關注。

8log file parallel write

   log bufferredo 記錄到redo log文件主要指常規寫操作(相對於log file sync)。如果你的Log group 存在多個組成員,當flush log buffer 時,寫操作是並行的,這時候此等待事件可能出現。儘管這個寫操作並行處理,直到所有I/O 操作完成該寫操作纔會完成(如果你的磁盤支持異步IO或者使用IO SLAVE,那麼即使只有一個redo log file member,也有可能出現此等待)。這個參數和log file sync 時間相比較可以用來衡量log file 的寫入成本。通常稱爲同步成本率。改善這個等待的方法是將redo logs放到I/O快的盤中,儘量不使用raid5,確保表空間不是處在熱備模式下,確保redo log和data的數據文件位於不同的磁盤中。

9、log file sync:

   當一個用戶提交或回滾數據時,LGWR將會話的redo記錄從日誌緩衝區填充到日誌文件中,用戶的進程必須等待這個填充工作完成。在每次提交時都出現,如果這個等待事件影響到數據庫性能,那麼就需要修改應用程序的提交頻率, 爲減少這個等待事件,須一次提交更多記錄,或者將重做日誌REDO LOG 文件訪在不同的物理磁盤上,提高I/O的性能。

當一個用戶提交或回滾數據時,LGWR 將會話期的重做由日誌緩衝器寫入到重做日誌中。日誌文件同步過程必須等待這一過程成功完成。爲了減少這種等待事件,可以嘗試一次提交更多的記錄(頻繁的提交會帶來更多的系統開銷)。將重做日誌置於較快的磁盤上,或者交替使用不同物理磁盤上的重做日誌,以降低歸檔對LGWR的影響。

  對於軟RAID,一般來說不要使用RAID 5,RAID5 對於頻繁寫入得系統會帶來較大的性能損失,可以考慮使用文件系統直接輸入/輸出,或者使用裸設備(raw device),這樣可以獲得寫入的性能提高。

Log file parallel write慢=> log file sync慢=>commit慢,commit慢則釋放行鎖慢。 Rac flush redo也受到寫redo慢的影響,則出現gc buffer busy release/acquire,前後相互作用è enq:TX大幅出現

 

10、log buffer space:

日誌緩衝區寫的速度快於LGWR寫REDOFILE的速度,可以增大日誌文件大小,增加日誌緩衝區的大小,或者使用更快的磁盤來寫數據。

 

當你將日誌緩衝(log buffer)產生重做日誌的速度比LGWR 的寫出速度快,或者是當日志切換(log switch)太慢時,就會發生這種等待。這個等待出現時,通常表明redo log buffer 過小,爲解決這個問題,可以考慮增大日誌文件的大小,或者增加日誌緩衝器的大小。

  另外一個可能的原因是磁盤I/O 存在瓶頸,可以考慮使用寫入速度更快的磁盤。在允許的條件下設置可以考慮使用裸設備來存放日誌文件,提高寫入效率。在一般的系統中,最低的標準是,不要把日誌文件和數據文件存放在一起,因爲通常日誌文件只寫不讀,分離存放可以獲得性能提升。

 

11、logfile switch:通常是因爲歸檔速度不夠快。

     表示所有的提交(commit)的請求都需要等待"日誌文件切換"的完成。Log file Switch 主要包含兩個子事件:
log file switch (archiving needed) 這個等待事件出現時通常是因爲日誌組循環寫滿以後,第一個日誌歸檔尚未完成,出現該等待。出現該等待,可能表示io 存在問題。解決辦法:①可以考慮增大日誌文件和增加日誌組;②移動歸檔文件到快速磁盤;③調整log_archive_max_processes。
log file switch (checkpoint incomplete) 當日志組都寫完以後,LGWR 試圖寫第一個log file,如果這時數據庫沒有完成寫出記錄在第一個log file 中的dirty 塊時(例如第一個檢查點未完成),該等待事件出現。該等待事件通常表示你的DBWR 寫出速度太慢或者IO 存在問題。爲解決該問題,你可能需要考慮增加額外的DBWR 或者增加你的日誌組或日誌文件大小,或者也可以考慮增加checkpoint的頻率。

12、DB File Parallel Write文件被DBWR並行寫時發生。解決辦法:改善IO性能。

處理此事件時,需要注意

1db file parallel write事件只屬於DBWR進程。

2緩慢的DBWR可能影響前臺進程。

3大量的db file parallel write等待時間很可能是I/O問題引起的。(在確認os支持異步io的前提下,你可以在系統中檢查disk_asynch_io參數,保證爲TRUE。可以通過設置db_writer_processes來提高DBWR進程數量,當然前提是不要超過cpu的數量。)
     DBWR進程執行經過SGA的所有數據庫寫入,當開始寫入時,DBWR進程編譯一組髒塊(dirty block),並且將系統寫入調用發佈到操作系統。DBWR進程查找在各個時間內寫入的塊,包括每隔3秒的一次查找,當前臺進程提交以清除緩衝區中的內容時:在檢查點處查找,當滿足_DB_LARGE_DIRTY_QUEUE_DB_BLOCK_MAX_DIRTY_TARGETFAST_START_MTTR_TARGET閥值時,等等。
    雖然用戶會話從來沒有經歷過db file parallel write等待事件但這並不意味着它們不會受到這種事件的影響。緩慢的DBWR寫入性能可以造成前臺會話在write complete waitsfree buffer waits事件上等待。DBWR寫入性能可能受到如下方面的影響:I/O操作的類型(同步或異步)、存儲設備(裸設備或成熟的文件系統)、數據庫佈局和I/O子系統配置。需要查看的關鍵數據庫統計是當db file parallel writefree buffer waitswrite complete waits等待事件互相關聯時,系統範圍內的TIME_WAITEDAVERAGE_WAIT
    如果db file parallel write平均等待時間大於10cs或者100ms),則通常表明緩慢的I/O吞吐量。可以通過很多方法來改善平均等待時間。主要的方法是使用正確類型的I/O操作。如果數據文件位於裸設備(raw device)上,並且平臺支持異步I/O,就應該使用異步寫入。但是,如果數據庫位於文件系統上,則應該使用同步寫入和直接I/O(這是操作系統直接I/O)。除了確保正在使用正確類型的I/O操作,還應該檢查你的數據庫佈局並使用常見的命令監控來自操作系統的I/O吞吐量。例如sar -diostat -dxnC
    db file parallel write平均等待時間高並且系統繁忙時,用戶會話可能開始在free buffer waits事件上等待。這是因爲DBWR進程不能滿足釋放緩衝區的需求。如果free buffer waits事件的TIME_WAITED高,則應該在高速緩存中增加緩衝區數量之前說明DBWR I/O吞吐量的問題。
    db file parallel write平均等待時間的另一個反響是在write complete waits等待事件上的高TIME_WAITED。前臺進程不允許修改正在傳輸到磁盤的塊。換句話說,也就是位於DBWR批量寫入中的塊。前臺的會話在write complete waits等待事件上等待。因此,write complete waits事件的出現,一定標誌着緩慢的DBWR進程,可以通過改進DBWR I/O吞吐量修正這種延遲。

13、DB File Single Write:當文件頭或別的單獨塊被寫入時發生,這一等待直到所有的I/O調用完成。解決辦法:改善IO性能。

14、DB FILE Scattered Read:當掃描整個段來根據初始化參數db_file_multiblock_read_count讀取多個塊時發生,因爲數據可能分散在不同的部分,這與分條或分段)相關,因此通常需要多個分散的讀來讀取所有的數據。等待時間是完成所有I/O調用的時間。解決辦法:改善IO性能。

這種情況通常顯示與全表掃描相關的等待。
當數據庫進行全表掃時,基於性能的考慮,數據會分散(scattered)讀入Buffer Cache。如果這個等待事件比較顯著,可能說明對於某些全表掃描的表,沒有創建索引或者沒有創建合適的索引,我們可能需要檢查這些數據表已確定是否進行了正確的設置。

然而這個等待事件不一定意味着性能低下,在某些條件下Oracle會主動使用全表掃描來替換索引掃描以提高性能,這和訪問的數據量有關,在CBOOracle會進行更爲智能的選擇,在RBOOracle更傾向於使用索引。

因爲全表掃描被置於LRULeast Recently Used最近最少適用列表的冷端cold end),對於頻繁訪問的較小的數據表可以選擇把他們Cache到內存中以避免反覆讀取。

當這個等待事件比較顯著時,可以結合v$session_longops動態性能視圖來進行診斷,該視圖中記錄了長時間(運行時間超過6秒的)運行的事物,可能很多是全表掃描操作(不管怎樣,這部分信息都是值得我們注意的)。

15、DB FILE Sequential Read:當前臺進程對數據文件進行常規讀時發生,包括索引查找和別的非整段掃描以及數據文件塊丟棄等待。等待時間是完成所有I/O調用的時間。解決辦法:改善IO性能。

如果這個等待事件比較顯著,可能表示在多表連接中,表的連接順序存在問題,沒有正確地使用驅動表;或者可能索引的使用存在問題,並非索引總是最好的選擇。在大多數情況下,通過索引可以更爲快速地獲取記錄,所以對於編碼規範、調整良好的數據庫,這個等待事件很大通常是正常的。有時候這個等待過高和存儲分佈不連續、連續數據塊中部分被緩存有關,特別對於DML頻繁的數據表,數據以及存儲空間的不連續可能導致過量的單塊讀,定期的數據整理和空間回收有時候是必須的。

需要注意在很多情況下,使用索引並不是最佳的選擇,比如讀取較大表中大量的數據,全表掃描可能會明顯快於索引掃描,所以在開發中就應該注意,對於這樣的查詢應該進行避免使用索引掃描。

16、Direct Path Read:一般直接路徑讀取是指將數據塊直接讀入PGA中。一般用於排序、並行查詢和read ahead操作。這個等待可能是由於I/O造成的。使用異步I/O模式或者限制排序在磁盤上,可能會降低這裏的等待時間。

與直接讀取相關聯的等待事件。當ORACLE將數據塊直接讀入會話的PGA(進程全局區)中,同時繞過SGA(系統全局區)。PGA中的數據並不和其他的會話共享。即表明,讀入的這部分數據該會話獨自使用,不放於共享的SGA中。

在排序操作(order by/group by/union/distinct/rollup/合併連接)由於PGA中的SORT_AREA_SIZE空間不足造成需要使用臨時表空間來保存中間結果當從臨時表空間讀入排序結果時產生direct path read等待事件。

使用HASH連接的SQL語句,將不適合位於內存中的散列分區刷新到臨時表空間中。爲了查明匹配SQL謂詞的行,臨時表空間中的散列分區被讀回到內存中(目的是爲了查明匹配SQL謂詞的行)ORALCE會話在direct path read等待事件上等待。

使用並行掃描的SQL語句也會影響系統範圍的direct path read等待事件。在並行執行過程中direct path read等待事件與從屬查詢有關而與父查詢無關運行父查詢的會話基本上會在PX Deq:Execute Reply上等待從屬查詢會產生direct path read等待事件。

直接讀取可能按照同步或異步的方式執行,取決於平臺和初始化參數disk_asynch_io參數的值。使用異步I/O時,系統範圍的等待的事件的統計可能不準確,會造成誤導作用。

17、direct path write:直接路徑寫該等待發生在,系統等待確認所有未完成的異步I/O 都已寫入磁盤。對於這一寫入等待,我們應該找到I/O 操作最爲頻繁的數據文件(如果有過多的排序操作,很有可能就是臨時文件),分散負載,加快其寫入操作。如果系統存在過多的磁盤排序,會導致臨時表空間操作頻繁,對於這種情況,可以考慮使用Local管理表空間,分成多個小文件,寫入不同磁盤或者裸設備。

DSS系統中,存在大量的direct path read是很正常的,但是在OLTP系統中,通常顯著的直接路徑讀(direct path read)都意味着系統應用存在問題,從而導致大量的磁盤排序讀取操作。

直接路徑寫(direct paht write)通常發生在Oracle直接從PGA寫數據到數據文件或臨時文件,這個寫操作可以繞過SGA

這類寫入操作通常在以下情況被使用
·直接路徑加載
·並行DML操作
·磁盤排序
·對未緩存的“LOB”段的寫入隨後會記錄爲direct path write(lob)等待。

最爲常見的直接路徑寫,多數因爲磁盤排序導致。對於這一寫入等待,我們應該找到I/O操作最爲頻繁的數據文件(如果有過多的排序操作,很有可能就是臨時文件),分散負載,加快其寫入操作。

18、control file parallel write:當server 進程更新所有控制文件時,這個事件可能出現。如果等待很短,可以不用考慮。如果等待時間較長,檢查存放控制文件的物理磁盤I/O 是否存在瓶頸。
多個控制文件是完全相同的拷貝,用於鏡像以提高安全性。對於業務系統,多個控制文件應該存放在不同的磁盤上,一般來說三個是足夠的,如果只有兩個物理硬盤,那麼兩個控制文件也是可以接受的。在同一個磁盤上保存多個控制文件是不具備實際意義的。減少這個等待,可以考慮如下方法:①減少控制文件的個數(在確保安全的前提下)。②如果系統支持,使用異步IO。③轉移控制文件到IO 負擔輕的物理磁盤。

19control file sequential read

control file single write :控制文件連續讀/控制文件單個寫對單個控制文件I/O 存在問題時,這兩個事件會出現。如果等待比較明顯,檢查單個控制文件,看存放位置是否存在I/O 瓶頸。

20library cache pin

該事件通常是發生在先有會話在運行PL/SQL,VIEW,TYPES等object時,又有另外的會話執行重新編譯這些object,即先給對象加上了一個共享鎖,然後又給它加排它鎖,這樣在加排它鎖的會話上就會出現這個等待。P1,P2可與x$kglpn和x$kglob表相關
X$KGLOB (Kernel Generic Library Cache Manager Object)
X$KGLPN (Kernel Generic Library Cache Manager Object Pins)
-- 查詢X$KGLOB,可找到相關的object,其SQL語句如下
(即把V$SESSION_WAIT中的P1raw與X$KGLOB中的KGLHDADR相關連)
select kglnaown,kglnaobj from X$KGLOB
where KGLHDADR =(select p1raw from v$session_wait
where event='library cache pin')
-- 查出引起該等待事件的阻塞者的sid
select sid from x$kglpn , v$session
where KGLPNHDL in
(select p1raw from v$session_wait
where wait_time=0 and event like 'library cache pin%')
and KGLPNMOD <> 0
and v$session.saddr=x$kglpn.kglpnuse
-- 查出阻塞者正執行的SQL語句
select sid,sql_text
from v$session, v$sqlarea
where v$session.sql_address=v$sqlarea.address
and sid=<阻塞者的sid>
這樣,就可找到"library cache pin"等待的根源,從而解決由此引起的性能問題。

21、library cache lock
該事件通常是由於執行多個DDL操作導致的,即在library cache object上添加一個排它鎖後,又從另一個會話給它添加一個排它鎖,這樣在第二個會話就會生成等待。可通過到基表x$kgllk中查找其對應的對象。
-- 查詢引起該等待事件的阻塞者的sid、會話用戶、鎖住的對象
select b.sid,a.user_name,a.kglnaobj
from x$kgllk a , v$session b
where a.kgllkhdl in
(select p1raw from v$session_wait
where wait_time=0 and event = 'library cache lock')
and a.kgllkmod <> 0
and b.saddr=a.kgllkuse
當然也可以直接從v$locked_objects中查看,但沒有上面語句直觀根據sid可以到v$process中查出pid,然後將其kill或者其它處理。

 

22、RAC系統常見的等待:gc buffer busy wait 熱塊

 

23、對於常見的一些IDLE wait事件舉例:

dispatcher timer                  

lock element cleanup              

Null event                        

parallel query dequeue wait       

parallel query idle wait - Slaves 

pipe get                          

PL/SQL lock timer                 

pmon timer- pmon                  

rdbms ipc message                 

slave wait                        

smon timer                        

SQL*Net break/reset to client     

SQL*Net message from client       

SQL*Net message to client         

SQL*Net more data to client       

virtual circuit status            

client message                    

SQL*Net message from client  

下面是關於這裏的常見的等待事件和解決方法的一個快速預覽

等待事件

一般解決方法

Sequential Read 順序讀

調整相關的索引和選擇合適的驅動行源

Scattered Read  離散讀

表明出現很多全表掃描。優化code,cache小表到內存中。

Free Buffer

增大DB_CACHE_SIZE,增大checkpoint的頻率,優化代碼

Buffer Busy Segment header

增加freelist或者freelistgroups

Buffer Busy Data block

隔離熱塊;使用反轉索引;使用更小的塊;增大表的initrans

Buffer Busy Undo header

增加回滾段的數量或者大小

Buffer Busy Undo block

Commit more;增加回滾段的數量或者大小

Latch Free

檢查具體的等待latch類型,解決方法參考後面介紹

EnqueueST

使用本地管理的表空間或者增加預分配的盤區大小

EnqueueHW

在HWM之上預先分配盤區

EnqueueTX4

在表或者索引上增大initrans的值或者使用更小的塊

Log Buffer Space

增大LOG_BUFFER改善I/O

Log File Switch

增加或者增大日誌文件

Log file sync

減小提交的頻率;使用更快的I/O;或者使用裸設備

Write complete waits

增加DBWR;提高CKPT的頻率;

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章