千家信息网

Oracle 彻底 kill session的示例分析

发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,这期内容当中小编将会给大家带来有关Oracle 彻底 kill session的示例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。Oracle 彻底 kill
千家信息网最后更新 2024年09月22日Oracle 彻底 kill session的示例分析

这期内容当中小编将会给大家带来有关Oracle 彻底 kill session的示例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

Oracle 彻底 kill session

killsessionDBA经常碰到的事情之一。如果kill掉了不该killsession,则具有破坏性,因此尽可能的避免这样的错误发生。同时也应当注意,

如果killsession属于Oracle后台进程,则容易导致数据库实例宕机。

通常情况下,并不需要从操作系统级别杀掉Oracle会话进程,但并非总是如此,下面的描述中给出了在Oracle级别杀掉会话以及操作系统级别杀掉进程。

一、获得需要kill session的信息(使用V$SESSIONGV$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命令实现

语法:

SQL>ALTERSYSTEMKILLSESSION'sid,serial#';

SQL>ALTERSYSTEMKILLSESSION'sid,serial#'IMMEDIATE;

对于RAC环境下的killsession,需要搞清楚需要killsession位于哪个节点,可以查询GV$SESSION视图获得。

killsession的时候仅仅是将会话杀掉。在有些时候,由于较大的事务或需要运行较长的SQL语句将导致需要killsession并不能立即杀掉。对于这种情

况将收到"marked for kill"提示(如下),一旦会话当前事务或操作完成,该会话被立即杀掉。

altersystemkillsession'4730,39171'

*

ERRORatline1:

ORA-00031:sessionmarkedforkill

在下面的操作中将杀掉会话146144

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地址发生了变化,参照查询结果中的红色字体。如果多个sessionkill掉,则多个sessionPADDR

被改为相同的进程地址。

通过下面的语句来找回被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)

上面的查询中有一个SID2731的位于节点2上。

也可以通过下面的方式来获得RAC的节点信息,便于确定需要killsession究竟位于哪一个节点。

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相关的其他几篇文章

原文地址:http://www.eygle.com/archives/2004/06/kill_session.html

Oracle中Kill session的研究

作者:eygle | 出处和作者信息及本声明】
链接:http://www.eygle.com/archives/2004/06/kill_session.html

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                          INACTIVE542E5044         18        662 542B6D38 SYS                            ACTIVESQL> 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                          KILLED542E5044         18        662 542B6D38 SYS                            ACTIVESQL> 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                          KILLED542E2AA4         14        397 542B7498 EQSP                           INACTIVE542E5044         18        662 542B6D38 SYS                            ACTIVESQL> 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                          KILLED542E2AA4         14        397 542D6BD4 EQSP                           KILLED542E5044         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    1USERNAME                       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                       0SYS                            INACTIVE 542B7BF8          1         15 24081               195 EV16 rows selected.

我们注意,红字标出的部分就是被Kill掉的进程的进程地址.

简化一点,其实就是如下概念:

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-
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

原文地址:http://space.itpub.net/22578826/viewspace-702988

很多时候由于异常或程序错误会导致个别进程占用大量系统资源,需要结束这些进程,通常可以使用以下命令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 scott/tiger@wilson

已连接。


观察会话情况,查询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 oracle@oracle11g


我们可以看出,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 oracle@oracle11g

"怪事"发生了,我们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 oracle@oracle11g

结论:当我们在原有窗口执行操作,尝试会话通信时,被拒绝。通过视图查询,发现原有被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 oracle@oracle11g(J000)

诶,为什么有记录呢?仔细看看: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 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平台上,就有一些问题了。由于体系结构的不同,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为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)如果被误删除,相当于实例死掉,是一件重大事故。在没有确认需要、没有专业人员许可的情况下,尽可能的选取破坏性小的方案进行处理。

上述就是小编为大家分享的Oracle 彻底 kill session的示例分析了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

0