等待事件 db file scattered read
db file scattered read 等待事件,在生產環境之中,這個等待事件可能更為常見。 這個事件表明使用者程序正在讀資料到 Buffer Cache 中,等待直到物理 I/O呼叫返回。 DB File Scattered Read 發出離散讀,將儲存上連續的資料塊離散的讀入到多個不連續的記憶體位置。 Scattered Read 通常是多塊讀,在 Full Table Scan 或 Fast Full Scan 等訪問方式下使用。
Scattered Read 代表 Full Scan,當執行 Full Scan 讀取資料到 Buffer Cache 時,通常連續的資料在記憶體中的儲存位置並不連續,所以這個等待被命名為 Scattered Read( 離散讀)。每次多
從 V$EVENT_NAME 檢視可以看到,該等待有 3 個引數,分別代表檔案號、 起始資料塊號、 資料塊的數量:
SQL> select * from v$event_name where name='db file scattered read';
EVENT# NAME PARAMETER1 PARAMETER2 PARAMETER3
---------- ---------------------- ---------------------- ------------- ----
206 db file scattered read file# block# blocks
資料檔案號、起始資料塊號加上資料塊的數量, 通過這些資訊可以知道 Oracle Session 正在等待的物件檔案等資訊。 該等待可能和全表掃描( Full Table Scan)或者快速全索引掃描( Index Fast Full Scan) 的連續讀取相關, 根據經驗, 通常大量的 db file scattered read 等待可能意味著應用問題或者索引缺失。
在實際環境的診斷過程中, 可以通過 v$session_wait 檢視發現 Session 的等待,再結合其他檢視找到存在問題的 SQL 等根本原因,從而從根本上解決問題。
當這個等待事件比較顯著時, 使用者也可以結合 v$session_longops 動態效能檢視來進行診斷,該檢視中記錄了長時間(執行時間超過 6 秒的)執行的事務,可能很多是全表掃描操作(不管怎樣,這部分資訊都是值得我們注意的),上一個案例就是通過 v$session_longops 快速發現了問題所在。
從 Oracle 9i 開始, Oracle 新增加了一個檢視 V$SQL_PLAN 用於記錄當前系統 Library Cache 中 SQL 語句的執行計劃, 可以通過這個檢視找到存在問題的 SQL 語句, 以下是在一個
生產系統中查詢得到的結果:
SQL> @getplan
Enter value for waitevent: free buffer waits
old 15: AND b.event = '&waitevent')
new 15: AND b.event = 'free buffer waits')
HASH_VALUE CHILD_NUMBER OPERATION OBJECT COST KBYTES
---------- ------------ ---------------------------------------- -------------------
2838180055 0 INSERT STATEMENT CHOOSE Cost=41733 41733
2838180055 0 TABLE ACCESS FULL I_CM_POWER_TEMP 41733 1356468
進而可以通過 v$sql_text 檢視獲得這個問題 Session 正在執行的 SQL 語句:
SQL> select sid,event from v$session_wait;
SID EVENT
---------- ----------------------------------------------------------------
1 pmon timer
4 rdbms ipc message
7 rdbms ipc message
5 rdbms ipc message
8 rdbms ipc message
21 free buffer waits
49 free buffer waits
2 db file parallel write
3 db file parallel write
6 smon timer
……
16 rows selected.
SQL>@ GetSqlBySid
Enter value for sid: 49
old 5: where b.sid='&sid'
new 5: where b.sid='49'
SQL_TEXT
-----------------------------------------------------------------------
insert into i_cm_power_new(PNAME,YYS,SPHM,SJH,SENTTIME,NOTES,PLACE,RMK)
select PNAME,YYS,SPHM,SJH,SENTTIME,NOTES,PLACE,RMK FROM i_cm_power_temp
通過 V$SQL_PLAN 檢視, 可以獲得大量有用的資訊,比如獲得全表掃描的物件:
SQL> select distinct object_name,object_owner from v$sql_plan p
2 where p.operation='TABLE ACCESS' and p.options='FULL'
3 and object_owner = 'MKT';
OBJECT_NAME OBJECT_OWNER
--------------------------------------------------- -----------------
HD_TEMP MKT
I_CM_BILL MKT
I_CM_IVR_BUTTON MKT
……
TOOLS_HD MKT
TOOLS_HD_NEW MKT
TOOLS_HD_NEW_BAK MKT
TOOLS_IVRBLIST MKT
TOOLS_USER_CANCEL MKT
29 rows selected
或者獲得全索引掃描物件:
SQL> select distinct object_name,object_owner from v$sql_plan p
2 where p.operation='INDEX' and p.options='FULL SCAN' ;
OBJECT_NAME OBJECT_OWNER
------------------------------ -----------------------------------
FK_ITEM_LEVEL_CODE AVATAR
FK_ITEM_SELLCNT_CODE AVATAR
FK_MYZZIM_CRTDATE AVATAR
I_SYSAUTH1 SYS
SYS_C008211 WLLM
進而可以通過 V$SQL_PLAN 和 V$SQLTEXT 聯合,獲得這些查詢的 SQL 語句, 查詢全
表掃描的 SQL 語句可以參考如下語句:
SELECT sql_text FROM v$sqltext t, v$sql_plan p
WHERE t.hash_value = p.hash_value AND p.operation = 'TABLE ACCESS' AND p.options = 'FULL'
ORDER BY p.hash_value, t.piece;
查詢 Fast Full Index 掃描的 SQL 語句可以參考如下語句:
SELECT sql_text FROM v$sqltext t, v$sql_plan p
WHERE t.hash_value = p.hash_value AND p.operation = 'INDEX' AND p.options = 'FULL SCAN'
ORDER BY p.hash_value, t.piece;
這些資訊對於發現數據庫問題,優化資料庫效能具有極強的指導意義。 本例中用到的 SQL
程式碼 getplan.sql 內容如下: :
SET linesize 120
COL operation format a55
COL cost format 99999
COL kbytes format 999999
COL object format a25
SELECT hash_value, child_number, LPAD (' ', 2 * DEPTH) || operation || ' ' || options
|| DECODE (ID, 0, SUBSTR (optimizer, 1, 6) || ' Cost=' || TO_CHAR (COST) ) operation,
object_name OBJECT, COST, ROUND (BYTES / 1024) kbytes
FROM v$sql_plan WHERE hash_value IN (
SELECT a.sql_hash_value FROM v$session a, v$session_wait b
WHERE a.SID = b.SID AND b.event = '&waitevent')
ORDER BY hash_value, child_number, ID;
在 Oracle 10g 中, Oracle 對等待事件進行了分類, db file scattered read 事件被歸入 User I/O
一類:
SQL> select name,PARAMETER1 p1,PARAMETER2 p2,PARAMETER3 p3,
2 WAIT_CLASS_ID,WAIT_CLASS#,WAIT_CLASS
3 from v$event_name where name='db file scattered read';
NAME P1 P2 P3 WAIT_CLASS_ID WAIT_CLASS# WAIT_CLASS
------------------------- -------- -------- -------- ------------- ----------- ----------
db file scattered read file# block# blocks 1740759767 8 User I/O
下面是一條有用的SQL語句,在資料庫層面檢視db file等待事件的I/O是否有問題。
############################ IO 響應時間 ############################
select to_char(b.begin_interval_time,'yyyy-mm-dd:hh24'),a.event_name,a.avg_time
from (
select event_name,snap_id,round(lag_time/lag_count/1000,2) avg_time from (
select event_name,snap_id,total_waits-lag(total_waits,1,total_waits) over(partition by event_name,instance_number order by snap_id) lag_count,
time_waited_micro-lag(time_waited_micro,1,time_waited_micro) over(partition by event_name,instance_number order by snap_id) lag_time
from dba_hist_system_event where event_name in ('db file scattered read') <==========這個地方要檢查db file sequential read 和 db file scattered read
and instance_number=1) where lag_count>0) a,dba_hist_snapshot b
where b.instance_number=1 <=============這個地方要檢查例項1和例項2
and a.snap_id=b.snap_id
order by 2,1;