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

相關文章
相關標籤/搜索