工作了一段时间,有一天测试的同事问我,我的一个后台shell脚本每次手动启动之后就像挂死在那里,也不打印日志了,当时觉得奇怪,为什么会出现这个问题呢,之前从未遇到过,打开代码,发现在挂死的那里后面有个和数据库交互去改变某一个表的字段值的操作,猜想下,估计是锁表了,和测试的同事沟通之后,果然有一个同事当时就在操作那个表中的那个字段,没有提交,刚好是我要修改的,他们的语句是select * from test for update;然后我去修改那个值得时候,当然就处于等待状态了,但到目前为止,只是猜想,要测试下知道,发了一条查询锁表的语句给测试耳朵同事,他们执行之后果然有输出,那么就证明了我的猜想,如何解锁呢?我又不得不再发一条语句给他们,问题解决了,现在把sql贴出来,以备后期查看。
第一种:
select sess.sid,
sess.serial#,
lo.oracle_username,
lo.os_user_name,
ao.object_name,
lo.locked_mode
from v$locked_object lo,
dba_objects ao,
v$session sess
where ao.object_id = lo.object_id and lo.session_id = sess.sid;
第二种:
select * from v$session t1, v$locked_object t2 where t1.sid = t2.SESSION_ID;
两种方式都可以查出当前用户下那些表被锁住了。
杀掉锁表进程:
如有记录則表示有表被锁住了,记录下SID和serial# ,將两个字段的取值替换下面的例子中的两个数字(注意中间是以逗号分隔的),即可解除LOCK
如下图:
alter system kill session '138,19';
下面简单说下Oracle下集中锁的模式(借鉴的):
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的锁。