【问题标题】:SQLException: database is locked despite closing all resourcesSQLException:尽管关闭了所有资源,但数据库仍被锁定
【发布时间】:2017-07-06 17:06:03
【问题描述】:

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

在应用程序中,我创建了 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);
    }
}

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

java.sql.SQLException: database is locked

这要么将我指向我调用的行

insertReview.executeBatch();

conn.commit();

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

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

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

【问题讨论】:

  • 您不需要在 try-with-resources 块中显式关闭连接。
  • @Andy 我意识到这一点,但我这样做只是为了安全起见,因为当我只对资源使用 try 时仍然会抛出错误。
  • “锁定”表示其他人正在访问同一个数据库。您确定每个线程只使用自己的 .db 吗?
  • @CL。是的,创建文件路径时引用的“num”变量是在创建每个线程时设置的变量,我确保每个线程都为此设置了不同的值。所以第一个线程只输出到database1.db,第二个输出到databes4.db,以此类推

标签: java multithreading sqlite


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2011-02-05
    • 1970-01-01
    • 2014-09-30
    • 2011-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-13
    相关资源
    最近更新 更多