在上一篇的文章中《第68期 自己手写Oracle AWR 近 3 小时 TOP5 非空闲等待事件采集脚本(一)》我们详细解释了脚本的编写过程。本次主要给大家分享一下使用的案例。
sqlplus / as sysdba 执行,必须开启输出:[oracle@zbyl ~]$ sqlplus / as sysdba SQL*Plus: Release 19.0.0.0.0 - Production on Wed Jul 8 16:27:13 2026 Version 19.22.0.0.0 Copyright (c) 1982, 2023, Oracle. All rights reserved. Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.22.0.0.0 SQL> set lines 400 set pages 1000 set feedback off set serverout on declare vevent varchar2(100); vtime number; vavgtime number; vpctwt number; vwaits number; vwaitclass varchar2(100); vbid number ; veid number ; vdbid number ; vinid number ; startid number; endid number; vstarttime varchar2(200); vendtime varchar2(200); vdbname varchar2(36); v_inst_startup date; begin select instance_number,STARTUP_TIME into vinid ,v_inst_startup from v$instance; select dbid into vdbid from v$database; -- begin select min(snap_id),max(snap_id) into vbid,veid from dba_hist_snapshot where END_INTERVAL_TIME between sysdate - 3/24 and sysdate and END_INTERVAL_TIME > = v_inst_startup and instance_number = vinid and dbid = vdbid; exception when no_data_found then select min(snap_id),max(snap_id) into vbid,veid from dba_hist_snapshot where END_INTERVAL_TIME between sysdate -1 and sysdate -1 - 3/24 and END_INTERVAL_TIME > = v_inst_startup and instance_number = vinid and dbid = vdbid; end; select chr(34)||to_char(a.end_interval_time,'yyyy-mm-dd hh24:mi')||chr(34) into vstarttime from dba_hist_snapshot a where snap_id=vbid and instance_number=vinid; select chr(34)||to_char(a.end_interval_time,'yyyy-mm-dd hh24:mi')||chr(34) into vendtime from dba_hist_snapshot a where snap_id=veid and instance_number=vinid; for c1 in ( SELECT EVENT, WAITS, round(TIME,0) tm, round(DECODE(WAITS, NULL, TO_NUMBER(NULL), 0, TO_NUMBER(NULL), TIME / WAITS * 1000),0) AVGWT, round(PCTWTT,2) PCTWTT, WAIT_CLASS FROM (SELECT EVENT, WAITS, TIME, PCTWTT, WAIT_CLASS FROM (SELECT E.EVENT_NAME EVENT, E.TOTAL_WAITS_FG - NVL(B.TOTAL_WAITS_FG, 0) WAITS, (E.TIME_WAITED_MICRO_FG - NVL(B.TIME_WAITED_MICRO_FG, 0)) / 1000000 TIME, 100 * (E.TIME_WAITED_MICRO_FG - NVL(B.TIME_WAITED_MICRO_FG, 0)) / ((SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL e WHERE e.SNAP_ID = veid AND e.INSTANCE_NUMBER = vinid AND e.STAT_NAME = 'DB time') - (SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL b WHERE b.SNAP_ID = vbid AND b.INSTANCE_NUMBER = vinid AND b.STAT_NAME = 'DB time')) PCTWTT, E.WAIT_CLASS WAIT_CLASS FROM DBA_HIST_SYSTEM_EVENT B, DBA_HIST_SYSTEM_EVENT E WHERE B.SNAP_ID(+) = vbid AND E.SNAP_ID = veid AND B.INSTANCE_NUMBER(+) = vinid AND E.INSTANCE_NUMBER = vinid AND B.EVENT_ID(+) = E.EVENT_ID AND E.TOTAL_WAITS > NVL(B.TOTAL_WAITS, 0) AND E.WAIT_CLASS != 'Idle' UNION ALL SELECT 'CPU time' EVENT, TO_NUMBER(NULL) WAITS, ((SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL e WHERE e.SNAP_ID = veid AND e.INSTANCE_NUMBER = vinid AND e.STAT_NAME = 'DB CPU') - (SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL b WHERE b.SNAP_ID = vbid AND b.INSTANCE_NUMBER = vinid AND b.STAT_NAME = 'DB CPU')) / 1000000 TIME, 100 * ((SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL e WHERE e.SNAP_ID = veid AND e.INSTANCE_NUMBER = vinid AND e.STAT_NAME = 'DB CPU') - (SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL b WHERE b.SNAP_ID = vbid AND b.INSTANCE_NUMBER = vinid AND b.STAT_NAME = 'DB CPU')) / ((SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL e WHERE e.SNAP_ID = veid AND e.INSTANCE_NUMBER = vinid AND e.STAT_NAME = 'DB time') - (SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL b WHERE b.SNAP_ID = vbid AND b.INSTANCE_NUMBER = vinid AND b.STAT_NAME = 'DB time')) PCTWTT, NULL WAIT_CLASS from dual WHERE ((SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL e WHERE e.SNAP_ID = veid AND e.INSTANCE_NUMBER = vinid AND e.STAT_NAME = 'DB CPU') - (SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL b WHERE b.SNAP_ID = vbid AND b.INSTANCE_NUMBER = vinid AND b.STAT_NAME = 'DB CPU')) > 0) ORDER BY TIME DESC, WAITS DESC) WHERE ROWNUM <= 5) loop dbms_output.put_line(vstarttime||','||vendtime||','|| chr(34)||c1.EVENT||chr(34)||','|| chr(34)|| nvl(to_char(c1.WAITS),'---')||chr(34)||','|| chr(34)|| nvl(to_char(c1.Tm),'---')||chr(34)||','|| chr(34)|| nvl(to_char(c1.AVGWT),'---')||chr(34)||','|| chr(34)|| nvl(to_char(c1.PCTWTT),'---')||chr(34)||','|| chr(34)|| nvl(to_char(c1.WAIT_CLASS),'---')||chr(34)); end loop; end; /
-- 粘贴你完整的那段PLSQL脚本/
输入的结果如下: "2026-07-08 09:00","2026-07-08 12:00","CPU time","---",24680,---,72.35,"---" "2026-07-08 09:00","2026-07-08 12:00","db file sequential read",1268450,6210,5,18.12,"User I/O" "2026-07-08 09:00","2026-07-08 12:00","latch: cache buffers chains",365200,2140,6,6.24,"Concurrency" "2026-07-08 09:00","2026-07-08 12:00","db file scattered read",102400,860,8,2.48,"User I/O" "2026-07-08 09:00","2026-07-08 12:00","enq: TX - row lock contention",12560,120,9,0.81,"Application"
字段含义对照:
快照开始时间,快照结束时间,等待事件名,总等待次数,总等待秒,单次平均等待ms,占DBTime百分比,等待分类
"2026-07-08 09:00","2026-07-08 12:00","CPU time","---",24680,---,72.35,"---"
现象解读
gather_plan_statistics 看执行计划,补联合索引;"2026-07-08 09:00","2026-07-08 12:00","db file sequential read",1268450,6210,5,18.12,"User I/O"
"2026-07-08 09:00","2026-07-08 12:00","latch: cache buffers chains",365200,2140,6,6.24,"Concurrency"
"2026-07-08 09:00","2026-07-08 12:00","enq: TX - row lock contention",12560,120,9,0.81,"Application"
"2026-07-08 09:00","2026-07-08 12:00","db file scattered read",102400,860,8,2.48,"User I/O"
解读
sysdate-3/24(09~12 点)查不到快照,触发
no_data_found异常。脚本自动切换窗口:
sysdate-1-3/24 ~ sysdate-1,读取昨天同时段快照输出性能数据,不会直接报错中断巡检。输出时间会变成:"2026-07-07 09:00","2026-07-07 12:00","CPU time","---",22150,---,68.11,"---"
#!/bin/bashlog=/tmp/awr_wait_top5.log sqlplus -S / as sysdba >> $log <<EOF set lines 400 set pages 1000 set feedback off set serverout on declare vevent varchar2(100); vtime number; vavgtime number; vpctwt number; vwaits number; vwaitclass varchar2(100); vbid number ; veid number ; vdbid number ; vinid number ; startid number; endid number; vstarttime varchar2(200); vendtime varchar2(200); vdbname varchar2(36); v_inst_startup date; begin select instance_number,STARTUP_TIME into vinid ,v_inst_startup from v$instance; select dbid into vdbid from v$database; -- begin select min(snap_id),max(snap_id) into vbid,veid from dba_hist_snapshot where END_INTERVAL_TIME between sysdate - 3/24 and sysdate and END_INTERVAL_TIME > = v_inst_startup and instance_number = vinid and dbid = vdbid; exception when no_data_found then select min(snap_id),max(snap_id) into vbid,veid from dba_hist_snapshot where END_INTERVAL_TIME between sysdate -1 and sysdate -1 - 3/24 and END_INTERVAL_TIME > = v_inst_startup and instance_number = vinid and dbid = vdbid; end; select chr(34)||to_char(a.end_interval_time,'yyyy-mm-dd hh24:mi')||chr(34) into vstarttime from dba_hist_snapshot a where snap_id=vbid and instance_number=vinid; select chr(34)||to_char(a.end_interval_time,'yyyy-mm-dd hh24:mi')||chr(34) into vendtime from dba_hist_snapshot a where snap_id=veid and instance_number=vinid; for c1 in ( SELECT EVENT, WAITS, round(TIME,0) tm, round(DECODE(WAITS, NULL, TO_NUMBER(NULL), 0, TO_NUMBER(NULL), TIME / WAITS * 1000),0) AVGWT, round(PCTWTT,2) PCTWTT, WAIT_CLASS FROM (SELECT EVENT, WAITS, TIME, PCTWTT, WAIT_CLASS FROM (SELECT E.EVENT_NAME EVENT, E.TOTAL_WAITS_FG - NVL(B.TOTAL_WAITS_FG, 0) WAITS, (E.TIME_WAITED_MICRO_FG - NVL(B.TIME_WAITED_MICRO_FG, 0)) / 1000000 TIME, 100 * (E.TIME_WAITED_MICRO_FG - NVL(B.TIME_WAITED_MICRO_FG, 0)) / ((SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL e WHERE e.SNAP_ID = veid AND e.INSTANCE_NUMBER = vinid AND e.STAT_NAME = 'DB time') - (SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL b WHERE b.SNAP_ID = vbid AND b.INSTANCE_NUMBER = vinid AND b.STAT_NAME = 'DB time')) PCTWTT, E.WAIT_CLASS WAIT_CLASS FROM DBA_HIST_SYSTEM_EVENT B, DBA_HIST_SYSTEM_EVENT E WHERE B.SNAP_ID(+) = vbid AND E.SNAP_ID = veid AND B.INSTANCE_NUMBER(+) = vinid AND E.INSTANCE_NUMBER = vinid AND B.EVENT_ID(+) = E.EVENT_ID AND E.TOTAL_WAITS > NVL(B.TOTAL_WAITS, 0) AND E.WAIT_CLASS != 'Idle' UNION ALL SELECT 'CPU time' EVENT, TO_NUMBER(NULL) WAITS, ((SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL e WHERE e.SNAP_ID = veid AND e.INSTANCE_NUMBER = vinid AND e.STAT_NAME = 'DB CPU') - (SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL b WHERE b.SNAP_ID = vbid AND b.INSTANCE_NUMBER = vinid AND b.STAT_NAME = 'DB CPU')) / 1000000 TIME, 100 * ((SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL e WHERE e.SNAP_ID = veid AND e.INSTANCE_NUMBER = vinid AND e.STAT_NAME = 'DB CPU') - (SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL b WHERE b.SNAP_ID = vbid AND b.INSTANCE_NUMBER = vinid AND b.STAT_NAME = 'DB CPU')) / ((SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL e WHERE e.SNAP_ID = veid AND e.INSTANCE_NUMBER = vinid AND e.STAT_NAME = 'DB time') - (SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL b WHERE b.SNAP_ID = vbid AND b.INSTANCE_NUMBER = vinid AND b.STAT_NAME = 'DB time')) PCTWTT, NULL WAIT_CLASS from dual WHERE ((SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL e WHERE e.SNAP_ID = veid AND e.INSTANCE_NUMBER = vinid AND e.STAT_NAME = 'DB CPU') - (SELECT sum(value) FROM DBA_HIST_SYS_TIME_MODEL b WHERE b.SNAP_ID = vbid AND b.INSTANCE_NUMBER = vinid AND b.STAT_NAME = 'DB CPU')) > 0) ORDER BY TIME DESC, WAITS DESC) WHERE ROWNUM <= 5) loop dbms_output.put_line(vstarttime||','||vendtime||','|| chr(34)||c1.EVENT||chr(34)||','|| chr(34)|| nvl(to_char(c1.WAITS),'---')||chr(34)||','|| chr(34)|| nvl(to_char(c1.Tm),'---')||chr(34)||','|| chr(34)|| nvl(to_char(c1.AVGWT),'---')||chr(34)||','|| chr(34)|| nvl(to_char(c1.PCTWTT),'---')||chr(34)||','|| chr(34)|| nvl(to_char(c1.WAIT_CLASS),'---')||chr(34)); end loop; end; / EOF# 日志发送到监控平台/导出excel分析cat $log
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/12798004/viewspace-3175467/ ,如需转载,请注明出处,否则将追究法律责任。