• 如何杀掉Oracle的Session


    一、为什么要kill session
    很多的时候我们迅速的杀掉Oralcle的一些session,理由大体如下:

    1、  一些时候,由于我们的数据量很大,相应的事务大并且多,在做shutdown immediate的时候会花费好多的时间,而我们却想用shutdown immediate的方式,而又要把数据库迅速的shutdown下来。

    2、  我们的应用可能使用了会话控制,即在应用的层面控制了一些用户的连接的数量。但有时可能网络发生的瞬断,从而就产生了一些死进程,他们的状态为Inactive的状态。当我们用alter system kill session ‘sid,serial#’进行清除时,这些session的状态又变成了killed,这些就由Pmon进程来慢慢进行清除了,而你恰恰又是个急脾气。

    3、  系统忽然慢了现来,你发现是某个session在做怪,想迅速把它迅速结束掉。

    二、如何kill session
    锁的产生,config:

    (1)环境:PL/SQL developer:
    SQL> create table Spread(id number(6),
      2  mobile char(11)
      3  );
     
    Table created
     
    SQL> insert into spread(id,mobile)
      2  values(1,'13515127139');
     
    1 row inserted

    (2)环境:Rapid SQL
    insert into spread(id,mobile)
    values(3,'1583676639')
    /
    insert into spread(id,mobile)
    values(2,'1583676739')
    /
    update spread
    set mobile='11111111111'
    where id=1

    以上DML均未commit;

    (3)然后:
    truncate table spread

    接着报错:
    ORA-00054: resource busy and acquire with NOWAIT specified

    那么,怎么解决这个问题呢?
    首先找出这个表是不是被锁住?
    select b.owner table_owner,b.object_name,c.username,c.sid,c.serial#,c.PADDR
    from v$locked_object a,dba_objects b,v$session c
    where a.object_id=b.object_id and c.sid=a.session_id;
    ----------------
    TABLE_OWNER OBJECT_NAME USERNAME SID SERIAL# PADDR
    EDU SPREAD EDU 219 8244 0000000072B71878
    EDU SPREAD EDU 178 10231 0000000072B75FA0

    锁住的原因:
    SELECT lk.SID, se.username, se.osuser, se.machine,se.sid,se.serial#,se.PADDR,
           DECODE (lk.TYPE,
                   'TX', 'Transaction',
                   'TM', 'DML',
                   'UL', 'PL/SQL User Lock',
                   lk.TYPE
                  ) lock_type,
           DECODE (lk.lmode,
                   0, 'None',
                   1, 'Null',
                   2, 'Row-S (SS)',
                   3, 'Row-X (SX)',
                   4, 'Share',
                   5, 'S/Row-X (SSX)',
                   6, 'Exclusive',
               TO_CHAR (lk.lmode)
                  ) mode_held,
           DECODE (lk.request,
                   0, 'None',
                   1, 'Null',
                   2, 'Row-S (SS)',
                   3, 'Row-X (SX)',
                   4, 'Share',
                   5, 'S/Row-X (SSX)',
                   6, 'Exclusive',
                   TO_CHAR (lk.request)
                  ) mode_requested,
           TO_CHAR (lk.id1) lock_id1, TO_CHAR (lk.id2) lock_id2, ob.owner,
           ob.object_type, ob.object_name, lk.BLOCK, se.lockwait
      FROM v$lock lk, dba_objects ob, v$session se
     WHERE lk.TYPE IN ('TM', 'UL') AND lk.SID = se.SID AND lk.id1 = ob.object_id(+)
    ----------------------
    SID USERNAME OSUSER MACHINE SID SERIAL# PADDR LOCK_TYPE MODE_HELD MODE_REQUESTED LOCK_ID1 LOCK_ID2 OWNER OBJECT_TYPE OBJECT_NAME BLOCK LOCKWAIT
    178 EDU jhj EDU\JIANGHUANJUN 178 10231 0000000072B75FA0 DML Row-X (SX) None 123257 0 EDU TABLE SPREAD 0 [NULL]
    219 EDU jhj EDU\JIANGHUANJUN 219 8244 0000000072B71878 DML Row-X (SX) None 123257 0 EDU TABLE SPREAD 0 [NULL]

    /


    根据在Oracle数据库中,可以通过kill session的方式来终止一个进程,其基本语法结构为:
    alter system kill session 'sid,serial#' ; 
    然后
    alter system kill session '219,8244';
     System altered
     
    然后
    select b.owner table_owner,b.object_name,c.username,c.sid,c.serial#,c.PADDR
    from v$locked_object a,dba_objects b,v$session c
    where a.object_id=b.object_id and c.sid=a.session_id;
    显示为null
    而且再次提交原来的对话框 会提示 your session has been killed;
     
     
    查看此时的session"
    select saddr,sid,serial#,paddr,username,status 
    from v$session 
    where username='EDU'
    ------------------------------------
    SADDR SID SERIAL# PADDR USERNAME STATUS
    000000007208DA58 86 6469 0000000072B77758 EDU INACTIVE
    0000000072090528 88 9550 0000000072B77F40 EDU INACTIVE
    00000000720A9BE0 107 7623 0000000072B76F70 EDU INACTIVE
    00000000720C1D30 125 28979 0000000072B73030 EDU INACTIVE
    00000000720E49C0 151 12337 0000000072B796F8 EDU ACTIVE
    0000000072128D78 202 13727 0000000072B76788 EDU INACTIVE
       000000007213F960 219 8244 0000000072BDEA58 EDU KILLED   可以看到Killed
    000000007214A4A0 227 16252 0000000072B78728 EDU INACTIVE
    000000007216E698 254 11533 0000000072B747E8 EDU INACTIVE

    再kill一个session
    alter system kill session '86,6469' 
     
    查看此时的session对应的process
    select saddr,sid,serial#,paddr,username,status 
    from v$session 
    where username='EDU'
    order by paddr
    ---------------------------------
    SADDR                   SID    SERIAL# PADDR            USERNAME                       STATUS
    ---------------- ---------- ---------- ---------------- ------------------------------ --------
    00000000720C1D30        125      28979 0000000072B73030 EDU                            INACTIVE
    000000007216E698        254      11533 0000000072B747E8 EDU                            INACTIVE
    0000000072128D78        202      13727 0000000072B76788 EDU                            INACTIVE
    00000000720A9BE0        107       7623 0000000072B76F70 EDU                            INACTIVE
    0000000072090528         88       9550 0000000072B77F40 EDU                            INACTIVE
    000000007214A4A0        227      16252 0000000072B78728 EDU                            INACTIVE
    00000000720E49C0        151      12337 0000000072B796F8 EDU                            INACTIVE
     000000007208DA58         86       6469 0000000072BDEA58 EDU                            KILLED
     000000007213F960        219       8244 0000000072BDEA58 EDU                            KILLED
     被kill的两个session此时的process PADDR一致;
     
    这是什么原因嘞?
    在这种情况下,很多时候,资源是无法释放的,我们需要查询spid,在操作系统级来kill这些进程.
    但是由于此时v$session.paddr已经改变,我们无法通过v$session和v$process关联来获得spid
    那还可以怎么办呢?

    SELECT s.username,s.status,
       x.ADDR,x.KSLLAPSC,x.KSLLAPSN,x.KSLLASPO,x.KSLLID1R,x.KSLLRTYP,
       decode(bitand (x.ksuprflg,2),0,null,1)
       FROM x$ksupr x,v$session s
       WHERE s.paddr(+)=x.addr
      and bitand(ksspaflg,1)!=0
      order By x.ADDR,x.KSLLAPSC,x.KSLLAPSN,x.KSLLASPO
    /
    select p.addr from v$process p where pid <> 1
     minus
    select s.paddr from v$session s;

    找到是被Kill掉的进程的进程地址.
    ADDR
    ----------------
    0000000072B68240
    0000000072B68A28
    0000000072B71878
    0000000072B77758

    then,现在我们获得了进程地址,就可以在v$process中找到spid,然后可以使用Kill或者orakill在系统级来杀掉这些进程.
    select *
    from v$process  p
    where p.ADDR
    IN(
     '0000000072B68240',
    '0000000072B68A28',
    '0000000072B71878',
    '0000000072B77758'
    )
    ------------------------
    SPID
    24375
    24377
    12385
    10283
    -----------
    orakill sid spid

    c:\>orakill 219,24375;

  • 相关阅读:
    第一章初识java
    初识jQuery
    初识jQuery的案例
    jdk的安装与环境变量的配置
    第六章连接和分组查询
    第五章模糊查询和聚合函数
    第四章数据查询基础
    第三章用sql语句操作数据
    第二章用表组织数据
    第一章数据库系统基础
  • 原文地址:https://www.cnblogs.com/gracejiang/p/5890477.html
Copyright © 2020-2023  润新知