【DEADLOCK】Oracle“死鎖”模擬

secooler發表於2011-10-22
本著實驗優先的原則,先模擬死鎖的發生,然後在列一下死鎖產生的四個必要條件和處理死鎖的一般策略。

1.建立兩個簡單的表t1_deadlock和t2_deadlock,每個表中僅僅包含一個欄位a
sys@ora10g> conn sec/sec
Connected.
sec@ora10g> create table t1_deadlock (a int);

Table created.

sec@ora10g> create table t2_deadlock (a int);

Table created.

2.每張表中僅初始化一條資料
sec@ora10g> insert into t1_deadlock values (1);

1 row created.

sec@ora10g> insert into t2_deadlock values (2);

1 row created.

sec@ora10g> commit;

Commit complete.

3.在第一個會話session1中更新表t1_deadlock中的記錄“1”為“1000”,不進行提交
sec@ora10g> update t1_deadlock set a = 1000 where a = 1;

1 row updated.

4.在第二個會話session2中更新表t2_deadlock中的記錄“2”為“2000”,不進行提交
sec@ora10g> update t2_deadlock set a = 2000 where a = 2;

1 row updated.

5.此時,沒有任何問題發生。OK,現在注意一下下面的現象,我們再回到會話session1中,更新t2_deadlock的記錄
sec@ora10g> update t2_deadlock set a = 2000 where a = 2;
這裡出現了“鎖等待”(“阻塞”)的現象,原因很簡單,因為在session2中已經對這條資料執行過這個操作,在session2中已經對該行加了行級鎖。
注意,這裡是“鎖等待”,不是“死鎖”,注意這兩個概念的區別!

檢測“鎖等待”的方法曾經提到過,請參考《【實驗】【LOCK】“鎖等待”模擬、診斷及處理方法》http://space.itpub.net/519536/viewspace-605526
sec@ora10g> @lock

lock       lock               
holder   holder         lock               lock request       blocked
username sessid SERIAL# type      id1  id2 mode    mode BLOCK  sessid
-------- ------ ------- ------ ------ ---- ---- ------- ----- -------
SEC         141    6921 TM      15160    0    3       0     0
SEC         141    6921 TX     393231 1672    6       0     1     145
SEC         145    7402 TM      15159    0    3       0     0
SEC         145    7402 TM      15160    0    3       0     0
SEC         145    7402 TX     131077 1675    6       0     0
            164       1 TS          3    1    3       0     0
            165       1 CF          0    0    2       0     0
            165       1 RS         25    1    2       0     0
            165       1 XR          4    0    1       0     0
            166       1 RT          1    0    6       0     0
            167       1 PW          1    0    3       0     0

11 rows selected.


6.我們關注的“死鎖”馬上就要隆重出場了:在會話session2中,更新t1_deadlock的記錄(滿足了死鎖產生的四個條件了,請慢慢體會)
sec@ora10g> update t1_deadlock set a = 1000 where a = 1;
這裡還是長時間等待的現象,但是這裡發生了“死鎖”!!
細心的您再去第一個會話session1中看一下,原先一直在等待的SQL語句出現如下的現象:
sec@ora10g> update t2_deadlock set a = 2000 where a = 2;
update t2_deadlock set a = 2000 where a = 2
       *
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource

更進一步:檢視一下alert警告日誌檔案發現有如下的記錄
Mon Aug 10 11:24:29 2009
ORA-00060: Deadlock detected. More info in file /oracle/app/oracle/admin/ora10g/udump/ora10g_ora_25466.trc.

再進一步:看看系統自動生成的trace檔案中記錄了什麼
這個檔案包含了5721行的記錄資訊,擷取其中我們關心的前面N多行的內容(結合剛才檢測“鎖等待”指令碼產生的結果分析一下,看看有沒有收穫):
/oracle/app/oracle/admin/ora10g/udump/ora10g_ora_25466.trc
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP and Data Mining Scoring Engine options
ORACLE_HOME = /oracle/app/oracle/product/10.2.0/db_1
System name:    Linux
Node name:      testdb
Release:        2.6.18-53.el5xen
Version:        #1 SMP Wed Oct 10 16:48:44 EDT 2007
Machine:        x86_64
Instance name: ora10g
Redo thread mounted by this instance: 1
Oracle process number: 14
Unix process pid: 25466, image: oracle@testdb (TNS V1-V3)

*** 2009-08-10 11:24:29.541
*** ACTION NAME:() 2009-08-10 11:24:29.540
*** MODULE NAME:(SQL*Plus) 2009-08-10 11:24:29.540
*** SERVICE NAME:(SYS$USERS) 2009-08-10 11:24:29.540
*** SESSION ID:(145.7402) 2009-08-10 11:24:29.540
DEADLOCK DETECTED
[Transaction Deadlock]
Current SQL statement for this session:
update t2_deadlock set a = 2000 where a = 2
The following deadlock is not an ORACLE error. It is a
deadlock due to user error in the design of an application
or from issuing incorrect ad-hoc SQL. The following
information may aid in determining the deadlock:
Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TX-00020005-0000068b        14     145     X             15     141           X
TX-0006000f-00000688        15     141     X             14     145           X
session 145: DID 0001-000E-0000037D     session 141: DID 0001-000F-0000013D
session 141: DID 0001-000F-0000013D     session 145: DID 0001-000E-0000037D
Rows waited on:

7.以上種種現象說明什麼?
說明:Oracle對於“死鎖”是要做處理的,而不是採用下面提到的“鴕鳥演算法”不聞不問。
注意trace檔案中的一行如下提示資訊,說明一般情況下都是應用和人為的,和Oracle同學沒有關係:
The following deadlock is not an ORACLE error. It is a
deadlock due to user error in the design of an application
or from issuing incorrect ad-hoc SQL.

8.以上演示了一種“死鎖”現象的發生,當然導致死鎖發生的情況遠遠不僅如此。所以在程式設計時一定要好好的進行思考

9.【擴充】
死鎖產生的四個必要條件
1)Mutual exclusion(互斥):資源不能被共享,只能由一個程式使用。
2)Hold and wait(請求並保持):已經得到資源的程式可以再次申請新的資源。
3)No pre-emption(不可剝奪):已經分配的資源不能從相應的程式中被強制地剝奪。
4)Circular wait(迴圈等待條件):系統中若干程式組成環路,該環路中每個程式都在等待相鄰程式正佔用的資源。

處理死鎖的一般策略
1)鴕鳥演算法忽略該問題
2)檢測死鎖並且恢復
3)仔細地對資源進行動態分配,以避免死鎖
4)透過破壞死鎖產生呢過的四個必要條件之一,來防止死鎖產生

10.總結
死鎖對於資料庫來說是非常要命的,請多多注意!
對於上面的演示處理的方式:在會話session1中執行rollback進行回滾,會釋放導致session2鎖等待的鎖資源(死鎖Oracle已經處理了)。

Good luck.

secooler
11.10.22

-- The End --

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/519536/viewspace-611729/,如需轉載,請註明出處,否則將追究法律責任。

相關文章