上午开发人员反映说,一个存储过程编译时马上就没有响应了,自己尝试打开存储过程编译
也是一样的提示,就想到是这个过程发生死锁了。
查看dba_ddl_locks 字典,可以看到该过程的锁定信息。
SQL> select * from dba_ddl_locks WHERE OWNER='GUANGZHOU';
 
SESSION_ID OWNER             NAME                          TYPE                      
---------- ----------------------- -------------------------------- --------------
       109 GUANGZHOU    P_UNCREATECONSUMEBILL        Table/Procedure/Type  
       103 GUANGZHOU    GUANGZHOU                                     18                         
       137 GUANGZHOU    GUANGZHOU                                     18                         
       109 GUANGZHOU    GUANGZHOU                                     18                          
       137 GUANGZHOU    P_CREATECONSUMEBILL             Table/Procedure/Type         
       109 GUANGZHOU    P_CREATECONSUMEBILL             Table/Procedure/Type         
 
6 rows selected
考虑到这个过程每日有运行着自动任务。 查看job字典可以看到相关运行的任务。
发现87任务并不在当前时间段运行,排除这个的可能性。
SQL> select * from dba_jobs_running;
 
  SID      JOB   FAILURES      LAST_DATE          LAST_SEC  THIS_DATE  IS_SEC 
 ---------- ---------- ---------- ----------- ---------------- ----------- --
 137      87      0     2010-06-25  16:59:44   2010-06-25  17:59:45      0
 
SQL> select * from dba_jobs;
 
  JOB LOG_USER      PRIV_USER      SCHEMA_USER        LAST_DATE   LAST_SEC
---------- ------------------------------ ------------------------------ -----
27   SYS         WKSYS             WKSYS             2010-06-27  01:00:01
26   SYS         WKSYS             WKSYS             2010-06-30  10:00:01
66   SYS         SYS                    SYS                   2010-06-29  22:00:00
4001 SYS         FLOWS_030000      FLOWS_030000      2010-06-30  02:19:00
4002 SYS         FLOWS_030000      FLOWS_030000      2010-06-30  09:59:16
46 SYSMAN        SYSMAN            SYSMAN                2010-06-30  10:06:56
86 GUANGZHOU     GUANGZHOU         GUANGZHOU         2010-06-30  10:01:16
87 GUANGZHOU     GUANGZHOU         GUANGZHOU         2010-06-25  16:59:44
 
8 rows selected
查看等待事件:,可以看到sid=137 的用户有等待事件。
SQL> select * from v$session_wait where WAIT_CLASS#<>6;
 
       SID       SEQ# EVENT                         P1TEXT           
---------- ---------- ------------------------------------- --
       137      10871 SQL*Net message from dblink  driver id        
 
查看这个sid的用户信息。
SQL> select sid,username,serial# from v$session where SID='137';
 
       SID USERNAME                          SERIAL#
---------- ------------------------------ ----------
       137 GUANGZHOU                             527
1 rows selected
 
尝试杀掉该用户的进程,运行下面的命令后很长时间没有相应,只能结束任务。
SQL> alter system kill session '109,213';
 
alter system kill session '109,213'
 
ORA-01013: 用户请求取消当前的操作
再次查看这个sid的用户信息。可以看到进程已经被杀掉了,但资源没有释放出来。
SQL> select sid,username,serial# from v$session where SID='137';
 
       SID USERNAME                          SERIAL#          STATUS
---------- ------------------------------ ---------------------------
       137 GUANGZHOU                             527          KILLED
在这种情况下,很多时候,资源是无法释放的,我们需要查询spid,
在操作系统级来kill这些进程. 但是由于此时v$session.paddr已经改变,
无法通过v$session和v$process关联来获得spid。
这时可以使用下面的查询得到addr地址:  
SQL> SELECT s.username,s.status,S.SID,S.SERIAL#,
  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 and s.USERNAME='GUANGZHOU'
  6     and bitand(ksspaflg,1)!=0;
 
USERNAME         STATUS      SID    SERIAL# ADDR      KSLLAPSC   KSLLAPSN
------------------------------ -------- ---------- ---------- -------------
GUANGZHOU    INACTIVE        103      28929 482CD448      1       25 5192                  
GUANGZHOU    ACTIVE          137        527 482D40B8    241       25 5192                  
GUANGZHOU    INACTIVE        101       3559 482D76F0      1       25 5192                  
GUANGZHOU    KILLED          109        213 482DA250      1       25 5192                  
 
现在我们获得了进程地址,就可以在v$process中找到spid,
然后可以使用Kill或者orakill在系统级来杀掉这些进程.
SQL> SELECT * FROM V$PROCESS WHERE ADDR='482DA250';
 
ADDR          PID SPID    USERNAME   SERIAL# TERMINAL   PROGRAM       
-------- -------- --------------- ---------- ----------- ---------------
482DA250       50 1880    SYSTEM        6    MID-TEST  ORACLE.EXE (SHAD)
在服务器上杀掉操作系统级进程就可以了。
C:\Documents and Settings\Administrator>ORAKILL GZTEST 1880
Kill of thread id 1880 in instance GZTEST successfully signalled.
再次查看时,该进程的信息就被杀掉了。
SQL> SELECT * FROM V$PROCESS WHERE ADDR='482DA250';
 
ADDR        PID SPID      USERNAME      SERIAL# TERMINAL        PROGRAM  
-------- ---------- ------------------------ --------------- ----------
参考文章:
  http://www.ddway.com/ShowDetail_31558.aspx
  http://hi.baidu.com/firefly5002/blog/item/c64ed21fd586cbff1ad57652.html