在从表中进行选择后,尝试写入表时,我得到错误代码SQLITE_BUSY。select语句和结果在insert之前已正确关闭。
如果我删除了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吗?也许我对自己的错误视而不见,因为我看了太久。
编辑:在单独的线程中执行select也能起到作用。但这不可能是解决之道。在关闭前面的语句后,我是否试图过快地插入到数据库中?
Edit2:我遇到了一个busy_timeout,它承诺让更新/查询在返回SQLITE_BUSY之前等待一段指定的时间。我尝试这样设置忙碌超时:
if(jdbcConn.prepareStatement("PRAGMA busy_timeout = 30000").execute()) {
jdbcConn.commit();
}executeUpdate()函数仍然会立即返回SQLITE_BUSY。
发布于 2019-02-05 17:29:50
我是个笨蛋。删除select语句起作用了(仍然不确定为什么起作用,可能时机不对),以至于我错过了使用同一文件的不同线程。
使两个线程使用相同的java.sql.Connection,现在一切都正常了。
感谢您将我推向正确的方向@GordThompson。我没有意识到jdbc:sqlite::memory:选项导致我找到了问题。
https://stackoverflow.com/questions/54513666
复制相似问题