通常情况下,用户提交一条SQL语句,总会存在这样或那样的等待事件。也就是说由于所需资源被占用导致进程不得不处于等待状态。Oracle为我们提供了获取这些等待事件的可用视图。根据这些视图可以得知哪些事件导致该SQL语句效率低下而采取相应的修改或调整。本文基于Oracle 10g描述了如何通过视图v$session_wait,v$session_event,以及v$system_event去获取等待事件的相关信息。
1、等待事件相关参数
timed_statistics
指定了在搜集数据库统计信息时,与时间相关的统计信息是否会被收集。该参数影响等待事件中时间相关的值,且受制于statistics_level。
statistics_level
指定了收集数据库以及操作系统统计信息的级别。
该参数值的范围STATISTICS_LEVEL = { ALL | TYPICAL | BASIC },可修改级别ALTER SESSION, ALTER SYSTEM
缺省情况下为TYPICAL
2、等待事件的相关视图
可以从dict数据库字典中获得当前数据库的与等待事件相关的视图,如使用如下SQL来获得:
SELECT *
FROM dict
WHERE table_name LIKE '%V$EVENT%' OR table_name LIKE '%V$%WAIT%';
几个重要的等待事件视图
下面这三个视图提供了不同粒度级的等待事件统计和计时信息。
v$SESSION_WAIT(最低粒度的等待事件)
v$SESSION_EVENT(该视图提供上一视图等待事件的汇总)
v$SYSTEM_EVENT(该视图提供自实例启动以来所有等待事件的汇总)
几个视图的粒度关系
V$SESSION_WAIT ⊂ v$SESSION_EVENT ⊂ v$SYSTEM_EVENT
下面将逐一描述这些视图
3、视图v$event_name
该视图列出了当前Oracle版本中所有等待事件的描述信息。如等待事件的ID,名字,参数,类别等等
SELECT COUNT (*) FROM v$event_name;
SELECT wait_class, COUNT (*)
FROM v$event_name
GROUP BY wait_class
ORDER BY 2;
4、视图v$session_wait
该视图显示的基于会话级的等待信息,为每个会话当前正在等待的事件或资源提供详细信息。
也就是说在视图v$session_wait中,每一个连接到的实例的session都对应一行活动的或不活动的信息。
视图的p1,p2,p3标识了对应的session正在等待的具体资源,p1text,p2text,p3text则是对p1,p2,p3的文字描述。
从Oracle 10g R1启,该视图的所有信息可以直接从v$session获得。
1)、state字段有四种含义﹕
a、Waiting:当前SESSION正等待这个事件。SECONDS_IN_WAIT表示已经等待的时间。
b、Waited unknown time:参数timed_statistics值为false时,无法确定等待时间。
c、Wait short time:表示发生了等待,且低于1厘秒,此情形下wait_time列显示为-1。
d、Waited known time:如果session等待然后得到了所需资源,那么将从waiting进入本状态,并且时间发送给wait_time列
2)、wait_time值也有四种含义:
a、值>0:最后一次等待时间(单位:厘秒),当前未在等待状态。
b、值=0:session正在等待当前的事件。
c、值=-1:最后一次等待时间小于1个统计单位,当前未在等待状态。
d、值=-2:时间统计状态未置为可用,当前未在等待状态。
3)、wait_time和seconds_in_wait字段值与state相关:
a、如果state值为Waiting,则wait_time值无效。seconds_in_wait值为实际的等待时间(单位:秒)。
b、如果state值为Wait unknow time或者Wait short time,那么wait_time值和Seconds_in_wait值都无效。
c、如果state值为Waiting known time,则wait_time值就是实际等待时间(单位:秒),seconds_in_wait值无效。
4)、指定session当前的等待事件
SELECT *
FROM v$session_wait
WHERE sid = &input_sid;
5、视图v$session_event
该视图记录了每个session的每一个等待事件的总等待时间,已等待时间以及最大等待时间。
也就是说该视图是对每个session自启动以来所经历的所有等待的汇总。
v$session_event视图的SID列提供了基于sid来获得等待事件信息。
该视图相当于v$system_event的一个子集,两者都提供基于等待时间的统计信息
其差异是v$session_event提供的是会话级的统计信息,v$system_event提供的是实例级别统计信息
SQL> desc v$session_event;
Name Type Nullable Default Comments
----------------- ------------ -------- ------- --------
SID NUMBER Y
EVENT VARCHAR2(64) Y 事件名称
TOTAL_WAITS NUMBER Y 当前事件总等待次数
TOTAL_TIMEOUTS NUMBER Y 自会话初次等待之后未能成功获得所请求资源的次数
TIME_WAITED NUMBER Y 等待该事件所耗用的总时间(百分之一秒)
AVERAGE_WAIT NUMBER Y 平均等待时间(重要参考列,百分之一秒)
MAX_WAIT NUMBER Y 最大等待时间(百分之一秒)
TIME_WAITED_MICRO NUMBER Y
EVENT_ID NUMBER Y
WAIT_CLASS_ID NUMBER Y
WAIT_CLASS# NUMBER Y
WAIT_CLASS VARCHAR2(64) Y
6、视图v$system_event
显示自实例启动后所有Oracle会话遇到的所有等待时间的总和,包括等待的总次数,总超时,是所有会话的在所有等待事件上的汇总。
SQL> desc v$system_event;
Name Type Nullable Default Comments
----------------- ------------ -------- ------- --------
EVENT VARCHAR2(64) Y
TOTAL_WAITS NUMBER Y
TOTAL_TIMEOUTS NUMBER Y
TIME_WAITED NUMBER Y
AVERAGE_WAIT NUMBER Y
TIME_WAITED_MICRO NUMBER Y
EVENT_ID NUMBER Y
WAIT_CLASS_ID NUMBER Y
WAIT_CLASS# NUMBER Y
WAIT_CLASS VARCHAR2(64) Y
7、演示等待事件
-->查看当前数据库的总session数 goex_admin@SYBO2SZ> select count(*) from v$session; COUNT(*) ---------- 20 --查看数据库当前的总等待事件数 --下面的查询结果与session数的值相等,也即是一个session对应一个空闲或非空闲等待事件 goex_admin@SYBO2SZ> select count(*) from v$session_wait; COUNT(*) ---------- 20 --开一个session 1 来update emp --session 1 scott@SYBO2SZ> update emp set sal=sal+100 where deptno=20; 5 rows updated. --开启另外一个session 2来尝试delete emp上的一些记录 Author: Robinson --session 2此时处于阻塞状态 Blog : http://blog.csdn.net/robinson_0612 scott@SYBO2SZ> delete from emp where deptno=20; --可以看到当前数据库sid为1067上存在一个enq等待事件(1067为session 2的SID) goex_admin@SYBO2SZ> select sid,event,wait_class,wait_time,seconds_in_wait,state from v$session_wait where sid=1067; SID EVENT WAIT_CLASS WAIT_TIME SECONDS_IN_WAIT STATE ------ ----------------------------------- ------------------ ---------- --------------- ------------------- 1067 enq: TX - row lock contention Application 0 960 WAITING --在sid为1067的session中,当TX锁等待获得资源后,再次查询该session,此时已经变成了空闲等待。 goex_admin@SYBO2SZ> select sid,event,wait_class,wait_time,seconds_in_wait,state from v$session_wait where sid=1067; SID EVENT WAIT_CLASS WAIT_TIME SECONDS_IN_WAIT STATE ------ ----------------------------------- ------------------ ---------- --------------- ------------------- 1067 SQL*Net message from client Idle 0 10 WAITING --下面的脚本查询的是基于v$session_event的等待事件 goex_admin@SYBO2SZ> @wait_event_by_sid Enter value for sid: 1067 Enter value for sid: 1067 EVENT TIME_SPENT ----------------------------------- ---------- enq: TX - row lock contention 95489 -->总等待时间为95489,单位为百分之一秒,比seconds_in_wait更精确 CPU used when call started 4 --下面查询基于实例级别的等待事件 --当输入enq,则所有enq相关的等待记录会列出 goex_admin@SYBO2SZ> @wait_event_inst_lvl Enter value for input_event_name: enq Enter value for input_event_name: enq WAIT_CLASS EVENT TOTAL_WAITS TOTAL_TIMEOUTS TIME_WAITED AVERAGE_WAIT STARTUP_TIME -------------------- ------------------------------ ------------ -------------- ----------- ------------- ----------------- Application enq: RO - fast object reuse 99 1 393 4 20130410 20:22:43 Application enq: TX - row lock contention 382 379 111,476 292 20130410 20:22:43 Concurrency enq: TX - index contention 3 0 28 9 20130410 20:22:43 Configuration enq: HW - contention 27 1 592 22 20130410 20:22:43 Other latch: enqueue hash chains 5 0 6 1 20130410 20:22:43 Other enq: FB - contention 1 0 10 10 20130410 20:22:43 Other enq: TX - contention 4 0 158 39 20130410 20:22:43 Other enq: CF - contention 6 5 1,556 259 20130410 20:22:43 8 rows selected. --当输入ALL时,该实例的所有等待事件被列出 goex_admin@SYBO2SZ> @wait_event_inst_lvl Enter value for input_event_name: ALL Enter value for input_event_name: ALL WAIT_CLASS EVENT TOTAL_WAITS TOTAL_TIMEOUTS TIME_WAITED AVERAGE_WAIT STARTUP_TIME -------------------- ------------------------------ ------------ -------------- ----------- ------------- ----------------- Application SQL*Net break/reset to client 99 0 1 0 20130410 20:22:43 Application enq: RO - fast object reuse 99 1 393 4 20130410 20:22:43 Application enq: TX - row lock contention 382 379 111,476 292 20130410 20:22:43 Commit log file sync 33,165 3,788 798,189 24 20130410 20:22:43 Concurrency latch: library cache pin 5 0 0 0 20130410 20:22:43 Concurrency latch: library cache lock 5 0 15 3 20130410 20:22:43 Concurrency enq: TX - index contention 3 0 28 9 20130410 20:22:43 Concurrency cursor: mutex S 6,737 0 29 0 20130410 20:22:43 goex_admin@SYBO2SZ> @wait_event_inst_lvl Enter value for input_event_name: ALL Enter value for input_event_name: ALL WAIT_CLASS EVENT TOTAL_WAITS TOTAL_TIMEOUTS TIME_WAITED AVERAGE_WAIT STARTUP_TIME -------------------- ------------------------------ ------------ -------------- ----------- ------------- ----------------- Application SQL*Net break/reset to client 99 0 1 0 20130410 20:22:43 Application enq: RO - fast object reuse 99 1 393 4 20130410 20:22:43 Application enq: TX - row lock contention 382 379 111,476 292 20130410 20:22:43 Commit log file sync 33,165 3,788 798,189 24 20130410 20:22:43 ...................... Concurrency latch: library cache pin 5 0 0 0 20130410 20:22:43 Concurrency latch: library cache lock 5 0 15 3 20130410 20:22:43 Concurrency enq: TX - index contention 3 0 28 9 20130410 20:22:43 Concurrency cursor: mutex S 6,737 0 29 0 20130410 20:22:43
8、演示中使用到的脚本
a、wait_event_by_sid.sql robin@SZDB:~/dba_scripts/custom/sql> more wait_event_by_sid.sql SELECT event, time_waited AS time_spent FROM v$session_event WHERE sid = &sid AND wait_class<>'Idle' AND event NOT IN ('Null event', 'client message', 'KXFX: Execution Message Dequeue - Slave', 'PX Deq: Execution Msg', 'KXFQ: kxfqdeq - normal deqeue', 'PX Deq: Table Q Normal', 'Wait for credit - send blocked', 'PX Deq Credit: send blkd', 'Wait for credit - need buffer to send', 'PX Deq Credit: need buffer', 'Wait for credit - free buffer', 'PX Deq Credit: free buffer', 'parallel query dequeue wait', 'PX Deque wait', 'Parallel Query Idle Wait - Slaves', 'PX Idle Wait', 'slave wait', 'dispatcher timer', 'virtual circuit status', 'pipe get', 'rdbms ipc message', 'rdbms ipc reply', 'pmon timer', 'smon timer', 'PL/SQL lock timer', 'SQL*Net message from client', 'SQL*Net message to client', 'SQL*Net break/reset to client', 'SQL*Net more data to client', 'rdbms ipc message', 'WMON goes to sleep') UNION ALL SELECT b.name, a.VALUE FROM v$sesstat a, v$statname b WHERE a.statistic# = b.statistic# AND b.name = 'CPU used when call started' AND a.sid = &sid; b、wait_event_inst_lvl.sql robin@SZDB:~/dba_scripts/custom/sql> more wait_event_inst_lvl.sql SET LINES 160 SET NUMWIDTH 18 COL class FOR a15 COL event FOR a30 COL total_waits FOR 999,999,999 COL total_timeouts FOR 999,999,999 COL time_waited FOR 999,999,999,999 COL average_wait FOR 999,999,999,999 COL event FORMAT a30 WRAP COL wait_class FORMAT a20 SELECT b.wait_class, a.event, total_waits, total_timeouts, time_waited, average_wait, c.startup_time FROM v$system_event a, v$event_name b, v$instance c WHERE a.event = b.name AND UPPER (a.event) LIKE DECODE (UPPER ('&input_event_name'), 'ALL', UPPER (a.event), UPPER ('%&input_event_name%')) AND b.wait_class<>'Idle' AND a.event NOT IN ('Null event', 'client message', 'KXFX: Execution Message Dequeue - Slave', 'PX Deq: Execution Msg', 'KXFQ: kxfqdeq - normal deqeue', 'PX Deq: Table Q Normal', 'Wait for credit - send blocked', 'PX Deq Credit: send blkd', 'Wait for credit - need buffer to send', 'PX Deq Credit: need buffer', 'Wait for credit - free buffer', 'PX Deq Credit: free buffer', 'parallel query dequeue wait', 'PX Deque wait', 'Parallel Query Idle Wait - Slaves', 'PX Idle Wait', 'slave wait', 'dispatcher timer', 'virtual circuit status', 'pipe get', 'rdbms ipc message', 'rdbms ipc reply', 'pmon timer', 'smon timer', 'PL/SQL lock timer', 'SQL*Net message from client', 'SQL*Net message to client', 'SQL*Net break/reset to client', 'SQL*Net more data to client', 'rdbms ipc message', 'WMON goes to sleep') ORDER BY b.wait_class, a.time_waited;
9、小结
a、参数timed_statistics与statistics_level影响等待事件时间片的收集
b、v$event_name数据库字典(此处不是动态视图)提供了所有等待事件相关的名称,类别,ID等
c、v$session_wait为当前实例的session提供当前正在等待的事件或资源(单一事件,一个session对应一条记录)
d、v$session_event提供了每个session的每一个等待事件的总等待时间,已等待时间以及最大等待时间
e、v$system_event提供的是自实例启动以来所有等待时间的总和,包括等待的总次数,总超时,是所有会话的在所有等待事件上的汇总。
f、如果用户说某个session响应比较慢,排除Cpu过度繁忙之外,一定是该session 处于某个等待事件而导致session变慢。
g、根据上述描述的相关视图,可以快速定位指定session变慢的真正原因。
更多参考
PL/SQL --> 游标
PL/SQL --> 隐式游标(SQL%FOUND)
批量SQL之 FORALL 语句
批量SQL之 BULK COLLECT 子句
PL/SQL 集合的初始化与赋值
PL/SQL 联合数组与嵌套表
PL/SQL 变长数组
PL/SQL --> PL/SQL记录
SQL tuning 步骤
高效SQL语句必杀技
父游标、子游标及共享游标
绑定变量及其优缺点
dbms_xplan之display_cursor函数的使用
dbms_xplan之display函数的使用
执行计划中各字段各模块描述
使用 EXPLAIN PLAN 获取SQL语句执行计划
Oracle ROWID
NULL 值与索引(一)
NULL 值与索引(二)
启用 AUTOTRACE 功能
函数使得索引列失效
Oracle 绑定变量窥探
Oracle 自适应共享游标
Oracle 表空间与数据文件
Oracle 密码文件
Oracle 参数文件
Oracle 联机重做日志文件(ONLINE LOG FILE)
Oracle 控制文件(CONTROLFILE)
Oracle 归档日志
Oracle 回滚(ROLLBACK)和撤销(UNDO)
Oracle 数据库实例启动关闭过程
Oracle 10g SGA 的自动化管理
Oracle 实例和Oracle数据库(Oracle体系结构)