ITPub博客

首页 > 数据库 > Oracle > v$session - 你看到的event真的是session当前的等待事件么?

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

Oracle 作者:巡完南山巡南山 时间:2019-06-06 17:11:07 0 删除 编辑

转自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这个关键列


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26964624/viewspace-2646997/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2016-04-11

  • 博文量
    39
  • 访问量
    26504