开发者社区> 长烟慢慢> 正文

kill会话过程分析+

简介: 转自:http://space.itpub.net/?uid-17203031-action-viewspace-itemid-684039 在实际开发中,我们常常需要将用户的会话强制断开。
+关注继续查看

转自:http://space.itpub.net/?uid-17203031-action-viewspace-itemid-684039

在实际开发中,我们常常需要将用户的会话强制断开。比如:事务执行超时、代码出现死循环、死锁或者无意中将数据表锁住。这个使用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=1Serial#=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,进程编号为5803PIDOracle相关进程的内部编号,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

 

//发现,会话SCOTTSID=1Serial#=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     25          5956            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释放;

 

我们知道,当需要强制断开一个会话的时候,可以通过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 | 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时间最后一列一般为启动命令行。

 

其中,我们比较关注的就是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 <sid> <thread>

其中,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 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.


 

结论:在Windows平台上,可以使用orakill工具进行sessionserver的杀死工作。

 

最后,笔者还要强调一下。无论是kill session还是kill -9操作,都是一种危险的操作,特别是在生产环境下。原因在于,后台进程特别是核心后台进程(PMONSMONDBWNLGWR)如果被误删除,相当于实例死掉,是一件重大事故。在没有确认需要、没有专业人员许可的情况下,尽可能的选取破坏性小的方案进行处理。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
冬季实战营第一期:从零到一上手玩转云服务器 | 学习报告
训练营日期:2022年1月17日 - 2022年1月23日 需要先报名后学习,实际是17-21共5天5个场景的学习,链接地址:https://developer.aliyun.com/adc/series/wintercamplist1?spm=a2c6h.26268694.J_3660455150.2.503610f8RnszVx 我是5月份学习的,并没有实时参加训练营,因为觉着本次训练营课程设置很实用,所以对本次学习做个总结。
6 0
手撸一款简单高效的线程池(五)
在之前的内容中,我们给大家介绍了 C++实现线程池过程中的一些常用线优化方案,并分析了不同机制使用时的利弊。这一篇,是线程池系列的最后一章。我们会介绍一下 CGraph 中的 threadpool 如何使用,给出性能对比,并对接下来的工作做一些展望。让我们在线程池性能优化和功能提升的道路上,越走越远。
5 0
心中有“树”!图文并茂介绍数据结构中常见的树(一)
提到数据结构中的树(Tree) ,大家应该都不陌生,相关书籍中都有大段篇幅的介绍,刷 Leetcode 的时候会遇到很多相关问题。很多人往往会用 “手写红黑树” 来形容面试难度很高。
10 0
心中有“树”!图文并茂介绍数据结构中常见的树(二)
计算机科学家尼古拉斯·沃斯(Niklaus Wirth)曾说过:编程=数据结构+算法 ,可见数据结构在编程中的重要性。
5 0
心中有“树”!图文并茂介绍数据结构中常见的树(三)
在前面两篇文章中,我们简要介绍了数据结构中的各种【树】在搜索、数据库等领域的使用场景,希望对大家有所帮助。
11 0
如何在小游戏制作工具中使用云函数
本节试图以最简单的方式带你了解如何在小程序后台申请和开通云开发服务,创建并编写第一个云函数并在小游戏制作工具中对其进行调用。
11 0
Win系统 - 重装系统(微PE、MSDN镜像)【绝对纯净】
Win系统 - 重装系统(微PE、MSDN镜像)【绝对纯净】
14 0
+关注
长烟慢慢
系统架构师
814
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载