2017-02-17 67 views
0

我試圖調試一個多線程應用程序,它處理一個文件作爲輸入並寫入SQLite數據庫。SQLException:數據庫被鎖定,儘管關閉所有資源

在應用程序中,我創建4個線程,每個線程寫入單獨的.db文件以防止任何同步/文件訪問問題。儘管事實上我正在使用資源嘗試,除了明確地關閉完成後打開的任何資源外,我還是收到了數據庫已鎖定的錯誤。這裏是我的代碼(內部線程對象的):

public void run() { 
    String path = database + num + ".db"; 
    try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + path); 
     PreparedStatement insertReview = conn.prepareStatement("insert into reviews (" + 
       "reviewerID, " + 
       "asin, " + 
       "rating, " + 
       "title, " + 
       "content, " + 
       "helpfulVotes, " + 
       "totalVotes) values (?1, ?2, ?3, ?4, ?5, ?6, ?7);");) { 
     System.out.println("Writing from thread " + num); 
     Class.forName("org.sqlite.JDBC"); 
     int x = 1; 
     for (Object[] review : reviews) { 
      insertReview.setString(1, (String) review[0]); 
      insertReview.setString(2, (String) review[1]); 
      insertReview.setDouble(3, (Double) review[2]); 
      insertReview.setString(4, (String) review[3]); 
      insertReview.setString(5, (String) review[4]); 
      insertReview.setInt(6, Integer.parseInt((String) review[5])); 
      insertReview.setInt(7, Integer.parseInt((String) review[6])); 
      insertReview.addBatch(); 
      //System.out.println("Processed review " + x + " of " + reviews.size() + " in " + num); 
      x++; 
     } 

     conn.setAutoCommit(false); 
     System.out.println("Executing batch in " + num); 
     insertReview.executeBatch(); 
     insertReview.close(); 
     conn.commit(); 
     conn.close(); 
    } 
    catch (Exception e) { 
     System.out.println("Thread" + num); 
     e.printStackTrace(); 
     System.exit(1); 
    } 
} 

正如你所看到的,我打開與連接,並已準備語句是「試着用資源」,然後在嘗試年底關閉它們既塊。什麼情況是,該方案將運行一段罰款(與正在創建的線程,運行和垂死的),然後我會看似隨機得到:

java.sql.SQLException: database is locked 

要麼點我​​到我所說的行

insertReview.executeBatch(); 

conn.commit(); 

或嘗試聲明,我創建了事先準備好的聲明中的線,並引發異常的線程是似乎是隨機的爲好。

我完全不知道爲什麼,因爲我肯定我會關閉每一個資源,一旦我不再需要它。

編輯:我想強調的是,異常被拋出看似隨機。有時它是在線程第一次嘗試執行批處理時拋出的,有時候程序會在沒有問題的情況下運行一段時間(在進程中創建線程,這些線程都運行得非常好),直到拋出異常爲止。它與目前爲止已經被程序處理的數據量沒有關係(它的範圍從0到60,000個條目)。

+0

您不應該在try-with-resources塊中顯式關閉連接。 –

+0

@我意識到這一點,但我只是爲了安全起見,因爲當我僅僅使用資源嘗試時,錯誤仍然被拋出。 – theasianpianist

+1

「鎖定」表示其他人正在訪問相同的數據庫。你確定每個線程只使用它自己的.db嗎? –

回答

0

檢查executeBatch()和commit()是否都是同步函數......此外,您可以嘗試將數據庫設置爲序列化或多線程模式以防萬一。