1. 程式人生 > >鎖分析

鎖分析

在資料庫運維工作中,有相當大一部分工作跟鎖有關。

鎖用對了地方能保證資料一致性,用錯了地方就能導致併發性下降。

下面來講解資料庫發生鎖,該如何進行診斷:

首先將幾個鎖相關的檢視:

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一致。