常見的死鎖是如何產生的,如何避免

2021-09-09 05:45:49 字數 4565 閱讀 8047

什麼場景下回發生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 不可以強佔 兩個程序,乙個程序占有某乙個資源...

什麼是死鎖?如何避免死鎖?

所謂死鎖 是指兩個或兩個以上的程序在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的程序稱為死鎖程序。由於資源占用是互斥的,當某個程序提出申請資源後,使得有關程序在無外力協助下,永遠分配不到必需的資源而...

位元幣是如何產生的?如何獲得?

位元幣實際上只是區塊鏈上的乙個密碼鎖定的位址,而不是在你計算機上安裝乙個位元幣,您實際上擁有的是私鑰,可以解鎖位元幣在區塊鏈上的位置。位元幣的產生就和它的特性有關。位元幣不依賴任何機構發行,因此設計者中本聰就設計了乙個叫區塊鏈的程式,玩家只要按要求完成這個程式就可以獲得位元幣。這個過程被們戲稱稱為挖...