Kill會話過程分析(二)

realkid4發表於2011-01-17

本文為筆者“Kill會話過程分析”(http://space.itpub.net/17203031/viewspace-683786 )的續篇。做一些更深入的分析。

 

 

我們知道,當需要強制斷開一個會話的時候,可以透過SQL命令alter system kill session ‘sid, serial#’;強制的將會話斷開。其中,SID為會話的編號,Serial為會話的系列號。這兩個值是唯一標誌Oracle一個會話。而會話的相關資訊,可以透過查詢v$session檢視來獲取到。

 

 

根據前文我們的分析,認為alter system kill session命令是存在一些不足的。

 

首先,kill session命令是在會話層面的強制斷開。本質上相當於進行了一個標誌,切斷了Server Process與會話之間的對映關係。會話所佔有的資源是不會直接被回收;

 

其次,kill session命令在一些特殊場合,應對效果不佳。比如在Oracle Job裡面執行的時候,是不能定位到相應的會話物件的。

 

最後,一些緊急的時候,kill session還存在一些適應性較差的情況。比如當前根本無法登陸SQL命令視窗;

 

 

那麼,比kill session更有效直接的做法是什麼呢?針對Server Processkill操作,也就是OS作業系統級別的kill。當我們不能夠使用alter system kill session或者使用其無效的時候,可以考慮使用這種方法。

 

首先,我們研究一些Linux環境。選擇是專用連線模式。

 

在沒有連線的時候,我們檢視連線情況。

 

[oracle@oracle11g ~]$ ps -ef | grep wilson | grep -v grep

oracle    5583     1  0 02:52 ?        00:00:00 ora_pmon_wilson

oracle    5585     1  0 02:52 ?        00:00:00 ora_vktm_wilson

……(篇幅原因,有省略部分)

oracle    5672     1  0 02:52 ?        00:00:00 ora_q001_wilson

oracle    5700     1  0 02:57 ?        00:00:00 ora_smco_wilson

oracle    5702     1  0 02:57 ?        00:00:00 ora_w000_wilson

 

 

在沒有連線的時候,程式列表中只能看到例項多個background process的執行情況。此時,我們連入一個客戶端。檢視程式情況:(為省略篇幅,設定篩選條件)

 

 

[oracle@oracle11g ~]$ ps -ef | grep LOCAL | grep -v grep;

oracle    5777     1  1 03:09 ?        00:00:00 oraclewilson (LOCAL=NO)

[oracle@oracle11g ~]$

 

 

連入了一個客戶端,在專用模式下有一個Server Process與之關聯。這裡對各列含義略作說明。

 

第一列表示執行使用者Owner,第二列是PID,表示程式的系統唯一編號。第三列表示該程式的父程式PPID編號,就是該程式是由哪個程式啟動的。之後有兩個時間值,分別為程式啟動到現在時間與佔用CPU時間。最後一列一般為啟動命令列。

 

其中,我們比較關注的就是PIDPID唯一的標識,如果強制終止這個程式,我們就可以強制的結束會話(皮之不存,毛將焉附)。同時,在OS層面的強制終止,程式會話對應的資源可以直接回收。

 

Unix/Linux平臺下,可以使用kill -9 PID,實現刪除。

 

[oracle@oracle11g ~]$ kill -9 5777 //終止

[oracle@oracle11g ~]$ ps -ef | grep LOCAL | grep -v grep; //確認

[oracle@oracle11g ~]$

 

 

使用後,作業系統程式樹上的Server Process被清除。此時,連線的客戶端如果發起請求。

 

//之前建立的連線

SQL> conn scott/tiger@wilson

已連線。

 

//kill之後,嘗試連線

SQL> select count(*) from emp;

select count(*) from emp

                       *

1 行出現錯誤:

ORA-03113: 通訊通道的檔案結束 //報錯!

 

 

 

使用kill -9命令,還可以對background process程式進行管理,對一些問題程式進行殺死重建,也是我們經常使用的手段。

 

結論:在Linux平臺上,當需要在作業系統級別進行kill的時候,可以使用kill -9命令。

 

接下來,我們在Windows平臺上,就有一些問題了。由於體系結構的不同,OracleWindows下實現的例項結構,並不是多程式架構方式,而採用的是多執行緒模式。Unix/Linux下的background processServer Process,成為了一個ORACLE.exe程式裡的執行緒。那麼,這種情況下,我們如何處理?

 

為了應對這種情況,Oracle提供了一個為orakill.exe的命令。這個命令本質上和alter system kill session的功能相同,但是不需要登入連線資料庫。只需要輸入執行緒編號和SID就可以。

 

這樣,問題轉化為我們如果獲取到一個執行緒的執行緒編號。在Windows平臺上,有很多檢視執行緒的工具。如Qslice.exeQuickSlice.exe以及Pstat

 

語法:orakill

其中,sidOraclesid號。Thread為會話對應的執行緒的編號。我們可以透過v$sessionv$process的資訊獲取。

 

SQL> select b.username, a.spid, b.username, b.sid, b.osuser, b.action

  2  from v$process a, v$session b

  3  where a.ADDR=b.PADDR and b.username='SYS';

 

USERNAME  SPID         USERNAME   SID OSUSER                         ACTION

--------- ------------ ---------- ------------------------------ --------------------------------

SYS       1464         SYS        152 WWW-0E6111DFF74\Administrator  Command Window - New

SYS       632          SYS        141 WWW-0E6111DFF74\Administrator  Main session

 

 

注意下v$processSPID列。在Linux/Unix環境下,這個列的SPID表示Process的編號。在Windows環境下,這列就表示在ORACLE.exe程式下的執行緒編號。

 

我們嘗試刪除命令視窗執行緒(SPID=1464)。

 

C:\>orakill orcl 1464

 

Kill of thread id 1464 in instance orcl successfully signalled.

 

 

命令視窗再次嘗試連線時。

 

SQL> select count(*) from dba_objects;

Warning: connection was lost and re-established

 

 

說明:連線被切斷。

 

此外,orakill命令也可以在SQL命令提示中使用。

 

SQL> host orakill orcl 3140

 

Kill of thread id 3140 in instance orcl successfully signalled.

 

SQL>

 

 

 

結論:在Windows平臺上,可以使用orakill工具進行sessionserver的殺死工作。

 

最後,筆者還要強調一下。無論是kill session還是kill -9操作,都是一種危險的操作,特別是在生產環境下。原因在於,後臺程式特別是核心後臺程式(PMONSMONDBWNLGWR)如果被誤刪除,相當於例項死掉,是一件重大事故。在沒有確認需要、沒有專業人員許可的情況下,儘可能的選取破壞性小的方案進行處理。

 

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

相關文章