Welcome 微信登录

首页 / 数据库 / MySQL / 如何定位Oracle数据库被锁阻塞会话的根源

首先再次明确下,数据库因为要同时保证数据的并发性和一致性,所以操作有锁等待是正常的。只有那些长时间没有提交或回滚的事物,阻塞了其他业务正常操作,才是需要去定位处理的。1.单实例环境
2.RAC环境

1. 单实例环境

实验环境:Oracle 10.2.0.5 单实例会话1模拟业务操作:SQL> select sid from v$mystat where rownum=1;SID---------- 144SQL> show userUSER is "JINGYU"SQL> select * from t1 where id=1 for update;IDN CONTENTS---------- ---------- ---------------------------------------- 11 Alfred Zhao会话2模拟业务操作:SQL> select sid from v$mystat where rownum=1;SID---------- 149SQL> show userUSER is "JINGYU"SQL> update t1 set contents="Mcdull" where id=1;这里update操作会卡住不动。用户感知就是长时间无法执行成功,很可能还会直接抱怨数据库性能慢。会话3模拟DBA查看:SQL> select sid from v$mystat where rownum=1;SID---------- 145SQL> show user USER is "SYS"SQL> select sid, username, blocking_session from v$session where blocking_session is not null; SID USERNAME BLOCKING_SESSION---------- ------------------------------ ---------------- 149 JINGYU144SQL> select sid, serial#, username from v$session where sid=144; SIDSERIAL# USERNAME---------- ---------- ------------------------------ 144102 JINGYU这里可以清楚的看到会话149是被会话144阻塞,进一步查看会话144的serial#值。这时候的处理方式一般有2种方案:
1)杀掉会话144,当然操作之前需要和应用负责人确认沟通好;
2)如果可以定位到144会话相关责任人,由他来提交或者回滚事物;
处理后可以看到会话2的update操作正常执行成功。

2.RAC环境

实验环境:Oracle 10.2.0.5 RAC
如果是RAC环境,还必须要定位到具体是哪个实例的会话,其实方法非常简单,查询时加入blocking_instance字段即可。
实例2模拟业务操作:select sid from v$mystat where rownum=1; select * from t1 where id=1 for update;实例1模拟业务操作:select sid from v$mystat where rownum=1; update t1 set contents="Mcdull" where id=1;会话模拟DBA查看:SQL> select sid, username, blocking_instance, blocking_session from gv$session where blocking_session is not null; SID USERNAME BLOCKING_INSTANCE BLOCKING_SESSION---------- ------------------------------ ----------------- ---------------- 129 JINGYU 2129SQL> select inst_id, sid, serial#, username from gv$session where sid=129; INST_IDSIDSERIAL# USERNAME---------- ---------- ---------- ------------------------------ 1129617 JINGYU 2129207 JINGYU查询阻塞会话也要注意当前连接的实例,千万别弄错了,比如上面这个情况,如果确定可以杀掉阻塞会话,那么就需要到实例2去杀掉会话;SQL> select instance_number from v$instance;INSTANCE_NUMBER---------------2SQL> alter system kill session "129,207";System altered.再次看被阻塞的会话操作已经恢复正常。后记:
整理该文主要缘由是在之前的一次面试过程中,发现自己对这样基本的问题反而太依赖于别人写好的SQL,比如下面这类的SQL,开始并不知道此SQL的具体适用场景:select a.sid blocker_sid, a.serial#, a.username as blocker_username, b.type,decode(b.lmode,0,"None",1,"Null",2,"Row share",3,"Row Exclusive",4,"Share",5,"Share Row Exclusive",6,"Exclusive") lock_mode,b.ctime as time_held,c.sid as waiter_sid,decode(c.request,0,"None",1,"Null",2,"Row share",3,"Row Exclusive",4,"Share",5,"Share Row Exclusive",6,"Exclusive") request_mode,c.ctime time_waitedfrom v$lock b, v$enqueue_lock c, v$session awherea.sid = b.sid andb.id1= c.id1(+) and b.id2 = c.id2(+) and c.type(+) = "TX" andb.type = "TX" andb.block = 1order by time_held, time_waited;所以对于专业的DBA来说,这样做是很不可取的。从现在起,自己要更多的研究这些基础知识,脚踏实地,练好内功,对于别人写的SQL,一定要彻底搞清楚含义之后再用。更多Oracle相关信息见Oracle 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=12本文永久更新链接地址