Oracle数据库锁诊断
2019獨角獸企業重金招聘Python工程師標準>>>
我們都知道Oracle是一個大并發的數據庫,有了鎖數據庫才可能實現大并發,也是應為鎖Oracle大并發受到影響。
首先介紹下如何判斷數據庫是否有鎖,來看一個視圖:
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 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 ?????????068 TM ???????74569 ?????????0 ?????????3 ?????????0 ?????????05 TM ???????74569 ?????????0 ?????????3 ?????????0 ?????????068 TX ??????131079 ???????777 ?????????6 ?????????0 ?????????1SQL>我們可以看到 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$lock where type in ('TX','TM'));SID ???SERIAL# SQL_ID---------- ---------- --------------------------5 ????????68 0d4ag0mv6hqcp68 ????????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=200d4ag0mv6hqcp?
以上可以看到,堵塞的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
轉載于:https://my.oschina.net/u/3862440/blog/2870115
總結
以上是生活随笔為你收集整理的Oracle数据库锁诊断的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: react - antd (Table
- 下一篇: 安装mysql-8.0.13-winx6