【kill session】Oracle 徹底 kill session(轉載)
偶然間看到一篇關於Kill session的文章,很不錯,mark一下,備忘。
原文地址:http://space.itpub.net/22578826/viewspace-702987
Oracle 徹底
--***************************
-- Oracle徹底kill session
--***************************
killsession是DBA經常碰到的事情之一。如果kill掉了不該kill的session,則具有破壞性,因此盡可能的避免這樣的錯誤發生。同時也應當注意,
如果kill的session屬於Oracle後臺進程,則容易導致數據庫實例當機。
通常情況下,並不需要從操作系統級別殺掉Oracle會話進程,但並非總是如此,下面的描述中給出了在Oracle級別殺掉會話以及操作系統級別殺掉進程。
一、獲得需要kill session的資訊(使用V$SESSION和GV$SESSION檢視)
SETLINESIZE180
COLUMNspid FORMAT A10
COLUMNusername FORMAT A10
COLUMNprogram FORMAT A40
SELECTs.inst_id,
s.sid,
s.serial#,
p.spid,
s.username,
s.program,
s.paddr,
s.STATUS
FROM gv$session s
JOINgv$process pONp.addr = s.paddrANDp.inst_id = s.inst_id
WHERE s.type !='BACKGROUND';
INST_ID SID SERIAL# SPID USERNAME PROGRAM PADDR STATUS
---------- ---------- ---------- ---------- ---------- --------------------------------------------- -------- --------
1 146 2327573 TEST sqlplus@oracle10g (TNS V1-V3) 4C621950INACTIVE
1 160 1727610 SYS sqlplus@oracle10g (TNS V1-V3) 4C624174 ACTIVE
1 144 4227641 SCOTT sqlplus@oracle10g (TNS V1-V3) 4C624730INACTIVE
二、使用ALTERSYSTEMKILLSESSION命令實現
語法:
>ALTERSYSTEMKILLSESSION'sid,serial#';
SQL>ALTERSYSTEMKILLSESSION'sid,serial#'IMMEDIATE;
對於環境下的killsession,需要搞清楚需要kill的session位於哪個節點,可以查詢GV$SESSION檢視獲得。
killsession的時候僅僅是將會話殺掉。在有些時候,由於較大的事務或需要運行較長的SQL語句將導致需要kill的session並不能立即殺掉。對於這種情
況將收到"marked for kill"提示(如下),一旦會話當前事務或操作完成,該會話被立即殺掉。
altersystemkillsession'4730,39171'
*
ERRORatline1:
ORA-00031:sessionmarkedforkill
在下面的操作中將殺掉會話146,144
sys@AUSTIN>altersystemkillsession'146,23';
Systemaltered.
sys@AUSTIN>altersystemkillsession'144,42';
Systemaltered.
sys@AUSTIN>selectinst_id,saddr,sid,serial#,paddr,username,status,programfromgv$sessionwhereusernameisnotnull;
INST_ID SADDR SID SERIAL# PADDR USERNAME STATUS PROGRAM
---------- -------- ---------- ---------- -------- ---------- -------- ---------------------------------------------
14C70BF04 144 424C6545A0SCOTT KILLED sqlplus@oracle10g (TNS V1-V3)
14C70E6B4 146 234C6545A0TEST KILLED sqlplus@oracle10g (TNS V1-V3)
14C71FC84 160 174C624174SYS ACTIVE sqlplus@oracle10g (TNS V1-V3)
注意:在查詢中可以看到被殺掉的會話的PADDR地址發生了變化,參照查詢結果中的紅色字型。如果多個session被kill掉,則多個session的PADDR
被改為相同的進程地址。
通過下面的語句來找回被kill掉的ADDR先前的地址
SELECTs.username,s.status,
x.ADDR,x.KSLLAPSC,x.KSLLAPSN,x.KSLLASPO,x.KSLLID1R,x.KSLLRTYP,
decode(bitand(x.ksuprflg,2),0,null,1)
FROMx$ksupr x,v$session s
WHEREs.paddr(+)=x.addr
andbitand(ksspaflg,1)!=0;
USERNAME STATUS ADDR KSLLAPSC KSLLAPSN KSLLASPO KSLLID1RKSD
---------- -------- -------- ---------- ---------- ------------ ---------- -- -
ACTIVE 4C623BB8 99 427468 275EV1
ACTIVE 4C623040 9 2427444 0 1
ACTIVE 4C622A84 101 427480 274EV1
ACTIVE 4C6224C8 1 4827450 0 1
ACTIVE 4C621F0C 1 4827450 0 1
ACTIVE 4C6235FC 2 427468 0 1
SYS ACTIVE 4C624174 2 1527442 0
ACTIVE 4C62081C 1 4827440 0 1
ACTIVE 4C621394 1 4827440 0 1
ACTIVE 4C620DD8 11 2427476 0 1
ACTIVE 4C61F6E8 15 427610 0 1
ACTIVE 4C620260 222 2427450 0 1
ACTIVE 4C61FCA4 7 2527573 0 1
ACTIVE 4C61F12C 6 2527573 0 1
ACTIVE 4C61EB70 4 2427458 0 1
ACTIVE 4C61E5B4 1 4827440 0 1
ACTIVE 4C61DFF8 2 2427444 0 1
4C624730 0 0 0
4C621950 0 0 0
4C61DA3C 0 0 0
或者根據下面的語句來獲得發生變化的addr
sys@AUSTIN>selectp.addrfromv$process pwherepid <>1
2 minus
3 selects.paddrfromv$session s;
ADDR
--------
4C621950
4C624730
三、在操作系統級別殺掉會話
尋找會話對應的操作系統的進程ID
sys@AUSTIN>selectSPIDfrom v$processwhereADDRin('4C621950','4C624730') ;
SPID
----------
27573
27641
使用kill命令來殺掉操作系統級別進程ID
killsession-927573
killsession-927641
四、獲得當前會話的SID
SQL>selectuserenv('sid')fromdual;
USERENV('SID')
--------------
627
五、多個會話需要kill的處理辦法
1.根據給定的SID(用戶名)查找需要殺掉會話的資訊,包括位於哪一個實例
setlinesize160
col program format a35
col username format a18
selectinst_id,saddr,sid,serial#,paddr,username,status,programfromgv$session
wheresidin('2731','2734','2720','2678','2685')
andusername='CTICUST'
orderbyinst_id;
INST_ID SADDR SID SERIAL# PADDR USERNAME STATUS PROGRAM
---------- ---------------- ---------- ---------- ---------------- ------------------ -------- ---------------------------
100000003DAF8F870 2678 826500000003DBC6CA08 MSS4USR INACTIVE JDBC Thin Client
100000003DAF98E48 2685 8300000003DBC08510 MSS4USR ACTIVE JDBC Thin Client
100000003DAFC7B80 2720 500000003DBBEDA20 MSS4USR INACTIVE JDBC Thin Client
100000003DAFD66F8 2731 300000003DBBE9AE0SYS ACTIVE racgimon@svdg0028(TNS V1-V3)
100000003DAFDA730 2734 1500000003DBBEC268 MSS4USR INACTIVE JDBC Thin Client
200000003DAFD66F8 2731 100000003DBBE92F8 ACTIVE oracle@svdg0029 (ARC0)
上面的查詢中有一個SID為2731的位於節點2上。
也可以通過下面的方式來獲得RAC的節點資訊,便於確定需要kill的session究竟位於哪一個節點。
setlinesize160
col HOST_NAME format a25
SQL>selectINSTANCE_NUMBER,INSTANCE_NAME,HOST_NAME,VERSION,STATUSfromgv$instanceorderby1;
INSTANCE_NUMBER INSTANCE_NAME HOST_NAME VERSION STATUS
--------------- ---------------- ------------------------- ----------------- ------------
1O02WMT1A svd0051 10.2.0.4.0 OPEN
2O02WMT1B svd0052 10.2.0.4.0 OPEN
3O02WMT1C svd0053 10.2.0.4.0 OPEN
2.使用下面查詢來生成killsession的語句
select'alter system kill session '''||sid||','||SERIAL# ||''''||';' from gv$session
wheresidin('2731','2734','2720','2678','2685')
orderbyinst_id;
獲得下列kill session的語句,根據要求由於此次需要殺掉的session全部位於節點1,因此登錄到節點節點1執行下面的語句
altersystemkillsession'2678,8265';
altersystemkillsession'2685,83';
altersystemkillsession'2720,5';
altersystemkillsession'2731,3';
altersystemkillsession'2734,15';
altersystemkillsession'2731,1'; --此條命令不需要執行,該session位於節點2。
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
與Kill Session相關的其他幾篇文章
原文地址:
Oracle中Kill session的研究
連結:
itpub link:
http://www.itpub.net/235873.html
我們知道,在Oracle資料庫中,可以透過kill session的方式來終止一個程式,其基本語法結構為:
alter system kill session 'sid,serial#' ;
被kill掉的session,狀態會被標記為killed,Oracle會在該使用者下一次touch時清除該程式.
我們發現當一個session被kill掉以後,該session的paddr被修改,如果有多個session被kill,那麼多個session
的paddr都被更改為相同的程式地址:
SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null; SADDR SID SERIAL# PADDR USERNAME STATUS -------- ---------- ---------- -------- ------------------------------ -------- 542E0E6C 11 314 542B70E8 EYGLE INACTIVE 542E5044 18 662 542B6D38 SYS ACTIVE SQL> alter system kill session '11,314'; System altered. SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null; SADDR SID SERIAL# PADDR USERNAME STATUS -------- ---------- ---------- -------- ------------------------------ -------- 542E0E6C 11 314 542D6BD4 EYGLE KILLED 542E5044 18 662 542B6D38 SYS ACTIVE SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null; SADDR SID SERIAL# PADDR USERNAME STATUS -------- ---------- ---------- -------- ------------------------------ -------- 542E0E6C 11 314 542D6BD4 EYGLE KILLED 542E2AA4 14 397 542B7498 EQSP INACTIVE 542E5044 18 662 542B6D38 SYS ACTIVE SQL> alter system kill session '14,397'; System altered. SQL> select saddr,sid,serial#,paddr,username,status from v$session where username is not null; SADDR SID SERIAL# PADDR USERNAME STATUS -------- ---------- ---------- -------- ------------------------------ -------- 542E0E6C 11 314 542D6BD4 EYGLE KILLED 542E2AA4 14 397 542D6BD4 EQSP KILLED 542E5044 18 662 542B6D38 SYS ACTIVE
在這種情況下,很多時候,資源是無法釋放的,我們需要查詢spid,在作業系統級來kill這些程式.
但是由於此時v$session.paddr已經改變,我們無法透過v$session和v$process關聯來獲得spid
那還可以怎麼辦呢?
我們來看一下下面的查詢:
SQL> SELECT s.username,s.status,
2 x.ADDR,x.KSLLAPSC,x.KSLLAPSN,x.KSLLASPO,x.KSLLID1R,x.KSLLRTYP,
3 decode(bitand (x.ksuprflg,2),0,null,1)
4 FROM x$ksupr x,v$session s
5 WHERE s.paddr(+)=x.addr
6 and bitand(ksspaflg,1)!=0;
USERNAME STATUS ADDR KSLLAPSC KSLLAPSN KSLLASPO KSLLID1R KS D
------------------------------ -------- -------- ---------- ---------- ------------ ---------- -- -
542B44A8 0 0 0
ACTIVE 542B4858 1 14 24069 0 1
ACTIVE 542B4C08 26 16 15901 0 1
ACTIVE 542B4FB8 7 46 24083 0 1
ACTIVE 542B5368 12 15 24081 0 1
ACTIVE 542B5718 15 46 24083 0 1
ACTIVE 542B5AC8 79 4 15923 0 1
ACTIVE 542B5E78 50 16 24085 0 1
ACTIVE 542B6228 754 15 24081 0 1
ACTIVE 542B65D8 1 14 24069 0 1
ACTIVE 542B6988 2 30 14571 0 1
USERNAME STATUS ADDR KSLLAPSC KSLLAPSN KSLLASPO KSLLID1R KS D
------------------------------ -------- -------- ---------- ---------- ------------ ---------- -- -
SYS ACTIVE 542B6D38 2 8 24071 0
542B70E8 1 15 24081 195 EV
542B7498 1 15 24081 195 EV
SYS INACTIVE 542B7848 0 0 0
SYS INACTIVE 542B7BF8 1 15 24081 195 EV
16 rows selected.
我們注意,紅字標出的部分就是被Kill掉的程式的程式地址.
簡化一點,其實就是如下概念:
SQL> select p.addr from v$process p where pid <> 1
2 minus
3 select s.paddr from v$session s;ADDR
--------
542B70E8
542B7498
Ok,現在我們獲得了程式地址,就可以在v$process中找到spid,然後可以使用Kill或者orakill在系統級來殺掉這些程式.
實際上,我猜測:
當在Oracle中kill session以後, Oracle只是簡單的把相關session的paddr 指向同一個虛擬地址.
此時v$process和v$session失去關聯,程式就此中斷.
然後Oracle就等待PMON去清除這些Session.所以通常等待一個被標記為Killed的Session退出需要花費很長的時間.
如果此時被Kill的process,重新嘗試執行任務,那麼馬上會收到程式中斷的提示,process退出,此時Oracle會立即啟動PMON
來清除該session.這被作為一次異常中斷處理.
-The End-
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
原文地址:http://space.itpub.net/22578826/viewspace-702988
Oracle HowTo:如何快速殺死佔用過多資源(CPU,記憶體)的資料庫程式
很多時候由於異常或程式錯誤會導致個別程式佔用大量系統資源,需要結束這些程式,通常可以使用以下命令Kill程式:
alter system kill session 'sid,serial#';
但是此命令釋放資源極為緩慢,為了更快速的釋放資源,通常我們使用如下步驟來Kill程式:
1.首先在作業系統級kill程式
2.在資料庫內部kill session
這樣通常可以快速中止程式,釋放資源。
今天就遇到這樣一個案例,其他朋友在資料庫裡kill session,可是長時間仍無效果:
[oracle@danaly ~]$ sqlplus "/ as sysdba"
SQL*Plus: Release 10.2.0.1.0 - Production on Thu Oct 27 11:09:50 2005
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Data Mining Scoring Engine options
SQL> select sid,username,status from v$session;
SID USERNAME STATUS
---------- ------------------------------ --------
....
154 SCOTT KILLED
...
30 rows selected.
那按照我前面提到的步驟,首先查詢得到該session對應的OS程式號:
SQL> select 'kill -9 '||spid from v$process where addr = (select paddr from v$session where sid=&sid);
Enter value for sid: 154
old 1: select 'kill -9 '||spid from v$process where addr = (select paddr from v$session where sid=&sid)
new 1: select 'kill -9 '||spid from v$process where addr = (select paddr from v$session where sid=154)
'KILL-9'||SPID
--------------------
kill -9 22702
SQL> !
在作業系統級kill該程式:
[oracle@danaly ~]$ ps -ef|grep 22702
oracle 22702 1 0 Oct25 ? 00:00:02 oracledanaly (LOCAL=NO)
oracle 12082 12063 0 11:12 pts/1 00:00:00 grep 22702
[oracle@danaly ~]$ kill -9 22702
[oracle@danaly ~]$ ps -ef|grep 22702
oracle 12088 12063 0 11:12 pts/1 00:00:00 grep 22702
[oracle@danaly ~]$ exit
exit
SQL> select sid,username,status from v$session;
SID USERNAME STATUS
---------- ------------------------------ --------
...
154 SCOTT KILLED
...
30 rows selected.
SQL> select sid,serial#,username from v$session where sid=154;
SID SERIAL# USERNAME
---------- ---------- ------------------------------
154 56090 SCOTT
再次在資料庫中kill該session,並指定immediate選項:
SQL> alter system kill session '154,56090' immediate;
System altered.
SQL> select sid,serial#,username from v$session where sid=154;
no rows selected
此時該程式被迅速清除。
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
原文地址:http://space.itpub.net/17203031/viewspace-683786
Kill會話過程分析
在實際開發中,我們常常需要將使用者的會話強制斷開。比如:事務執行超時、程式碼出現死迴圈、死鎖或者無意中將資料表鎖住。這個使用kill session是很實用的方法。那麼,kill session的時候,系統究竟發生了什麼呢?
基礎知識
使用者連線到資料庫,涉及到幾個物件。首先是監聽器,我們常常使用的本地命名服務(tnsname.ora),實際上連線的就是監聽器。但是,對於我們連線過程來說,與監聽器打交道的時間還是很短暫的(詳細可以見筆者其他討論監聽器和連線的文章)。其次是Server Process,是客戶端應用在資料庫伺服器上的操作代表。所有對於資料庫例項、資料檔案和SGA的操作,實際執行都是Server Process來進行的。最後就是以PMON為代表的後臺程式(影子程式),他們負責管理例項的方方面面,保證各方面職能正確實現。
另一個邏輯層次上,使用者會話session是一個重要概念。在特定的情況下,我們可以說使用者與資料庫的互動,就是在一個持續的session中完成。在一個session中,使用者可以執行多個事務,可以處在閒置狀態(Inactive)。
在任何情況下,如果我們強制性的斷開連線,放開session(主動)。PMON後臺程式會主動的做回收處理工作(在繁忙的時候存在延時)。回收包括清理會話資訊,回滾未提交事務,釋放Server Process資源(專用模式下)。
在一些時候,我們可以藉助alter system kill session ‘sid, serial#’;來手工強制斷開使用者連線。那麼,Oracle進行kill的時候,究竟發生了什麼呢?讓我一起來研究。
實驗環境構建
Connected to Oracle Database11gEnterpriseEdition Release11.2.0.1.0
Connected as SYS
//檢視元件版本:使用SYS登入
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database11gEnterpriseEdition Release11.2.0.1.0 - Production
PL/SQL Release11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version11.2.0.1.0 - Production
NLSRTL Version11.2.0.1.0 - Production
首先,為了簡便,筆者啟動了PL/SQL Developer,並且開啟一個Command視窗。之後,啟動一個sqlplus視窗,觀察這個視窗對應的會話情況。
在sqlplus視窗中。
SQL> conn
已連線。
觀察會話情況,查詢v$session。
SQL> select saddr, sid, serial#, paddr, username, program,action,status from v$session where username in ('SYS','SCOTT');
SADDR SID SERIAL# PADDR USERNAME PROGRAM ACTION STATUS
-------- ----- ---------- -------- ---------- --------------- --------------- --------
382F0074 1 64 38BC6C94 SCOTT sqlplusw.exe INACTIVE
382B30C0 24 80 38BC61BC SYS plsqldev.exe Main session INACTIVE
3829B2F4 33 10 38BC8244 SYS plsqldev.exe Command Window ACTIVE
- New
可以發現,會話中多了三個session。兩個使用者名稱SYS的會話是PL/SQL Developer開啟的(原理見之前部落格內容)。另一個SCOTT使用者開啟的sqlplusw.exe是我們的實驗物件,發現其sid=1,Serial#=64。會話對應的Server Process實體地址為38BC6C94。
之後,我們查詢的對應的server Process資訊,從v$process。
SQL> select addr,pid,spid,username,serial#,program from v$process where addr='38BC6C94';
ADDR PID SPID USERNAME SERIAL# PROGRAM
-------- ---------- ------------------------ ---------- ---------- -------------------------
38BC6C94 25 5803 oracle 23
我們可以看出,Scott使用者會話SID=1對應的Server Process,程式編號為5803(PID為Oracle相關程式的內部編號,SPID表示的是作業系統級別)。
最後,我們檢視作業系統級別程式資訊。
[oracle@oracle11g~]$ ps -ef | grep LOCAL
oracle 5780 1 0 05:47 ? 00:00:03 oraclewilson (LOCAL=NO)
oracle 5788 1 0 05:48 ? 00:00:00 oraclewilson (LOCAL=NO)
oracle 5803 1 0 05:50 ? 00:00:00 oraclewilson (LOCAL=NO) //對於的那個Server Process
實驗kill會話。
在觀察PL/SQL Developer裡,將SCOTT會話斷開。
SQL> alter system kill session '1,64';
System altered
Kill操作執行完成,沒有報錯。那麼,這個會話資訊真的被刪除了嗎?我們重新檢查v$session。
//發現,會話SCOTT(SID=1,Serial#=64資訊還存在)
SQL> select saddr, sid, serial#, paddr, username, program,action,status from v$session where username in ('SCOTT');
SADDR SID SERIAL# PADDR USERNAME PROGRAM ACTION STATUS
-------- ----- ---------- -------- ---------- ------------------------- --------------- --------
382F0074 1 64 38058594 SCOTT sqlplusw.exe KILLED
//按照原來的Server Process地址查詢Server Process資訊還存在;
SQL> select addr,pid,spid,username,serial#,program from v$process where addr='38BC6C94';
ADDR PID SPID USERNAME SERIAL# PROGRAM
-------- ---------- ------------------------ ---------- ---------- -------------------------
38BC6C94 25 5803 oracle 23
“怪事”發生了,我們kill掉了會話。但是會話資訊還存在,與剛才的結果區別是兩個:其一為會話的狀態變為了KILLED狀態,表示已經被kill。其二是對應Server Process的地址被修改,該到了38058594的位置上。
而檢視v$process程式檢視,發現原來為其服務的Server Process資訊仍然存在!那麼,是真的存在嗎?我們檢視作業系統層面:
[oracle@oracle11g~]$ ps -ef | grep LOCAL
oracle 5780 1 0 05:47 ? 00:00:03 oraclewilson (LOCAL=NO)
oracle 5788 1 0 05:48 ? 00:00:00 oraclewilson (LOCAL=NO)
oracle 5803 1 0 05:50 ? 00:00:00 oraclewilson (LOCAL=NO)
看來Server Process確實存在。那麼這個新Server Process地址38058594是什麼呢?
SQL> select addr,pid,spid,username,serial#,program from v$process where addr='38058594';
ADDR PID SPID USERNAME SERIAL# PROGRAM
-------- ---------- ------------------------ ---------- ---------- -------------------------
綜合上述:在kill的時候,Oracle做了兩件事。一件是將會話的狀態修改了KILLED,相當於打了一個標記。第二件是透過將會話對應的Server Process地址修改為一個虛擬地址,切斷會話資訊與Server Process的對映關聯。此外,Server Process並沒有回收。
等待一會之後,發現依然如此!沒有PMON主動的回收動作。
那麼,如果此時被kill掉的會話發起一個操作,如何?
在sqlplus上:
SQL> select * from emp;
select * from emp
*
第1行出現錯誤:
ORA-00028:您的會話己被終止
被斷開的會話拒絕操作,告知說會話已經被終止。
此時,系統還能檢視到這個會話資訊嗎?
SQL> select saddr, sid, serial#, paddr, username, program,action,status from v$session where username in ('SCOTT');
SADDR SID SERIAL# PADDR USERNAME PROGRAM ACTION STATUS
-------- ----- ---------- -------- ---------- ------------------------- --------------- --------
SQL> select addr,pid,spid,username,serial#,program from v$process where addr='38BC6C94';
ADDR PID SPID USERNAME SERIAL# PROGRAM
-------- ---------- ------------------------ ---------- ---------- -------------------------
38BC6C94 25 5803 oracle 23
結論:當我們在原有視窗執行操作,嘗試會話通訊時,被拒絕。透過檢視查詢,發現原有被kill的會話資訊被回收。但是Server Process還存在在檢視上,但不與任何會話對應。
那作業系統層面上:
[oracle@oracle11g~]$ ps -ef | grep LOCAL
oracle 5780 1 0 05:47 ? 00:00:03 oraclewilson (LOCAL=NO)
oracle 5788 1 0 05:48 ? 00:00:00 oraclewilson (LOCAL=NO)
oracle 5803 1 0 05:50 ? 00:00:00 oraclewilson (LOCAL=NO)
該Server Process還存在,沒有回收。
注意:當我們關閉掉sqlplusw視窗之後,也就是我們關掉客戶端的時候,我們再次查詢發現:
[oracle@oracle11g~]$ ps -ef | grep LOCAL
oracle 5780 1 0 05:47 ? 00:00:03 oraclewilson (LOCAL=NO)
oracle 5788 1 0 05:48 ? 00:00:00 oraclewilson (LOCAL=NO)
Server Process被回收,v$process自然也應當沒有對應記錄存在了。
SQL> select addr,pid,spid,username,serial#,program from v$process where addr='38BC6C94';
ADDR PID SPID USERNAME SERIAL# PROGRAM
-------- ---------- ------------------------ ---------- ---------- -------------------------
38BC6C94 255956 oracle 26 )
誒,為什麼有記錄呢?仔細看看:SPID已經發生變化,不是5803,而是5956,是一個新啟動的程式。只是使用了剛剛被釋放的地址。
結論:駐留在資料庫伺服器的Server Process會一直存在,直到客戶端應用斷開連線,不在於Server Process通訊。注意,這時如何客戶端重新連線conn,客戶端是重新與監聽器溝通,獲取一個新的Server Process重定向,不會找過去的那個舊Server Process。一旦重新登入,舊的Server Process就會被回收釋放掉。
綜上所述:在kill研究中,我們搞清楚了幾個方面問題:
1、alter system kill session:只是將session標記為可以回收,切斷會話與Server Process的對映關係。沒有進行資源釋放回收工作;
2、一旦嘗試連線,PMON會主動開始清理被kill的會話,同時Oracle拒絕連線操作;
3、Server Process是一個忠實於客戶端的程式,只要客戶端還在啟動,維持著兩個之間的聯絡。Server Process是不會被回收的。直到客戶端主動停止與Server Process的通訊,Server Process釋放;
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
原文地址:http://space.itpub.net/17203031/viewspace-684039
Kill會話過程分析(二)
本文為筆者“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 Process的kill操作,也就是OS作業系統級別的kill。當我們不能夠使用alter system kill session或者使用其無效的時候,可以考慮使用這種方法。
首先,我們研究一些Linux環境。選擇是專用連線模式。
在沒有連線的時候,我們檢視連線情況。
[oracle@oracle11g~]$ ps -ef | grepwilson| 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:00oraclewilson (LOCAL=NO)
[oracle@oracle11g~]$
連入了一個客戶端,在專用模式下有一個Server Process與之關聯。這裡對各列含義略作說明。
第一列表示執行使用者Owner,第二列是PID,表示程式的系統唯一編號。第三列表示該程式的父程式PPID編號,就是該程式是由哪個程式啟動的。之後有兩個時間值,分別為程式啟動到現在時間與佔用CPU時間。最後一列一般為啟動命令列。
其中,我們比較關注的就是PID。PID唯一的標識,如果強制終止這個程式,我們就可以強制的結束會話(皮之不存,毛將焉附)。同時,在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
已連線。
//kill之後,嘗試連線
SQL> select count(*) from emp;
select count(*) from emp
*
第1行出現錯誤:
ORA-03113:通訊通道的檔案結束//報錯!
使用kill -9命令,還可以對background process程式進行管理,對一些問題程式進行殺死重建,也是我們經常使用的手段。
結論:在Linux平臺上,當需要在作業系統級別進行kill的時候,可以使用kill -9命令。
接下來,我們在Windows平臺上,就有一些問題了。由於體系結構的不同,Oracle在Windows下實現的例項結構,並不是多程式架構方式,而採用的是多執行緒模式。Unix/Linux下的background process和Server Process,成為了一個ORACLE.exe程式裡的執行緒。那麼,這種情況下,我們如何處理?
為了應對這種情況,Oracle提供了一個為orakill.exe的命令。這個命令本質上和alter system kill session的功能相同,但是不需要登入連線資料庫。只需要輸入執行緒編號和SID就可以。
這樣,問題轉化為我們如果獲取到一個執行緒的執行緒編號。在Windows平臺上,有很多檢視執行緒的工具。如Qslice.exe、QuickSlice.exe以及Pstat。
語法:orakill <sid> <thread>;
其中,sid為Oracle的sid號。Thread為會話對應的執行緒的編號。我們可以透過v$session和v$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$process的SPID列。在Linux/Unix環境下,這個列的SPID表示Process的編號。在Windows環境下,這列就表示在ORACLE.exe程式下的執行緒編號。
我們嘗試刪除命令視窗執行緒(SPID=1464)。
C:\>orakill orcl 1464
Kill of thread id1464 ininstance 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 id3140 ininstance orcl successfully signalled.
SQL>
結論:在Windows平臺上,可以使用orakill工具進行session和server的殺死工作。
最後,筆者還要強調一下。無論是kill session還是kill -9操作,都是一種危險的操作,特別是在生產環境下。原因在於,後臺程式特別是核心後臺程式(PMON,SMON,DBWN,LGWR)如果被誤刪除,相當於例項死掉,是一件重大事故。在沒有確認需要、沒有專業人員許可的情況下,儘可能的選取破壞性小的方案進行處理。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29067253/viewspace-2137080/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle 徹底 kill sessionOracleSession
- Oracle中Kill session [轉]OracleSession
- Oracle kill sessionOracleSession
- Oracle kill session scriptOracleSession
- oracle_kill_sessionOracleSession
- Oracle中Kill sessionOracleSession
- Oracle批量kill sessionOracleSession
- kill sessionSession
- Oracle中Kill session的研究 for oracle -- 轉OracleSession
- awk -- kill sessionSession
- 【會話】Oracle kill session系列會話OracleSession
- Oracle中Kill session的研究OracleSession
- Alter system kill session and ORA-00031: session marked for killSession
- mysql批次kill sessionMySqlSession
- alter system kill sessionSession
- KILL SESSION 相關Session
- disconnect session和kill session的區別 轉Session
- 大話Oracle中的kill sessionOracleSession
- 無腦批量kill sessionSession
- 表鎖定,kill sessionSession
- kill session的學問Session
- kill session的測試Session
- Oracle kill session相關問題(上)OracleSession
- Oracle kill session相關問題(下)OracleSession
- 要 kill session 例子,session多,報錯如下Session
- disconnect session和kill session的區別Session
- ORACLE快速徹底Kill掉的會話Oracle會話
- ALTER SYSTEM KILL SESSION這麼沒力?(轉)Session
- Oracle中的Session kill不釋放問題OracleSession
- 批次kill session實現指令碼Session指令碼
- alter system kill session 不成功Session
- 定時kill長事務指令碼kill_long_session.sh指令碼Session
- 【Kill】兩條Linux命令徹底殺死OracleLinuxOracle
- kill session V$SESSION標記為KILLED 的2種情況Session
- 輕鬆接觸Oracle資料庫中的Kill sessionOracle資料庫Session
- [Oracle報錯處理]ORA-00031: session marked for killOracleSession
- 徹底理解cookie,session,tokenCookieSession
- 批量kill殺死某些會話session的plsql會話SessionSQL