v$session - 你看到的event真的是session当前的等待事件么?

来源:这里教程网 时间:2026-03-03 13:49:09 作者:

转自oracle官方博客 https://blogs.oracle.com/database4cn/vsession-%e4%bd%a0%e7%9c%8b%e5%88%b0%e7%9a%84event%e7%9c%9f%e7%9a%84%e6%98%afsession%e5%bd%93%e5%89%8d%e7%9a%84%e7%ad%89%e5%be%85%e4%ba%8b%e4%bb%b6%e4%b9%88-v2 当数据库出现性能问题的时候,几乎所有的DBA都会通过v$session来查询数据库的等待。但是用于查询session等待的SQL是正确的么? 看到的event可能并不是session当前的等待,下面举例来说明: 如下的一段简单的PL/SQL Block代码是一个死循环,很显然,它会持续的ON CPU begin   while true loop     null;   end loop; end; / 下面我们用以上代码做一个测试。 --开启一个sqlplus,先确定当前sesison的sid和spid select s.sid,s.serial#,p.spid from v$session s, v$process p, (select * from v$mystat where rownum=1) ms where s.paddr=p.addr and s.sid=ms.sid;        SID    SERIAL# SPID ---------- ---------- ------------------------        283    55044 30176 --然后在这个sqlplus中执行以上PL/SQL代码: begin   while true loop     null;   end loop; end; / --再开启一个新的session,观察以上session 283的等待: set line 200 pages 1000 col username for a5 col event for a30 select sid,serial#,status,sql_id,event,seq# from v$session where sid=283;        SID    SERIAL# STATUS   SQL_ID         EVENT                  SEQ# ---------- ---------- -------- ------------- ------------------------------ ----------        283    55044 ACTIVE   1dn7nmztb2jaz SQL*Net message from client       247 --验证一下sql文本 col sql_text for a60 select sql_id,sql_text from v$sql where sql_id='1dn7nmztb2jaz'; SQL_ID          SQL_TEXT ------------- ------------------------------------------------------------ 1dn7nmztb2jaz begin   while true loop      null;   end loop; end; 会发现以上这个session竟然会在 "等待" SQL*Net message from client,并且status为ACTIVE 大家都知道SQL*Net message from client是一个空闲等待,代表server process正在等待client发出下一个sql指令。 接下来观察以上以上进程的CPU消耗情况,会发现它在持续的ON CPU # top -p 30176   PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                             30176 oracle    20   0 1470m  89m  80m R 47.0  1.1   2:38.91 oracle_30176_or 它几乎消耗了一半的CPU(本测试机为两个CPU),这符合代码的特点。 那么问题来了,这个如此烧CPU的死循环session怎么会是处于空闲等待?答案是我们忽略了v$session.state这个非常重要的列。 一个session的状态要么是在等待,要么是在ON CPU,v$session.state这个列可以判断这个状态。 有且只有v$session.state='WAITING'的时候,才代表这个session当前正在等待这个event,否则代表这个session在ON CPU 并且观察到的event只是进程在ON CPU之前的最后一个等待。 接下来我们将以上用于查询session等待的SQL改一下,添加上v$session.state这个列: col state fro a15 select sid,serial#,status,state,sql_id,event,seq# from v$session where sid=283;        SID    SERIAL# STATUS   STATE           SQL_ID     EVENT                      SEQ# ---------- ---------- -------- ------------------- ------------- ------------------------------ ----------        283    55044 ACTIVE   WAITED KNOWN TIME   1dn7nmztb2jaz SQL*Net message from client           247 可见STATE的值为"WAITED KNOWN TIME",不是"WAITING",这表明这个session当前在ON CPU "SQL*Net message from client"只是这个session在ON CPU之前的最后一个等待 因此当您查询v$session观察session的等待事件的时候一定不要忘了v$session.state这个关键列

相关推荐