咱們都知道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