2012-05-11 108 views
3

我有一個運行在多臺計算機上的Java應用程序,它們都連接到同一個MySQL數據庫。我需要事務來確保數據庫正確更新。Java和MySQL交易

我有解鎖問題。下面是代碼:

public boolean bookSeats(int numeroSala, Calendar dataOra, List<Posto> posti) { 
    JDBConnection connection = JDBConnection.getDbConnection(); 
    Connection conn = connection.conn; 
    java.sql.Date javaSqlDate = new java.sql.Date(dataOra.getTime().getTime()); 
    java.sql.Time javaSqlTime = new java.sql.Time(dataOra.getTime().getTime()); 

    try { 
     conn.setAutoCommit(false); 
     conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); 
    } catch (SQLException e) { 
     e.printStackTrace(); 
    } 

    try 
    { 
     Posto p = null; 
     ListIterator<Posto> itr = posti.listIterator(); 
     PreparedStatement stmt = null; 
     stmt = conn.prepareStatement(
      "INSERT INTO sala?_tickets " + 
      "(giornoSpettacolo, orarioSpettacolo, fila, posto) " + 
      "VALUES (?, ?, ?, ?)"); 

     stmt.setInt(1, numeroSala); 
     while(itr.hasNext()) 
     { 
      p = itr.next(); 
      stmt.setString(2, javaSqlDate.toString()); // giornoSpettacolo 
      stmt.setString(3, javaSqlTime.toString()); // orarioSpettacolo 
      stmt.setInt(4, p.getFila()); // fila 
      stmt.setInt(5, p.getNumero()); // posto 
      stmt.addBatch(); 
     } 

     stmt.executeBatch(); 

     conn.commit(); 
     return true; 
    } 
    catch (SQLException e) { 
     e.printStackTrace(); 
    } 

    return false; 
} 

這種方法效果很好,但是當我試圖在同一時間執行這一另一臺計算機上,我得到即使conn.commit()完成死鎖錯誤。

只要我關閉第一個應用程序,其他應用程序就可以運行沒有死鎖錯誤的方法。這似乎是COMMIT不釋放鎖?

回答

3

每MySQL文檔,約SERIALIZABLE:

這個級別是像REPEATABLE READ,但是InnoDB的隱式轉換所有 平原SELECT語句SELECT ... LOCK IN SHARE MODE如果自動提交 被禁用。

您可能想要在提交後嘗試重新啓用自動提交,或嘗試連接。改爲REPEATABLE_READ。

+0

處理謝謝,這個固定我的問題! – Gotenks

0

您可以參考this documentantion關於如何使用裸JDBC執行事務。希望能幫助到你。

0

您應該始終在finally塊中執行conn.close()以確保釋放您的方法使用的任何資源。

0

是的,首先回答說關閉連接。但是,另外,如果您可以將上面的代碼放入「同步」方法中,它將確保一次只有一個線程可以訪問它。

除此之外,只要看看下面的鏈接,其中約僵局討論JDBC

Deadlock detection in Java