咱們知道,在Oracle數據庫中,能夠經過kill session的方式來終止一個進程,其基本語法結構爲:數據庫
alter system kill session 'sid,serial#' ;session
被kill掉的session,狀態會被標記爲killed,Oracle會在該用戶下一次touch時清除該進程.spa
咱們發現當一個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這些進程.code
可是因爲此時v$session.paddr已經改變,咱們沒法經過v$session和v$process關聯來得到spid進程
那還能夠怎麼辦呢?資源
咱們來看一下下面的查詢:
it
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 EVSYS INACTIVE 542B7848 0 0 0 SYS INACTIVE 542B7BF8 1 15 24081 195 EV 16 rows selected.
咱們注意,紅字標出的部分就是被Kill掉的進程的進程地址.
io
簡化一點,其實就是以下概念:class
SQL> select p.addr from v$process p where pid <> 1 2 minus 3 select s.paddr from v$session s;
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-