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

巡完南山巡南山發表於2019-06-06

轉自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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章