什麼場景下回發生00060死鎖問題:
一般情況下,資料庫自身發生死鎖的情況很少,一般情況都是因為應用本身呼叫問題導致的00060異常。
比如說有兩個會話sid,分別為 138 和136,這兩個會話都要對 6677 和 7788 兩個人加工資,但是執行的順序不一樣,操作分別是:
-- 會話session號 session 1 (sid = 136), session 2 (sid = 138)
-- 執行的語句 session 1 (sid = 136)
update emp set sal=sal+
100where empno=
6677
;update emp set sal=sal+
100where empno=
7788
;-- 執行的語句 session 2 (sid = 138)
update emp set sal=sal+
100where empno=
7788
;update emp set sal=sal+
100where empno=
6677
;
ora-00060:deadlock detected while waiting for resource
這樣我們就成功的觸發了乙個ora-00060。
出現這個問題,我們可以檢視oracle日誌,日誌路徑:$oracle_base/diag/rdbms/org11/ora11/trace/alert*.log
可以從告警日誌中看到很多類似如下的日誌:
ora-00060:deadlock detected.more info in file /home1/oracle/diag/rdbms/ora11g/ora11g/trace/ora11g_ora_14757.trc
我們看下對飲的trc日誌,主要看deadlock graph,其中:可以看到136和138互相死鎖,session 138(也就是 session2,sid=138)等著要 rowid=aaamfaaaagaaa的行鎖,而 session136(也就是 session1,sid=136)等著要rowid=aaamfpaaeaaaagaal 的行。
1. 給資源編號,然後按照固定的順序進行訪問。
簡單的來說,就是先改編號小的,在改編號大的。當然,反著來也可以。
-- 會話session號 session 1 (sid = 136), session 2 (sid = 138)
update emp set sal=sal+
100where empno=
6677
;update emp set sal=sal+
100where empno=
7788
;waiting...
update emp set sal=sal+
100where empno=
7788
;commit
/rollback
;update emp set sal=sal+
100where empno=
6677
;
在這裡,工資增加兩次,但是 session 2 被 session 1 阻塞了,對於使用者體驗來說,感受不好。
如果 session 1 一直不結束事務,session 2 只能一直等下去,這樣比deadlock 後,oracle 程式本身出面調停還要糟糕。
2. 可以在 select … for update nowait 語句測試一下需要更改的行是否被鎖定
如果沒有被鎖定,那這個語句會馬上給這行加鎖,如果已經加鎖那就馬上返回:ora-00054:resource busy and acquire with nowait specified
,如下表所示:
-- 會話session號 session 1 (sid = 136), session 2 (sid = 138)
select
*from emp where empno in
(6677
,7788
)for
update nowait;
select
*from emp where empno in
(6677
,7788
)for
update nowait;
ora-
00054:resource busy and acquire with nowait specified
update emp set sal=sal+
100where empno=
6677
;update emp set sal=sal+
100where empno=
7788
;
方法一和方法二都存在一定的問題,特別是在nd**中如果使用方法二那麼修改起來工作量太大,但是如果我們不處理,oracle有自動檢測死鎖並且回滾事務的功能,也就是說之前的會話中136 和138 有乙個會成功,乙個會回滾,返回失敗,這樣就保證了資料的一致性。
對應上面兩處處理方式。感覺都不好,畢竟現網這種場景較少。而且這種死鎖不是永久性的一直卡死在這,oracle會檢測到這種死鎖的,並且檢測到後會自己回滾,所以直接交給oracle即可。
查詢死鎖:
select t2.username,t2.sid,t2.seria#,t2.logon_time
from v$locked_object t1,v$session t2
where t1.session_id = t2.sid
order
by t2.logon_time;
根據 sid 查詢對應的sql語句,比如第一點查詢出 sid 為136 和138 的死鎖結果:
select sql_text
from v$session a,$sqltext_with_newlines b
where decode(a.sql_hash_value,
0,prev_hash_value,sql_hash_value)
= b.hash_value and a.sid in
('136'
,'138'
)order
by piece;
檢視處於等待狀態的sql語句:
select a.spid,c.event,b.logon_time,d.sql_text,a.program
from v$process a,v$session b,v$session_wait c,v$sql d
where a.addr = b.paddr and b.sid = c.sid
and b.sql_hash_value = d.hash_value
and c.event not
like
'%sql*net%'
and c.event not
like
'%smon%'
and c.event not
like
'%jopq%'
and c.event not
like
'%ipc%'
檢視目前是否有「長時間持有鎖未釋放」,必要的情況下可以用對應的 command 殺死 session:
select i.block,ilmode,i.request,i.
type
,i.id1,i.ctime,s.sid,s.
serial
#,t.sql_text,p.spid,
'alter system kill session'"||s.sid||
','||s.
serial
#||"',' command
from v$lock i,v$session s,v$sql t,v$process p
where i.id1 in
(select id1 from v$lock
where block =1)
and i.sid = s.sid and
(t.hash_value = decode(s.sql_hash_value,
0,s.prev_hash_value,s.sql_hash_value)
)and t.address = decode(a.sql_hash_value,
0,s.prev_hash_addr,s.sql_address)
)and p.addr = s.paddr
order
by i.id1,i.ctime desc
;
殺死程序(396為sid,60589為serial#),該條可以結合第一點進行:
alter system kill
session
'396,60589'
;
死鎖是如何產生的
死鎖產生的四個必要條件 何為必要條件?產生死鎖,必然四個條件成立 四個條件成立,不一定為死鎖 1 互斥 只有互斥才可以產生死鎖,兩個程序共同操作乙個資源,那麼,同一時間只能乙個程序來操作,那麼另乙個程序必須等待,此程序不釋放,另乙個永遠等待。產生死鎖 2 不可以強佔 兩個程序,乙個程序占有某乙個資源...
什麼是死鎖?如何避免死鎖?
所謂死鎖 是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的程序稱為死鎖程序。由於資源占用是互斥的,當某個程序提出申請資源後,使得有關程序在無外力協助下,永遠分配不到必需的資源而...
位元幣是如何產生的?如何獲得?
位元幣實際上只是區塊鏈上的乙個密碼鎖定的位址,而不是在你計算機上安裝乙個位元幣,您實際上擁有的是私鑰,可以解鎖位元幣在區塊鏈上的位置。位元幣的產生就和它的特性有關。位元幣不依賴任何機構發行,因此設計者中本聰就設計了乙個叫區塊鏈的程式,玩家只要按要求完成這個程式就可以獲得位元幣。這個過程被們戲稱稱為挖...