Java程式中解決資料庫逾時與死結

來源:互聯網
上載者:User

標籤:

Java程式中解決資料庫逾時與死結2011-06-07 11:09 佚名 幫考網 字型大小:T | T 

Java程式中解決資料庫逾時與死結,每個使用關係型資料庫的程式都可能遇到資料死結或停用情況,而這些情況需要在代碼中編程來解決。本文主要介紹與資料庫事務死結等情況相關的重試邏輯概念。

AD:

 

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

簡介

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

什麼是資料庫鎖定與死結

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

如何避免鎖

我們可利用事務型資料庫中的隔離等級機制來避免鎖的建立,正確地使用隔離等級可使程式處理更多的並發事件(如允許多個使用者訪問資料),還能預防像丟失修改 (Lost Update)、讀“髒”資料(Dirty Read)、不可重複讀取(Nonrepeatable Read)及“虛”(Phantom)等問題。

在唯讀模式中,就可以防止鎖定發生,而不用那些未提交唯讀隔離等級的含糊語句。一條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代碼,並進行重試:

 

  1. for (int i = 0; i < MAX_RETRY_ATTEMPTS; i++) {  
  2. //以下代碼類比一次事務  
  3. try {  
  4. stmt = conn.createStatement();  
  5. System.out.println("Transaction started...");  
  6. stmt.executeUpdate("UPDATE 1..."); //SQL語句1  
  7. stmt.executeUpdate("UPDATE 2..."); // SQL語句2  
  8. stmt.executeUpdate("UPDATE 3..."); // SQL語句3  
  9. stmt.executeUpdate("UPDATE 3..."); // SQL語句4  
  10. //提交所有更改  
  11. conn.commit();  
  12. System.out.println("事務已完成。");  
  13. //確保只運行了一次。  
  14. i = MAX_RETRY_ATTEMPTS;  
  15. } catch (SQLException e) {  
  16. /**  
  17. *如果返回的SQL代碼為-911,復原會自動完成,程式復原至前一次的提交狀態。  
  18. *程式將進行重試。  
  19. */ 
  20. if (-911 == e.getErrorCode()) {  
  21. //等待RETRY_WAIT_TIME  
  22. try {  
  23. Thread.sleep(RETRY_WAIT_TIME);  
  24. } catch (InterruptedException e1) {  
  25. //即使休眠被打斷,但仍要重試。  
  26. System.out.println("休眠被打斷。");  
  27. }  
  28. }  
  29. /**  
  30. *如果返回的SQL代碼為-912,表示死結及逾時。  
  31. *如果是-904,代表已達到資源限度。  
  32. *在這種情況下,程式將復原並進行重試。  
  33. */ 
  34. else if (-912 == e.getErrorCode() || -904 == e.getErrorCode()) {  
  35. try {  
  36. //需要復原  
  37. conn.rollback();  
  38. } catch (SQLException e1) {  
  39. System.out.println("無法復原。"; color:black’> + e);  
  40. }  
  41. try {  
  42. //等待RETRY_WAIT_TIME  
  43. Thread.sleep(RETRY_WAIT_TIME);  
  44. } catch (InterruptedException e1) {  
  45. //即使休眠被打斷,但仍要重試。  
  46. System.out.println("休眠被打斷。" + e1);  
  47. }  
  48. } else {  
  49. //如果是其他錯誤,就不進行重試。  
  50. i = MAX_RETRY_ATTEMPTS;  
  51. System.out.println("有錯誤發生,錯誤碼:" 
  52. + e.getErrorCode() + " SQL狀態:" 
  53. +e.getSQLState() + "其他資訊:" + e.getMessage());  

 

從上面也可看到,程式對死結、逾時、最大鎖數目將會進行MAX_RETRY_ATTEMPTS次重試;其次,當“最大鎖數目”的情況發生時 (-911),程式不必手工進行復原,因為此時的復原是自動完成的;最後,無論何時返回-911、-904、-912代碼,程式應在下次重試前等待 RETRY_WAIT_TIME一段時間。

Java程式中解決資料庫逾時與死結

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.