1 查出锁定object的session的信息以及被锁定的object名
SELECT l.session_id sid,
s.serial#,
l.locked_mode,
l.oracle_username,
l.os_user_name,
s.machine,
s.terminal,
o.object_name,
s.logon_time
FROM v$locked_object l, all_objects o, v$session s
WHERE l.object_id = o.object_id
AND l.session_id = s.sid
ORDER BY sid, s.serial# ;
2 查出锁定表的session的sid, serial#,os_user_name, machine name, terminal和执行的语句
SELECT l.session_id sid,
s.serial#,
l.locked_mode,
l.oracle_username,
s.user#,
l.os_user_name,
s.machine,
s.terminal,
a.sql_text,
a.action
FROM v$sqlarea a,v$session s, v$locked_object l
WHERE l.session_id = s.sid
AND s.prev_sql_addr = a.address
ORDER BY sid, s.serial#;
3 查出锁定表的sid, serial#,os_user_name, machine_name, terminal,锁的type,mode
SELECT s.sid,
s.serial#,
s.username,
s.schemaname,
s.osuser,
s.process,
s.machine,
s.terminal,
s.logon_time,
l.type
FROM v$session s, v$lock l
WHERE s.sid = l.sid
AND s.username IS NOT NULL
ORDER BY sid;
4 剩下的通过命令kill掉就可以了
alter system kill session 'sid,serial#'
这次遇到的税费问题,我是这样排查的:
1 检查oracle的job是否存在资源没有释放的情况
Select * from dba_job;
Select * from dba_job_running;
确定没有job执行之后,将job中对应的定时计划先删除。
2 检查所有远程计算机,看看有没有客户端存在session占用的情况
具体的做法就是访问各个远程计算机,看看有没有正在对表的数据进行操作的,就算没有都要将客户端关闭。
3 通过语句先看看有没有锁表的情况
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;
结果看到没有显示锁表的情况。
4 尝试对某一字段进行修改
结果显示修改失败,表被占用。之后进行数据的插入,发现是可以经行表的增删查改操作的,说明表只是表的结构被锁定了,但这个只是猜测,不能真正确定问题所在。
5 查询表的操作记录
select * from v$sqlarea a where a.sql_text like ‘%<table_name>%’;
看看对这个表的历史操作,发现了lock table 表名 in exclusive mode。
这时可以确定表是经过系统DML的隐式table lock锁定了表。所以发现在操作记录上没有处理session。
由于第一次的exclusive mode锁定是系统隐式做的,所以是找不到其sid是什么了(由于第一次锁的时候没有及时发现,所以没有找到sid,而在做完了锁定一段时间之后sid就会取消了)。
6 最后处理办法有两个
第一个是到数据库服务器中,将当前的数据库实例给重启一下;
第二个是另开一张新表(与当前被锁的表同构的)进行操作,数据操作都重新指向那个表。
补充信息:
1 一般情况下Oracle的锁表操作都可以通过手工去进行解锁的,就算不进行手工的解锁都可以通过一段时间后自动解锁的。
2 Oracle的锁表无论是什么锁表模式,都是存在时间限制的。当session结束或者操作结束之后(commit 或者 rollback)都是重新释放的。若表长期被锁住的话就要检查一下看看是不是进行的多重锁定或者session等待的情况出现了。
Oracle中的锁定可以分为几类:
1、DML lock(data lock),
2、DDL lock(dictionary lock)
3、internal lock/latch。
DML lock又可以分为row lock和table lock。
row lock在select.. for update/insert/update/delete时隐式自动产生,而table lock除了隐式产生,也可以调用lock table in name来显示锁定。
如果不希望别的session lock/insert/update/delete表中任意一行,只允许查询,可以用
lock table table_name in exclusive mode。(X)
这个锁定模式级别最高,并发度最小。
如果允许别的session查询或用select for update锁定记录,不允许insert/update/delete,可以用
lock table table_name in share row exclusive mode。(SRX)
如果允许别的session查询或select for update以及lock table table_name in share mode,只是不允许insert/update/delete,可以用
lock table table_name in share mode。
(share mode和share row exclusive mode的区别在于一个是非抢占式的而另一个是抢占式的。进入share row exclusive mode后其他session不能阻止你insert/update/delete,而进入share mode后其他session也同样可以进入share mode,进而阻止你对表的修改。(S)
还有两种锁定模式,row share(RS)和row exclusive(RX)。他们允许的并发操作更多,一般直接用DML语句自动获得,而不用lock语句。
方法一、kill session:
SQL> select object_id,session_id from v$locked_object; //注意session_id 就是上锁的 session标志
SQL> select username,sid,SERIAL# from v$session where sid='<sid>'; //这里的SID = session_id
SQL> alter system kill session 'id,serial#'; //杀死该session
方法二、rollback/commit 终止事务处理