我試圖調試一個多線程應用程序,它處理一個文件作爲輸入並寫入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個條目)。
您不應該在try-with-resources塊中顯式關閉連接。 –
@我意識到這一點,但我只是爲了安全起見,因爲當我僅僅使用資源嘗試時,錯誤仍然被拋出。 – theasianpianist
「鎖定」表示其他人正在訪問相同的數據庫。你確定每個線程只使用它自己的.db嗎? –