V$session 檢視的小運用

pingley發表於2012-04-23
V$session 檢視的小運用
我對這個檢視沒什麼好感,因為這個檢視又長又臭,對oracle真是愛並痛恨著。
一、kill session 這個是有些危險的操作如果不小心kill 掉了後臺程式那就只能哭了,很可能導致資料庫的崩潰或者執行時出現故障。為了確保你所kill 的那個session 確實是你所要kill 掉的。應該透過 V$session 檢視來獲得足夠的資訊。
SQL> select sid,serial#,username,type,program
  2  from V$session
  3  where type != 'BACKGROUND';
       SID    SERIAL# USERNAME   TYPE       PROGRAM
---------- ---------- ---------- ---------- -------------------------
         1          5 SYS        USER       sqlplus@zeng (TNS V1-V3)
        36         10 HR         USER       sqlplus@zeng (TNS V1-V3)
我透過使用上面的查詢就足夠讓我確定我要kill 掉的會話了。在kill 掉sid = 36 的會話之前我在這個會話中執行如下的update 語句。
SQL> select salary from employees where employee_id = 100;
    SALARY
----------
     24000
SQL> update employees
  2  set salary = salary + 100
  3  where employee_id = 100;
1 row updated.
下面把sid = 36,serial# = 10 的會話kill 掉。接著馬上查詢V$session 檢視。
SQL> alter system kill session '36,10';
System altered.
SQL> select sid,serial#,username,type,status,program
  2  from V$session
  3  where type != 'BACKGROUND';
       SID    SERIAL# USERNAME   TYPE       STATUS   PROGRAM
---------- ---------- ---------- ---------- -------- -------------------------
         1          5 SYS        USER       ACTIVE   sqlplus@zeng (TNS V1-V3)
        36         10 HR         USER       KILLED   sqlplus@zeng (TNS V1-V3)
實際上當發出Kill 命令的時候並不是馬上的kill 掉某個 session ,而是要等會話中的操作的完成(等待資料庫的響應或者事務的回滾)由會話“自殺”。所以發出kill 命令會馬上把指定的那個sesion 標記成 killed 但是session 不一定馬上就會被kill 掉。再來看看hr 那個會話,在其中隨便的執行一條SQL 命令,會報如下的錯誤。雖然session 已經被
kill 掉了,但是要是保持著一個會話的“尊嚴”,並不退出sqlplus 。把hr 再次連入資料庫,執行下面的查詢,我們可以知道被kill 掉的會話中沒有提交的事務,oracle 自動的把他回滾了。
SQL> select count(*) from employees;
select count(*) from employees
*
ERROR at line 1:
ORA-00028: your session has been killed
SQL> conn hr/hr
Connected.
SQL> select salary from employees where employee_id = 100;
    SALARY
----------
     24000
二、會話阻塞的查詢。
現在來確定下資料庫中使用者會話的狀態。把sid = 36 的這個hr 的會話標記為session 1.
SQL> select sid,serial#,username,type,program
  2  from V$session
  3  where type != 'BACKGROUND';
       SID    SERIAL# USERNAME   TYPE       PROGRAM
---------- ---------- ---------- ---------- -------------------------
         1          5 SYS        USER       sqlplus@zeng (TNS V1-V3)
        36         14 HR         USER       sqlplus@zeng (TNS V1-V3)
在新增一個hr 使用者的會話。把sid = 32 的這個hr 的會話標記為session 2.
SQL> select sid,serial#,username,type,program
  2  from V$session
  3  where type != 'BACKGROUND';
       SID    SERIAL# USERNAME   TYPE       PROGRAM
---------- ---------- ---------- ---------- -------------------------
         1          5 SYS        USER       sqlplus@zeng (TNS V1-V3)
        32         23 HR         USER       sqlplus@zeng (TNS V1-V3)
        36         14 HR         USER       sqlplus@zeng (TNS V1-V3)
在session 1 中執行如下的update 語句。
SQL> update employees
  2  set salary = salary + 100
  3  where employee_id = 100;
1 row updated.
在session 2 中執行同樣的update 語句。現在來確定這個兩個會話的相關資訊。
SQL> set linesize 200
SQL> select sid,serial#,username,type,
  2  blocking_session_status,blocking_session,blocking_instance
  3  from V$session 
  4  where sid in (32,36);
       SID    SERIAL# USERNAME   TYPE       BLOCKING_SE BLOCKING_SESSION BLOCKING_INSTANCE
---------- ---------- ---------- ---------- ----------- ---------------- -----------------
        32         23 HR         USER       VALID                     36                 1
        36         14 HR         USER       NO HOLDER
我們可以知道session 1 也就是sid = 36 的會話把session 也就是sid = 32 的會話阻塞了。更加本質的原因是鎖的問題。
SQL> select sid,type,lmode,request,block
  2  from V$lock
  3  where sid in (32,36);
       SID TY      LMODE    REQUEST      BLOCK
---------- -- ---------- ---------- ----------
        36 AE          4          0          0
        32 AE          4          0          0
        32 TX          0          6          0
        32 TM          3          0          0
        36 TM          3          0          0
        36 TX          6          0          1
6 rows selected.
我們從查詢可以知道sid = 32 的會話請求一個 lmode 為 6 的鎖,但是該鎖已經被sid = 36 的會話持有了。所以 sid = 32 的會話被阻塞了。如果想知道會話究竟是因為執行了什麼語句而阻塞的可以透過下面的查詢獲知。
SQL> select sql_text from V$sqltext t1
  2  where t1.hash_value = ( select sql_hash_value
  3                                          from V$session t2
  4                                          where t2.sid = 32);
SQL_TEXT
----------------------------------------------------------------
update employees set salary = salary + 100 where employee_id = 100

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26110315/viewspace-722009/,如需轉載,請註明出處,否則將追究法律責任。

相關文章