【问题标题】:SQLite via JDBC: SQLITE_BUSY when inserting after selecting通过 JDBC 的 SQLite:选择后插入时的 SQLITE_BUSY
【发布时间】:2019-02-04 09:57:06
【问题描述】:

从表中选择后尝试写入表时,我收到错误代码 SQLITE_BUSY。 select 语句和结果在我插入之前已正确关闭。

如果我要删除选择部分,则插入工作正常。这就是我没有得到的。根据文档SQLITE_BUSY 应该意味着不同的进程或连接(这里绝对不是这种情况)正在阻塞数据库。

没有运行 SQLite 管理器。 jdbcConn 也是我拥有的与数据库的唯一连接。也没有并行运行的线程。

这是我的代码:

    try {
        if(!jdbcConn.isClosed()) {
            ArrayList<String> variablesToAdd = new ArrayList<String>();

            String sql = "SELECT * FROM VARIABLES WHERE Name = ?";

            try (PreparedStatement stmt = jdbcConn.prepareStatement(sql)) {
                for(InVariable variable : this.variables.values()) {
                    stmt.setString(1, variable.getName());
                    try(ResultSet rs = stmt.executeQuery()) {
                        if(!rs.next()) {
                            variablesToAdd.add(variable.getName());                 
                        }
                    }
                }
            }

            if(variablesToAdd.size() > 0) {
                String sqlInsert = "INSERT INTO VARIABLES(Name, Var_Value) VALUES(?, '')";
                try(PreparedStatement stmtInsert = jdbcConn.prepareStatement(sqlInsert)) {
                    for(String name : variablesToAdd) {
                        stmtInsert.setString(1, name);
                        int affectedRows = stmtInsert.executeUpdate();

                        if(affectedRows == 0) {
                            LogManager.getLogger().error("Error while trying to add missing database variable '" + name + "'.");
                        }
                    }
                }

                jdbcConn.commit();
            }
        }
    }
    catch(Exception e) {
        LogManager.getLogger().error("Error creating potentially missing database variables.", e);
    }

这会在 int affectedRows = stmtInsert.executeUpdate(); 上崩溃。现在,如果我删除第一个块(并手动将一个值添加到 variablesToAdd 列表中),该值将很好地插入到数据库中。

我错过了什么吗?我没有正确关闭 ResultSet 和 PreparedStatement 吗?也许我看得太久了,我对自己的错误视而不见。

编辑:在单独的线程中执行选择也可以解决问题。但这不可能是解决方案。关闭之前的语句后,我是否试图太快地插入数据库?

Edit2:我遇到了一个 busy_timeout,它承诺让更新/查询在返回 SQLITE_BUSY 之前等待指定的时间。我尝试像这样设置繁忙超时:

if(jdbcConn.prepareStatement("PRAGMA busy_timeout = 30000").execute()) {
    jdbcConn.commit();
}

executeUpdate() 函数仍会立即返回 SQLITE_BUSY。

【问题讨论】:

  • 你写了 select 语句和结果在我插入之前正确关闭。,但你从不调用stmt.close()。所以,你的陈述没有正确结束。
  • 由于我使用了try-with-resource,它应该正确关闭:docs.oracle.com/javase/tutorial/essential/exceptions/… 但我可能会尝试传统的try-finally-close,看看它是否有所作为。
  • 啊,现在我明白了。不,理论上,隐式关闭应该适用于 JDBC。但是,这仍然会消除一个潜在的错误。
  • @M.Folte - 我似乎无法使用 sqlite-jdbc-3.25.2.jar 重现您的问题。你运行的是什么版本?
  • @Gord Thompson - 正在运行 3.19.3。不知道为什么我没有更新的想法。不幸的是,即使在 3.25.2 上,问题仍然存在。

标签: sqlite jdbc


【解决方案1】:

我很笨。 删除 select 语句有效(仍然不确定为什么有效,可能是时机不好),我非常震惊,以至于我错过了使用同一文件的不同线程。

让两个线程使用相同的 java.sql.Connection,现在一切正常。

感谢您将我推向正确的方向@GordThompson。不知道导致我发现问题的 jdbc:sqlite::memory: 选项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多