锁分析

在数据库运维工作中,有相当大一部分工作跟锁有关。

锁用对了地方能保证数据一致性,用错了地方就能导致并发性下降。

下面来讲解数据库发生锁,该如何进行诊断:

首先将几个锁相关的视图:

v$lock

v$lock_object

v$session

dba_objects

v$processes

v$sql

1、v$lock

type:TM 表锁 或者DML锁

     TX 行锁 事务锁 

lmode:会话保持的锁模式 

      0 = none

      1 = null

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

      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 addr,kaddr,sid,type,id1,id2,lmode,request,block from v$lock where type in ('TX','TM');
ADDR             KADDR                   SID TYPE        ID1        ID2      LMODE    REQUEST      BLOCK
---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ----------
000007FF5EC570F0 000007FF5EC57148          8 TX       589848       1189          0          6          0
000000001FCCDA30 000000001FCCDA90          8 TM        74686          0          3          0          0
000000001FCCDA30 000000001FCCDA90         73 TM        74686          0          3          0          0
000007FF5ACD8880 000007FF5ACD88F8         73 TX       589848       1189          6          0          1

        

        

73 会话持有TX锁,锁类型类6(排他锁),堵塞别人1次;

8 会话持有TX锁,锁类型为0,请求6号锁,;

从ID1,ID2可知  这两个事务请求的对象都一样,可见 73堵塞了8。

到底锁发生的对象是哪个?可以查看

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

死锁查询:

select a.sid,holdsid,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.bllck =0;

查询TM表锁对象:

select object_name from dba_objects o ,v$lock l where l.ID1=o.object_id and l.TYPE='TM';

查询TX锁对象:

select ss.EVENT,ss.SID,ss.SERIAL#,ss.PADDR,ss.ROW_WAIT_OBJ#,obj.object_name from v$session ss ,

dba_objects obj,v$lock l where ss.ROW_WAIT_OBJ#=obj.object_id and ss.SID=l.SID and l.KADDR=ss.LOCKWAIT;

SQL> select ss.EVENT,ss.SID,ss.SERIAL#,ss.PADDR,ss.ROW_WAIT_OBJ#,obj.object_name from v$session ss ,
  2  dba_objects obj,v$lock l where ss.ROW_WAIT_OBJ#=obj.object_id and ss.SID=l.SID and l.KADDR=ss.LOCKWAIT
  3  ;
EVENT                             SID     SERIAL#  PADDR            ROW_WAIT_OBJ# OBJECT_NAME
-------------------------------- ------- ---------- ---------------- ------------- ---------------
enq: TX - row lock contention        8       36     000007FF5E4D9DE0         74686 TEST1

或者

SQL> select /*+ NO_MERGE(a) NO_MERGE(b) NO_MERGE(c) */ a.username, a.machine, a.sid, a.serial#, a.last_call_et "Seconds", b.id1, c.sql_text "SQL"
  2  from v$session a, v$lock b, v$sqltext c
  3  where a.username is not null and a.lockwait = b.kaddr and c.hash_value =a.sql_hash_value
  4  ;
USERNAME  MACHINE                       SID    SERIAL#    Seconds        ID1 SQL
-------- ----------------------------- ------- ---------- ---------- ---------- ----------------------------------------------------------------
SYS        WORKGROUP\PC201812010809       8       36      10863     589848 update test1 set object_id=object_id+1 where object_id=1900

不知道大家有没有感觉得在数据库通过‘ alter system kill session 'sid,serial#' immediate;'’杀会话,有时候杀不掉,这个时候我们可以通过OS系统 pid 来杀 pkill -9 SID

SQL>  select a.spid,a.PID,a.username,b.program,b.SID,b.SERIAL#  from v$process a,v$session b,v$lock c  where a.addr=b.paddr and c.SID=b.SID and c.TYPE in ('TX','TM');
SPID    PID USERNAME   PROGRAM         SID    SERIAL#
------- ---------- --------------- -------------------------- 
8964    20 SYSTEM     sqlplus.exe      8         36
8964    20 SYSTEM     sqlplus.exe      8         36
10368   49 SYSTEM     sqlplus.exe      73       2616
10368   49 SYSTEM     sqlplus.exe      73       2616

下面来探讨一下,谁堵塞了谁?

这个需要查看v$lock 视图,block表示堵塞别人次数,只要block>1就比是堵塞了别人,有死锁。

REQUEST 表示这个SID请求锁类型,LMODE表示SID持有锁类型,对于排他锁而言,一旦持有排它锁,那么就堵塞了别人的会话,。

 2、 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的锁信息,包括回滚段和会话的信息。所以v$lock_object查询库锁使用情况,有锁不一定代表是死锁,这个一定要记住。

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

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

总结:

其它相关视图说明

视图名 描述 主要字段说明

v$session 查询会话的信息和锁的信息。 

sid,serial#:表示会话信息。

program:表示会话的应用程序信息。

row_wait_obj#:表示等待的对象,和dba_objects中的object_id相对应。

lockwait :该会话等待的锁的地址,与v$lock的kaddr对应.

v$session_wait 查询等待的会话信息。 sid:表示持有锁的会话信息。

Seconds_in_wait:表示等待持续的时间信息

Event:表示会话等待的事件,锁等于enqueue

dba_locks 对v$lock的格式化视图。

Session_id:和v$lock中的Sid对应。

Lock_type:和v$lock中的type对应。

Lock_ID1: 和v$lock中的ID1对应。

Mode_held,mode_requested:和v$lock中的lmode,request相对应。

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

Xidusn,xidslot,xidsqn:表示回滚段信息。和v$transaction相关联。

Object_id:表示被锁对象标识。

Session_id:表示持有锁的会话信息。

Locked_mode:表示会话等待的锁模式的信息,和v$lock中的lmode一致。

猜你喜欢

转载自my.oschina.net/u/3862440/blog/2986112