【熟能生巧】查看Oracle DB Lock及快速处理

问题

在开发时,遇到一个问题,我运行了一个简单的 update 语句如下:

update table_a set column_b = 'something' where condition_c = 'blablabla';

但是,执行了很久都没有完成。等了大概有 5 分钟,还在 run 。这个表不是很大,写入也不多,平时都是秒杀的。

分析长时间运行的语句

首先,看一下现在有没有 long running sql 。

-- check long running sql
select ses.osuser, nvl(ses.username,'ORACLE PROC')||' ('||ses.sid||')'
       username, sid, machine, replace(sql.sql_text,chr(10),'') stmt,
       ltrim(to_char(floor(ses.last_call_et/3600), '09')) || ':' ||
       ltrim(to_char(floor(mod(ses.last_call_et, 3600)/60), '09')) || ':' ||
       ltrim(to_char(mod(ses.last_call_et, 60), '09')) runt
  from v$session ses, v$sqltext_with_newlines sql
 where ses.status = 'ACTIVE'
   and ses.username is not null
   and ses.sql_address = sql.address
   and ses.sql_hash_value = sql.hash_value
   and ses.audsid <> userenv('SESSIONID')
 order by runt desc, 1,sql.piece;

结果 ->

OSUSER   USERNAME        SID    MACHINE        STMT                    RUNT
oracle   SCEMA_A (1111)	 1111	machine.a.ip   update table_a ...;     10:00:00
oracle   SCEMA_A (2222)	 2222	machine.b.ip   update table_a ...;     12:00:00

果然有,而且,也是 update 这个 table_a ,且已经跑了10几个小时了。

由此判断,应该是这个表被锁住了,所以 block 了其它想要 update 的语句。

查看锁

使用如下语句查看锁:

-- check lock
select
   (select username from v$session where sid=a.sid) blocker,
   a.sid,
   ' is blocking ',
   (select username from v$session where sid=b.sid) blockee,
   b.sid
from
   v$lock a,
   v$lock b
where
   a.block = 1
and
   b.request > 0
and
   a.id1 = b.id1
AND
   A.ID2 = B.ID2;

结果 ->

BLOCKER   SID    ISBLOCKING     BLOCKEE   SID_1
SCEMA_A	  3333   is blocking 	SCEMA_A	  1111
SCEMA_A	  3333	 is blocking 	SCEMA_A	  2222

果然,发现 SID 为 3333 的这个进程, block 住了 1111 和 2222 。

进一步,我们来看看这个进程是谁跑的。

SELECT SES.USERNAME, SES.OSUSER, SES.PROGRAM, SQL.SQL_TEXT 
FROM V$SESSION SES, V$SQLTEXT_WITH_NEWLINES SQL
WHERE SES.SID = 428
AND SES.SQL_ADDRESS = SQL.ADDRESS
AND SES.SQL_HASH_VALUE = SQL.HASH_VALUE;

结果 ->

USERNAME  OSUSER       PROGRM          SQL_TEXT
SCEMA_A   user_aaa     SQL Developer   something
SCEMA_A   user_aaa     SQL Developer   something
SCEMA_A   user_aaa     SQL Developer   something

可以看出,这个 3333 是 user_aaa 跑的。但是目前他并没有 run 相关的 update table_a 的 query 。

解决

和 user_aaa 讨论过后,知道,原来他之前跑了一句 update table_a ,但是没有 commit ,于是他的 session 一直拿着这个锁。

让他 commit 一下就好了,锁马上被释放,其它的语句也可以顺利执行完成。

如果 user_aaa 不在,联系不上咋办呢,把他的 session kill 掉,这个锁也会被释放。

ALTER SYSTEM KILL SESSION '<3333, 36575>';

参考

原文地址:https://www.cnblogs.com/maxstack/p/14005210.html