Oracle中的死鎖Dead Lock(一)
幾天前和一位做應用的同事討論,聊到了死鎖。筆者覺得很有意思,就把討論中的一些想法和知識拿出來和大家分享。
死鎖Dead Lock
我們大家最早接觸死鎖這個概念可能是在作業系統課程中,說多個程式(執行緒)對一個可共享的資源進行請求的時候,可能出現死鎖。死鎖問題分為死鎖檢測、處理等多個子問題可以進行討論。
其實,死鎖問題絕不僅僅限制在作業系統乃至電腦科學領域。死鎖存在的兩個必要條件,一個是多工工作的併發,另一個是共享資源的獨佔性需求。只要一個系統(廣義系統)中存在這兩個前提,我們就認為可能出現死鎖的情況。
死鎖描述的是一種狀態。當兩個或兩個以上的任務單元在執行過程中,因為請求資源出現等待,因資源永遠不能獲得而相互等待的狀態。如果沒有外力的作用,死鎖狀態是會一直持續下去。死鎖是伴隨著多工、並行操作產生的,在單任務情況下,一個任務單元可以使用並且獨佔所有資源,不存在資源等待的情況,所以也沒有死鎖的情況。在進入多工系統環境下,多個任務之間存在資源共享和獨佔的需求,才可能出現死鎖。
死鎖最簡單的例子:任務A,B,資源1,2。任務A獨佔了資源1,任務B獨佔了資源2。此時,任務A要資源2,向任務B提出請求並等待。任務B要求資源1,並且也等待。AB兩者均不釋放所佔有的資源,就造成了死鎖。
Oracle中的死鎖
Oracle是目前商業資料庫市場上表現最優秀的併發資料庫系統,同樣存在死鎖的威脅。存在併發、存在資源獨佔,就有鎖lock或者類似鎖概念的機制。Oracle提供了多種型別鎖和多種鎖的機制,包括共享鎖和獨佔鎖。並且,在進行各型別操作的時候,自動的對物件進行加鎖解鎖,以及鎖升級操作,最大可能的保證資料完整性。
那麼,如果出現死鎖,Oracle會如何處理呢?
Oracle的鎖機制是建立在行鎖一級,在插入、更新行一級資訊的時候,會加入獨佔鎖內容。那麼,我們嘗試模擬下出現死鎖的狀態。兩個session分別更新兩條記錄,在一個事務裡再嘗試更新對方記錄,那麼可以引發死鎖。
實驗環境準備:
SQL> desc t;
Name Type Nullable Default Comments
---- ------------ -------- ------- --------
ID NUMBER
COMM VARCHAR2(10) Y
SQL> select * from t where rownum<3;
ID COMM
---------- ----------
1 Tst1
2 Tst2
兩個session,分別針對id=1,2兩條記錄做文章。
//Session1
SQL> select sid from v$mystat where rownum<2;
SID
----------
152
SQL> update t set comm='Tst1' where id=1;
1 row updated
//Session2
SQL> select sid from v$mystat where rownum<2;
SID
----------
150
SQL> update t set comm='Tst2' where id=2;
1 row updated
此時,鎖的狀態為:
SQL> select * from v$lock where sid in (150,152);
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST
-------- -------- ---------- ---- ---------- ---------- ---------- ----------
333415A4 333415BC 152 TM 54599 0 3 0
33341668 33341680 150 TM 54599 0 3 0
3338A42C 3338A548 150 TX 393251 795 6 0
333B8954 333B8A70 152 TX 327686 779 6 0
此時,我們看到了在兩個session中,分別使用了行鎖,獨佔(LMODE=6)鎖住了兩行。下面繼續相互請求。
//session1中,嘗試更新id=2的記錄
SQL> update t set comm='Tst2' where id=2;
Session1(SID=152)被hange住。
//鎖狀態
SQL> select * from v$lock where sid in (150,152);
ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST
-------- -------- ---------- ---- ---------- ---------- ---------- ----------
33834398 338343AC 152 TX 393251 795 0 6
333415A4 333415BC 152 TM 54599 0 3 0
33341668 33341680 150 TM 54599 0 3 0
3338A42C 3338A548 150 TX 393251 795 6 0
333B8954 333B8A70 152 TX 327686 779 6 0
說明:在Oracle中,hange表示session正在等待資源被釋放,表現就是停住操作,不斷的輪詢資源。
Session2請求更新:
//session2(SID=150)
SQL> update t set comm='Tst1' where id=1;
注意:此時,應當出現死鎖狀態,而在系統中,也出現了一瞬間的兩個session互相hange的狀態;
此時,session2繼續被hange住,原先的session1退出,如下狀態:
//session1(SID=152)
SQL> update t set comm='Tst2' where id=2;
update t set comm='Tst2' where id=2
ORA-00060: 等待資源時檢測到死鎖
結果是:Oracle在兩個出現死鎖的session中,隨機尋找了一個session,駁回了其被hange住的請求,維持另一方session的hange狀態。
注意:Oracle此處的處理:只是駁回了一方的請求,並沒有回滾該請求,也沒有將另一方的hange狀態解除。
思考:顯然,這個過程中是Oracle內部的防護機制起了作用,防止了系統中死鎖的發生。在Oracle中,存在某種輪詢的機制,隨時檢查系統中出現的多會話被hange住的情況,一旦發生,就將一個session被hange住的請求退回,丟擲00060錯誤。
在兩個session互鎖的情況下,Oracle死鎖檢測程式可以起作用。那麼,如果死鎖結構複雜的時候,是不是Oracle的檢測機制會失效。筆者使用4-5個session進行檢查,雖然檢測起效的時間有長有短,但最後都是將死鎖的狀態加以解除。
有一點需要注意,Oracle解決死鎖的方式只是將請求拒絕,並不是將事務回滾。所以,在解決死鎖之後,其他被hange住的session依然還是被hange住。所以,從應用程式和PL/SQL的角度,如果接受到了60錯誤,應該做的工作就是回滾當前事務,解決整體的資源爭用現象。
Oracle死鎖發生
那麼,Oracle中死鎖發生的機率是不是那麼高呢?答案是否定的。這個是由Oracle鎖的特性所決定的。
1、 Oracle對查詢不加鎖。Oracle本身支援多版本一致讀,如果當前的資料塊正在被修改(獨佔)而並未提交,Oracle會根據SCN查詢日誌和Undo空間,找到合適SCN的版本返回結果。所以,在查詢的時候,是不需要加鎖的。
2、 Oracle資料操作使用行級鎖(本質上是事務鎖),實現最小粒度的獨佔範圍。Oracle在DML的時候,只會對操作的行進行獨佔鎖定,而不是過大的資料單元(如頁page)。這樣,就保證了不會引起過多的獨佔資源。
同時,Oracle本身也提供了死鎖監視程式功能,能及時發現死鎖狀態,並自動的進行解鎖。在這些機制下,Oracle認為死鎖發生的機率很低(起碼自身不會引起死鎖)。只有一種情況會引發死鎖,就是開發人員手工提高加鎖的級別。
Oracle對於SQL的擴充中,有一部分是顯示物件加鎖。從lock table XXX到select XXX for update。這些操作都會引起對物件鎖級別的提升,這些都可能引發死鎖的發生。
那麼,如果出現死鎖的情況,我們如何處理?在設計應用的過程中,我們如何避免死鎖現象? 留待下次繼續討論。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29067253/viewspace-2149853/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle中的死鎖Dead Lock(二)Oracle
- java安全編碼指南之:死鎖dead lockJava
- Dead lock - oracleOracle
- SQL Server 2000 死鎖(dead lock) 問題解決SQLServer
- oracle lock轉換及oracle deadlock死鎖系列一Oracle
- oracle dead lock與效能Oracle
- MYSQL中一個特殊的MDL LOCK死鎖案列MySql
- ORACLE中殺死鎖程式的方法Oracle
- [CareerCup] 16.4 A Lock Without Deadlocks 無死鎖的鎖
- mysql dead lock detectionMySql
- oracle 死鎖Oracle
- oracle lock鎖_v$lock_轉Oracle
- 殺死Oracle死鎖程式Oracle
- innodb_lock_monitor解決mysql死鎖MySql
- 從OS中kill ORACLE死鎖程式Oracle
- Java 中的死鎖Java
- 使用oracle 10704 event分析獲取鎖lock及死鎖deadlock系列九Oracle
- Oracle死鎖一例(ORA-00060),鎖表導致的業務死鎖問題Oracle
- 一個ORACLE死鎖問題的追蹤Oracle
- 檢視oracle死鎖程式並結束死鎖Oracle
- Oracle 死鎖處理Oracle
- Oracle死鎖處理Oracle
- ORACLE死鎖檢測Oracle
- 記一次Oracle死鎖/阻塞排查Oracle
- oracle 死鎖解決方法一例Oracle
- oracle殺死鎖表的程式Oracle
- 面試:什麼是死鎖,如何避免或解決死鎖;MySQL中的死鎖現象,MySQL死鎖如何解決面試MySql
- MySQL:一個死鎖分析 (未分析出來的死鎖)MySql
- 執行緒中的死鎖執行緒
- oracle deadlock死鎖trace file分析之一Oracle
- innodb next-key lock引發的死鎖現象分析
- MYSQL INNODB replace into 死鎖 及 next key lock 淺析MySql
- 解決Oracle死鎖的快捷方法Oracle
- 關於oracle死鎖的模擬Oracle
- oracle自治事務引起的死鎖Oracle
- 查詢並解除oracle的死鎖Oracle
- ORACLE 死鎖分析過程Oracle
- oracle 死鎖表解決方法Oracle