SQLException:尽管关闭了所有资源,数据库仍被锁定

时间:2017-02-17 08:53:32

标签: java multithreading sqlite

我正在尝试调试多线程应用程序,该应用程序将一个文件作为输入处理并写入SQLite数据库。

在应用程序中,我创建了4个线程,每个线程都写入一个单独的.db文件,以防止出现任何同步/文件访问问题。我得到的数据库是锁定错误,尽管我正在使用try资源,除了明确关闭我完成后打开的任何资源。这是我的代码(在线程对象内部):

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);
    }
}

正如您所看到的,我使用“try with resource”打开连接和预准备语句,然后在try块的末尾关闭它们。会发生什么事情,该程序将运行一段时间(线程正在创建,运行和死亡),然后我似乎随机得到这个:

java.sql.SQLException: database is locked

指向我所在的行

insertReview.executeBatch();

conn.commit();

或我创建预准备语句的try声明中的行,并且抛出异常的线程似乎也是随机的。

我完全不知道为什么,因为我很肯定,一旦我不再需要它,我就会关闭所有资源。

编辑:我只想强调,例外情况似乎是随机抛出的。有时它会在线程第一次尝试执行批处理时抛出,有时程序会在没有问题的情况下运行一段时间(在进程中创建线程,这些都运行得非常好),直到抛出异常为止。它与目前程序处理的数据量没有关联(从0到60,000个条目)。

1 个答案:

答案 0 :(得分:0)

检查executeBatch()和commit()是否都是同步函数...此外,您可以尝试将数据库设置为序列化或多线程模式以防万一。