Oracle 出现锁表问题解决步骤(以前写的一份故障排查报告)

基本操作顺序

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 ‘%%’;

看看对这个表的历史操作,发现了lock table 表名 in exclusive mode。
这时可以确定表是经过系统DML的隐式table lock锁定了表。所以发现在操作记录上没有处理session。

由于第一次的exclusive mode锁定是系统隐式做的,所以是找不到其sid是什么了(由于第一次锁的时候没有及时发现,所以没有找到sid,而在做完了锁定一段时间之后sid就会取消了)。

6 最后处理办法有两个
第一个是到数据库服务器中,将当前的数据库实例给重启一下;

第二个是另开一张新表(与当前被锁的表同构的)进行操作,数据操作都重新指向那个表。

补充信息:
1 一般情况下Oracle的锁表操作都可以通过手工去进行解锁的,就算不进行手工的解锁都可以通过一段时间后自动解锁的。

2 Oracle的锁表无论是什么锁表模式,都是存在时间限制的。当session结束或者操作结束之后(commit 或者 rollback)都是重新释放的。若表长期被锁住的话就要检查一下看看是不是进行的多重锁定或者session等待的情况出现了。


oracle table-lock的5种模式

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语句。


怎么unlock table 解锁

方法一、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 = session_id 
SQL> alter system kill session 'id,serial#';     //杀死该session

方法二、rollback/commit 终止事务处理

你可能感兴趣的:(Oracle)