在从表中选择后尝试写入表时,我收到错误代码 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);
}
这会在 intaffectedRows = stmtInsert.executeUpdate();
上崩溃。现在,如果我删除第一个 block (并手动将一个值添加到 variablesToAdd
列表中),该值就会很好地插入到数据库中。
我错过了什么吗?我没有正确关闭ResultSet和PreparedStatement吗?也许是我看得太久而看不到自己的错误。
编辑:在单独的线程中执行选择也可以达到目的。但这并不是解决办法。在关闭之前的语句后,我是否试图太快地插入数据库?
Edit2:我遇到了 busy_timeout,它 promise 让更新/查询在返回 SQLITE_BUSY 之前等待指定的时间。我尝试像这样设置繁忙超时:
if(jdbcConn.prepareStatement("PRAGMA busy_timeout = 30000").execute()) {
jdbcConn.commit();
}
executeUpdate()
函数仍然立即返回 SQLITE_BUSY。
最佳答案
我傻了。 删除 select 语句有效(仍然不确定为什么有效,可能是时机不好)这一事实让我感到非常困惑,以至于我错过了使用同一文件的不同线程。
使两个线程使用相同的 java.sql.Connection,现在一切正常。
感谢您将我推向正确的方向@GordThompson。不知道导致我发现问题的 jdbc:sqlite::memory:
选项。
关于SQLite 通过 JDBC : SQLITE_BUSY when inserting after selecting,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54513666/