Java程序中解決資料庫超時與死鎖

火星人 @ 2014-03-10 , reply:0


簡介

每個使用關係型資料庫的程序都可能遇到數據死鎖或不可用的情況,而這些情況需要在代碼中編程來解決;本文主要介紹與資料庫事務死鎖等情況相關的重試邏輯概念,此外,還會探討如何避免死鎖等問題,文章以DB2(版本9)與Java為例進行講解.

什麼是資料庫鎖定與死鎖

鎖定(Locking)發生在當一個事務獲得對某一資源的「鎖」時,這時,其他的事務就不能更改這個資源了,這種機制的存在是為了保證數據一致性;在設計與資料庫交互的程序時,處理鎖與資源不可用的情況.鎖定是個比較複雜的概念,仔細說起來可能又需要一大篇,在本文中,只把鎖定看作是一個臨時事件,這意味著如果一個資源被鎖定,它總會在以後某個時間被釋放.而死鎖發生在當多個進程訪問同一資料庫時,其中每個進程擁有的鎖都是其他進程所需的,由此造成每個進程都無法繼續下去.

如何避免鎖

我們可利用事務型資料庫中的隔離級別機制來避免鎖的創建,正確地使用隔離級別可使程序處理更多的併發事件(如允許多個用戶訪問數據),還能預防像丟失修改(Lost Update)、讀「臟」數據(Dirty Read)、不可重複讀(Nonrepeatable Read)及「虛」(Phantom)等問題.

隔離級別 問題現象

丟失修改 讀「臟」數據 不可重複讀
可重複讀取 No No No No
讀取穩定性 No No No Yes
游標穩定性 No No Yes Yes
未提交的讀 7No Yes Yes Yes

表1:DB2的隔離級別與其對應的問題現象

在只讀模式中,就可以防止鎖定發生,而不用那些未提交只讀隔離級別的含糊語句.一條SQL語句當使用了下列命令之一時,就應該考慮只讀模式了:

1、JOIN

2、SELECT DISTINCT

3、GROUP BY

4、ORDER BY

5、UNION

6、UNION ALL

7、SELECT

8、FOR FETCH ONLY (FOR READ ONLY)

9、SELECT FROM

如果包含上述任一命令,可以說你的SQL語句有歧義性,因此,鎖可能就是造成其中資源問題的源頭.

另外,以下是一些可降低鎖數目的建議:

1、 將CURRENTDATA設為NO.這條命令告訴DB2模糊游標為只讀.

2、 在適當的時候,儘可能使用User Uncommitted Read(用戶未提交的讀).

3、 儘可能關閉所有游標.

4、 有一個正確的提交策略.確保程序不再使用資源時就立即釋放它.

如何處理死鎖與超時

在程序中使用重試邏輯,可處理以下三種SQL錯誤代碼:

1、 904:返回這個代碼表示一條SQL語句是已達到資源限度而結束的.程序中可提交或回滾更改,並執行重試邏輯.

2、 911:程序收到這個SQL代碼,表示沒有為鎖列表分配足夠的內存,現在已達到資料庫的最大鎖數目.

3、 912:程序收到這個SQL代碼,表示死鎖或超時,依照904中的方法來解決.

以下是一段Java代碼,其捕捉返回的-911、-912、-904代碼,並進行重試:

for (int i = 0; i < MAX_RETRY_ATTEMPTS; i  ) {

//以下代碼模擬一次事務

try {

stmt = conn.createStatement();

System.out.println("Transaction started...");

stmt.executeUpdate("UPDATE 1..."); //SQL語句1

stmt.executeUpdate("UPDATE 2..."); // SQL語句2

stmt.executeUpdate("UPDATE 3..."); // SQL語句3

stmt.executeUpdate("UPDATE 3..."); // SQL語句4

//提交所有更改

conn.commit();

System.out.println("事務已完成.");

//確保只運行了一次.

i = MAX_RETRY_ATTEMPTS;

} catch (SQLException e) {

/**

*如果返回的SQL代碼為-911,回滾會自動完成,程序回滾至前一次的提交狀態.

*程序將進行重試.

*/

if (-911 == e.getErrorCode()) {

//等待RETRY_WAIT_TIME

try {

Thread.sleep(RETRY_WAIT_TIME);

} catch (InterruptedException e1) {

//即使休眠被打斷,但仍要重試.

System.out.println("休眠被打斷.");




[火星人 via ] Java程序中解決資料庫超時與死鎖已經有195次圍觀

http://www.coctec.com/docs/java/show-post-62208.html