Oracle Row-X(SX) 锁 引起的问题 说明

Row-X(SX)锁在Oracle的锁中级别是3,是行级排它锁,即在提交前不允许做DML操作 Insert、Update、 Delete、Lock row share。

 

关于Oracle 锁的说明,更多内容参考:

 

ORACLE 锁机制

http://blog.csdn.net/tianlesoftware/article/details/4696896

 

这里要说的的是Row-X(SX)锁引起的问题,不过这里部分内容也只是推测,因为之前的没有留足足够的证据来说明这个观点。

 

            之前发生过修改业务系统的一个核心存储过程,导致其他关联的过程也全部无效的情况,并且还不能直接进行编译,需要在OS级别kill 进程后才能编译的情况。

 

Oracle 存储过程 无法编译 解决方法

http://blog.csdn.net/tianlesoftware/article/details/7412555

 

Oracle shutdown 过程中 DB hang住 解决方法

http://blog.csdn.net/tianlesoftware/article/details/7407587

 

在这两种情况都是kill 掉相关进程才解决问题,因为业务需要,需要在次修改核心存储过程,为避免出现类似问题,提前做了一些准备工作。

 

1.     在修改之前查看对象持有锁的情况

Oracle 查看 对象 持有 锁 的情况

http://blog.csdn.net/tianlesoftware/article/details/6822321


Oracle Row-X(SX) 锁 引起的问题 说明_第1张图片

 

在这里,我们可以看到都是Ros-X(SX)的行级排他锁。

 

2.     查看session持有这些锁的session 的情况

 

这个我在之前的脚本里加了一个session的状态,脚本如下:

 

[sql]  view plain copy
  1. /* Formatted on 2012/6/6 10:59:49 (QP5 v5.185.11230.41888) */  
  2. SELECT distinct S.SID SESSION_ID,  
  3.        S.STATUS,  
  4.        S.USERNAME,  
  5.        DECODE (LMODE,  
  6.                0, ' None ',  
  7.                1, ' Null ',  
  8.                2, ' Row-S(SS) ',  
  9.                3, ' Row-X(SX) ',  
  10.                4, ' Share',  
  11.                5, 'S/Row-X (SSX) ',  
  12.                6, 'Exclusive ',  
  13.                TO_CHAR (LMODE))  
  14.           MODE_HELD,  
  15.        DECODE (REQUEST,  
  16.                0, ' None ',  
  17.                1, ' Null ',  
  18.                2, ' Row-S(SS) ',  
  19.                3, ' Row-X(SX) ',  
  20.                4, ' Share',  
  21.                5, 'S/Row-X (SSX) ',  
  22.                6, 'Exclusive ',  
  23.                TO_CHAR (REQUEST))  
  24.           MODE_REQUESTED,  
  25.        O.OWNER || ' . ' || O.OBJECT_NAME || ' ( ' || O.OBJECT_TYPE || ' ) '  
  26.           AS OBJECT_NAME,  
  27.        S.TYPE LOCK_TYPE,  
  28.        L.ID1 LOCK_ID1,  
  29.        L.ID2 LOCK_ID2,  
  30.        S2.SQL_TEXT  
  31.   FROM V$LOCK L,  
  32.        SYS.DBA_OBJECTS O,  
  33.        V$SESSION S,  
  34.        V$ACCESS A,  
  35.        V$SQL S2  
  36.  WHERE     L.SID = S.SID  
  37.        AND L.ID1 = O.OBJECT_ID  
  38.        AND S.SID = A.SID  
  39.        AND S2.HASH_VALUE = S.SQL_HASH_VALUE  
  40.        AND A.OBJECT = 'PROC_VALIDATE_RULE_V3';  

 

显示这些session 都是处于killed状态。 在之前的Blog中:

Oracle killsessin 说明

http://blog.csdn.net/tianlesoftware/article/details/7417058

 

killed状态的会话,被标注为删除,表示出现了错误,正在回滚。这个过程可能需要等待远程事务的回应或者回滚事务,在这个状态会被标记为killed,并且可能需要等待很长时间,等这些操作完成之后才会kill掉。要释放这些状态为killed的session,可以重启DB,也可以直接在OS 级别kill 进程, windows 下使用ORAKILL 命令,UNIX 直接使用kill 命令。

 

         因为我们编译过程这些行级排他锁如果没有及时释放,我们的编译也会一直处于等待状态,所以我这里是选择在OS级别kill 掉这些session。

 

 

3.     确认killed 状态的session是否使用回滚段

 

使用如下SQL:

[sql]  view plain copy
  1. /* Formatted on 2012/6/7 5:47:42 (QP5 v5.185.11230.41888) */  
  2.   SELECT s.username,  
  3.          s.sid,  
  4.          s.serial#,  
  5.          t.used_ublk,  
  6.          t.used_urec,  
  7.          rs.segment_name,  
  8.          r.rssize,  
  9.          r.status  
  10.     FROM v$transaction t,  
  11.          v$session s,  
  12.          v$rollstat r,  
  13.          dba_rollback_segs rs  
  14.    WHERE     s.saddr = t.ses_addr  
  15.          AND t.xidusn = r.usn  
  16.          AND rs.segment_id = t.xidusn  
  17.          AND s.sid IN  
  18.                 (850, 968, 991, 1039, 968, 991, 1039, 1009, 732, 850, 732)  
  19. ORDER BY t.used_ublk DESC;  

从查询结果看,确实在使用,不过session 是一个月之前的session,并且这些session 都是写log的操作,根据分析,可以直接在操作系统级别kill 掉进程,来释放相关的锁。

 

4.     OS 级别kill 进程

前面已经获取了对象上持有的session ID,这里根据Session ID 查出相关的系统SPID. Sql 语句如下:

[sql]  view plain copy
  1. /* Formatted on 2012/6/7 5:51:01 (QP5 v5.185.11230.41888) */  
  2. SELECT spid, osuser, s.program  
  3.   FROM v$session s, v$process p  
  4.  WHERE     s.paddr = p.addr  
  5.        AND s.sid IN  
  6.               (850, 968, 991, 1039, 968, 991, 1039, 1009, 732, 850, 732);  


 

然后在OS 级别直接kill 掉这些进程就可以了:

 

[oracle@qs-xezf-db1 ~]$ ps -ef|grep 6101

oracle   6101     1  0 May13 ?        00:01:06 oraclexezf (LOCAL=NO)

oracle  16790 16606  0 05:14 pts/2    00:00:00 grep 6101

[oracle@qs-xezf-db1 ~]$ kill -9 6101   

[oracle@qs-xezf-db1 ~]$ ps -ef|grep 6279

oracle   6279     1  0 May13 ?        00:00:57 oraclexezf (LOCAL=NO)

oracle  16824 16606  0 05:14 pts/2    00:00:00 grep 6279

[oracle@qs-xezf-db1 ~]$ kill -9 6279

 

 

5.     检查

在OS级别kill 掉这些状态为killed 的session 之后,对象的Row-X(SX)全部释放,过程对象上的操作也顺利进行,没有出现等待。

这里注意的是,修改之后会导致一些对象的无效,需要查看并重新编译这些无效对象。

 

 

 

 

 

 

-------------------------------------------------------------------------------------------------------

版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!

Skype:            tianlesoftware

QQ:                 [email protected]

Email:             [email protected]

Blog:   http://www.tianlesoftware.com

Weibo:            http://weibo.com/tianlesoftware

Twitter: http://twitter.com/tianlesoftware

Facebook: http://www.facebook.com/tianlesoftware

Linkedin: http://cn.linkedin.com/in/tianlesoftware

你可能感兴趣的:(oracle,sql,session,kill,OS,存储)