有关Oracle 锁的说明,参考:
http://blog.csdn.net/tianlesoftware/article/details/4696896
用如下SQL 查看一下系统中相关对象上锁的情况:
- <pre name="code" class="sql">/* Formattedon 2012/2/13 14:24:32 (QP5 v5.185.11230.41888) */
- SELECT S.SID SESSION_ID,
- S.USERNAME,
- DECODE (LMODE,
- 0, ' None ',
- 1, ' Null ',
- 2, ' Row-S(SS) ',
- 3, ' Row-X(SX) ',
- 4, ' Share',
- 5, 'S/Row-X (SSX) ',
- 6, 'Exclusive ',
- TO_CHAR (LMODE))
- MODE_HELD,
- DECODE (REQUEST,
- 0, ' None ',
- 1, ' Null ',
- 2, ' Row-S(SS) ',
- 3, ' Row-X(SX) ',
- 4, ' Share',
- 5, 'S/Row-X (SSX) ',
- 6, 'Exclusive ',
- TO_CHAR (REQUEST))
- MODE_REQUESTED,
- O.OWNER || ' . ' || O.OBJECT_NAME ||' ( ' || O.OBJECT_TYPE || ' ) '
- AS OBJECT_NAME,
- S.TYPE LOCK_TYPE,
- L.ID1 LOCK_ID1,
- L.ID2 LOCK_ID2
- FROM V$LOCK L, SYS.DBA_OBJECTS O, V$SESSION S
- WHERE L.SID = S.SID AND L.ID1 = O.OBJECT_IDAND object_name = 'xxxx';
该SQL 显示所有对象上的锁,如果要查某个具体的对象,可以根据OBJECT_NAME 字段进行一下过滤,找到对应的SID 之后去查V$SESSION 视图。
该视图会显示session 对应的信息,包括终端的信息,如果找到了终端,可以让它提交或者回滚一下就OK了。 我这里是测试环境,直接把session kill 掉了。然后修改表就ok了。
- SQL>alter system kill session'SID,SERIAL#'
后来测试了发现,上面的脚本有时候会查不到对象的的相关记录,故增加了V$ACCESS视图,通过对这个视图进行对象的判断,修改之后的脚本如下:
- SELECT S.SID SESSION_ID,
- S.USERNAME,
- DECODE (LMODE,
- 0, ' None ',
- 1, ' Null ',
- 2, ' Row-S(SS) ',
- 3, ' Row-X(SX) ',
- 4, ' Share',
- 5, 'S/Row-X (SSX) ',
- 6, 'Exclusive ',
- TO_CHAR (LMODE))
- MODE_HELD,
- DECODE (REQUEST,
- 0, ' None ',
- 1, ' Null ',
- 2, ' Row-S(SS) ',
- 3, ' Row-X(SX) ',
- 4, ' Share',
- 5, 'S/Row-X (SSX) ',
- 6, 'Exclusive ',
- TO_CHAR (REQUEST))
- MODE_REQUESTED,
- O.OWNER || ' . ' || O.OBJECT_NAME ||' ( ' || O.OBJECT_TYPE || ' ) '
- AS OBJECT_NAME,
- S.TYPE LOCK_TYPE,
- L.ID1 LOCK_ID1,
- L.ID2 LOCK_ID2
- FROM V$LOCK L, SYS.DBA_OBJECTS O, V$SESSION S,V$ACCESS A
- WHERE L.SID = S.SID AND L.ID1 = O.OBJECT_ID AND S.SID=A.SIDAND A.OBJECT= 'PROC_VALIDATE_RULE_V3';
再次修改了一下,添加了V$SQL视图,这样可以一起查出具体导致这种锁的SQL语句,一次性就搞定了,SQL如下:
- /* Formatted on 2012/6/6 10:59:49 (QP5 v5.185.11230.41888) */
- SELECT distinct S.SID SESSION_ID,
- S.STATUS,
- S.USERNAME,
- DECODE (LMODE,
- 0, ' None ',
- 1, ' Null ',
- 2, ' Row-S(SS) ',
- 3, ' Row-X(SX) ',
- 4, ' Share',
- 5, 'S/Row-X (SSX) ',
- 6, 'Exclusive ',
- TO_CHAR (LMODE))
- MODE_HELD,
- DECODE (REQUEST,
- 0, ' None ',
- 1, ' Null ',
- 2, ' Row-S(SS) ',
- 3, ' Row-X(SX) ',
- 4, ' Share',
- 5, 'S/Row-X (SSX) ',
- 6, 'Exclusive ',
- TO_CHAR (REQUEST))
- MODE_REQUESTED,
- O.OWNER || ' . ' || O.OBJECT_NAME ||' ( ' || O.OBJECT_TYPE || ' ) '
- AS OBJECT_NAME,
- S.TYPE LOCK_TYPE,
- L.ID1 LOCK_ID1,
- L.ID2 LOCK_ID2,
- S2.SQL_TEXT
- FROM V$LOCK L,
- SYS.DBA_OBJECTS O,
- V$SESSION S,
- V$ACCESS A,
- V$SQL S2
- WHERE L.SID = S.SID
- AND L.ID1 = O.OBJECT_ID
- AND S.SID = A.SID
- AND S2.HASH_VALUE = S.SQL_HASH_VALUE
- AND A.OBJECT = 'PROC_VALIDATE_RULE_V3';
效果如下:
转自:http://blog.csdn.net/tianlesoftware/article/details/6822321 在此谢谢DAVE
ORACLE里锁有以下几种模式:
0:none
1:null 空
2:Row-S 行共享(RS):共享表锁
3:Row-X 行专用(RX):用于行的修改
4:Share 共享锁(S):阻止其他DML操作
5:S/Row-X 共享行专用(SRX):阻止其他事务操作
6:exclusive 专用(X):独立访问使用
数字越大锁级别越高, 影响的操作越多。
一般的查询语句如select ... from ... ;是小于2的锁, 有时会在v$locked_object出现。
select ... from ... for update; 是2的锁。
当对话使用for update子串打开一个游标时,
所有返回集中的数据行都将处于行级(Row-X)独占式锁定,
其他对象只能查询这些数据行,不能进行update、delete或select...for update操作。
insert / update / delete ... ; 是3的锁。
没有commit之前插入同样的一条记录会没有反应,
因为后一个3的锁会一直等待上一个3的锁, 我们必须释放掉上一个才能继续工作。
创建索引的时候也会产生3,4级别的锁。
locked_mode为2,3,4不影响DML(insert,delete,update,select)操作,
但DDL(alter,drop等)操作会提示ora-00054错误。
有主外键约束时 update / delete ... ; 可能会产生4,5的锁。
DDL语句时是6的锁。
以DBA角色, 查看当前数据库里锁的情况可以用如下SQL语句:
select object_id,session_id,locked_mode from v$locked_object;
select t2.username,t2.sid,t2.serial#,t2.logon_time
from v$locked_object t1,v$session t2
where t1.session_id=t2.sid order by t2.logon_time;
如果有长期出现的一列,可能是没有释放的锁。