菜鸟lei的学习成长空间

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

      在要drop一个数据库用户时发现这个用户已连接到数据库,因此没法直接drop掉这个用户。使用

  1: select * from v$session where username='USERNAME' and STATUS <>'KILLED'

查看出要kill掉的session后,发现有近15个session。发现这样一个个去kill,太慢了,就来了招狠的:

  1: SELECT CONCAT('ALTER SYSTEM KILL SESSION ''',CONCAT(CONCAT(CONCAT(SID,','),SERIAL#),''';')) FROM V$SESSION WHERE USERNAME='SCOTT'

最后生成了一堆类似:

  1: ALTER SYSTEM KILL SESSION 'SID,SERIAL';

这样的语句。

      将这一堆语句贴到dbvis中,执行了下,确实是把所有与USERNMAE相关的sessionkill掉了,但是下次用USERNAME用户登录后,发现session个数并没有掉下去。

      从网上查资料来看,“当一个session被kill掉以后,该session的paddr被修改,如果有多个 session被kill,那么多个session的paddr都被更改为相同的进程地址”,在这种情况下,先前被占用的资源是无法被释放的,因此要从操作系统级去释放这些资源。实际上,在数据库层,每生成一个session,在Solaris上会新增一个oracle用户的进程,windows上由于有线程机制,会在oracle.exe中生成对应的线程。

      因此,在Solaris下,确定好了要清除的session对应的操作系统级别的进程,然后在把这些进程kill掉,下次进入系统,就可以看到先前被占用的session在V$SESSION中找不到了。

      那么,怎么去判断要被清除掉的session对应的操作系统进程呢?网上有位前辈说“当在Oracle中kill session以后, Oracle只是简单的把相关session的paddr 指向同一个虚拟地址.此时v$process和v$session失去关联,进程就此中断.然后Oracle就等待PMON去清除这些Session.所以通常等待一个被标记为Killed的 Session退出需要花费很长的时间.”

根据那位牛人的文章,我自己写了个sql:

  1: SELECT CONCAT('kill -9 ',SPID) FROM V$PROCESS WHERE V$PROCESS.ADDR IN(
  2: 
  3: select p.addr from v$process p where pid <> 1
  4: 
  5: minus
  6: 
  7: select s.paddr from v$session s)

      在dbvis中执行,执行的结果是生成一堆(又是一堆,-_-!)kill –9  pid这样的语句,将执行结果贴到securecrt中(此时securecrt以oracle用户连接到了对应的Solaris机器上),执行完成后,再用先前的USERNAME这个用户登录数据库,TOUCH一下,退出后,就可以用dba用户drop掉USERNAME用户了。

补充:最后上网找了半天,终于把那位牛人前辈的文章位置找到了:http://www.eygle.com/archives/2004/06/kill_session.html

posted on 2011-04-08 11:07  菜鸟-雷  阅读(1501)  评论(0编辑  收藏  举报