Oracle数据库锁诊断

咱们都知道Oracle是一个大并发的数据库,有了锁数据库才可能实现大并发,也是应为锁Oracle大并发受到影响。sql

首先介绍下如何判断数据库是否有锁,来看一个视图:数据库

v$lock session

type:TM 表锁 或者DML锁并发

     TX 行锁 事务锁 测试

lmode:会话保持的锁模式 ui

      0 = nonecode

      1 = null对象

      2 = Row-S(SS 行级共享锁 ,只能查询这些对象)blog

      3 = Row-X(行级排他锁,在提交前不容许修改)事务

      4 = Share(共享锁) 

      5 = S/ROW-X(共享行级排他锁)

      6 = Exclusive(排他锁)

ID1,ID2 根据Type取值不一样而不一样。

对于type=TM表级锁或者DML锁, ID1表示被锁定表的object_id,ID2 为0 ;

        对于type=TX事务锁,ID1表示高事务所占用的回滚段及事务槽,ID2表示为 环绕warp次数,即事务槽被重用的次数

        

REQUEST:表示会话请求锁类型        

block:表示堵塞了别的会话对该锁对象的请求次数,重点关注大于 1 ,等待锁类型由lmode决定,

SQL> select sid,type, id1,id2,LMODE,REQUEST,BLOCK from v$lock where type in ('TM','TX') order by type,sid;

       SID TY        ID1        ID2      LMODE    REQUEST      BLOCK

---------- -- ---------- ---------- ---------- ---------- ----------

      133  TX    1996         1701        0          6         0       

      135  TX    1996         1701        6          0         1

 

        

133 会话持有TX锁,锁类型类0,要请求6号锁,堵塞别人0 次,

135 会话持有TX锁,所类型为6(排他锁),堵塞过别人一次;从ID1,ID2可知  这两个会话请求的对象都同样,可见 135堵塞了133。

能够看到一点,lmode = 0 表示会话没有持有锁,可是 颇有可能被别的会话给堵塞了,具体要REQUEST 字段和ID1,ID2字段

死锁查询:

select a.sid,b.sid,a.type,a.id1,a.id2,a.ctime from v$lock a,v$lock b where a.id1=b.id1 and a.id2=b.id2 and a.block > 1 and b.block =0;

 

查询死锁对象:

select ls.sid,ls.serial#,o.object_name from  (select s.osuers,s.username,l.type,s.paddr,l.lmode,s.sid,s.serial# ,l.id1,l.id2 from v$session s,v$lock l where s.sid=l.sid) ls ,v$object o 

 where o.object_id=ls.id1;

 

 

测试:

对一张表在不一样的会话进行update更行

SQL> select sid,type,id1,id2,lmode,request,block from  v$lock where type in ('TX

','TM');



       SID TYPE        ID1        ID2      LMODE    REQUEST      BLOCK

---------- ---- ---------- ---------- ---------- ---------- ----------

         5 TX       131079        777          0          6          0

        68 TM        74569          0          3          0          0

         5 TM        74569          0          3          0          0

        68 TX       131079        777          6          0          1



SQL>

咱们能够看到 sid 为5的会话持有3号锁(R/X 行级排它锁),请求6号锁(排它锁),请求对象是74569   ,发生事务是 ‘ 131079 ,777 ’ 。

sid=68,持有6号锁和3号锁,加锁的对象是 74569,堵塞了别人锁请求一次。

因此问题和明显了,sid=68的会话在对象74569 上加了一个6号锁,而sid=5的会话须要请求对象74569 的一个6号锁,咱们知道6号锁是一个排它锁,会话互斥,因此堵塞了1次别人锁请求。

SQL> select object_name,owner ,object_id from dba_objects where object_id=74569;



OBJECT_NAME          OWNER                 OBJECT_ID

-------------------- -------------------- ----------

TEST1                SYS                       74569

能够看到发生锁的对象是 sys.Test1表。

SQL> select sid,serial#,sql_id from v$session where sid in (select sid from v$lo

ck where type in ('TX','TM'));



       SID    SERIAL# SQL_ID

---------- ---------- --------------------------

         5         68 0d4ag0mv6hqcp

        68         82
SQL> select sql_text,sql_id from v$sql where sql_id='0d4ag0mv6hqcp';



SQL_TEXT

--------------------------------------------------------------------------------



SQL_ID

--------------------------

 update test1 set object_name='test1' where object_id=20

0d4ag0mv6hqcp

 

以上能够看到,堵塞的sql_text 。

这样就好解决了,找到这个sql的开发或者业务,告诉他这个sql堵塞了别的会话,排查是否是没有提交或者数据量比较大未执行完,要么回滚掉,要么强制杀死会话。

alter system kill session 'SID,SERIAL#' 或者  rollback;

注意:

查询v$lock视图 看到有锁不要担忧,有锁未必是坏事,必定要看这个锁是否堵塞别人,就是看那个block >0的会话ji对象。

 

 v$locked_object 

 This view lists all locks acquired by every transaction on the system. It shows which sessions are holding DML locks (that is, TM-type enqueues) on what objects and in what mode.

 只包含DML的锁信息,包括回滚段和会话的信息。

 

持有锁对象查询(不必定是死锁): 

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 logon_time

相关文章
相关标签/搜索