0

我似乎经常在我的代码的(插入重的)部分中遇到上述错误。我通常知道这意味着连接中有一个打开的光标,但我已经检查了我所有的光标都在 try finally 块中并关闭。同样在 logcat 中,错误显示为 'sqlite3_close(...) failed: 5 我认为这意味着数据库很忙?

如果我将以下代码添加到关闭数据库连接的 finally 块中,则可以“忽略”该错误。

  finally
  {
    writer.endTransaction();
    boolean successAtClose = false;
    while(successAtClose == false)
    {
      try
      {
        writer.close();
        successAtClose = true;
      }
      catch(Exception e)
      {
        e.printStackTrace();
      }
    }
    dbConn.releaseLock();
  }

当单步执行上面的代码时,'e.printStackTrace()' 被击中一次,但在第二次尝试时,'writer.close()' 不会引发错误。

重申一下,这个问题甚至不会在每次代码块运行时发生,相同的数据可以插入 5/6 次,并且只会在其中一次抛出错误。此外,错误不会在发生一次后立即再次发生,而是会继续以随机间隔弹出。

有谁知道为什么会发生这种情况?还是比上面的 finally 代码更好的方法来恢复?(因为我需要很长时间才能将它添加到我所有的数据库代码中。)

添加:

使用自定义打开数据库,该自定义SQLiteOpenHelper扩展为使用可重入锁以确保在任何时候只有一个线程访问数据库。所以代码的开头是这样的:

  MyDatabaseHelper dbConn = MyDatabaseHelper.getDatabaseAccess(c);//await availability/lock the database here
  SQLiteDatabase writer = dbConn.getWritableDatabase();     
    try
    {       
        writer.beginTransaction();

        //do inserts

        writer.setTransactionSuccessful();

获取数据库访问权限如下:

  public static MyDatabaseHelper getDatabaseAccess(Context c)
  {      
    l.lock();       
    return new MyDatabaseHelper(c);
  }

作为进一步的测试,我进一步添加了Thread.sleep()对 finally 代码的调用(在我的情况下为 12 秒),在 之前close()但之后endTransaction(),这似乎已经停止了错误并确认它不是打开光标的情况,但我宁愿不依赖计时器。如果有更好的方法,或许可以预先检查数据库是否繁忙,请分享。

4

3 回答 3

1

如果您使用 SQLiteStatement 或 SQLiteQuery 对象来处理您的数据库,您需要确保它们也被关闭。如果它是 SQLiteClosable 你需要关闭它。

于 2013-10-29T17:27:52.807 回答
0

这主要发生在您没有关闭游标时,这意味着对数据库的某些引用无效。

请参阅链接 Android SQLite 异常:由于未完成的语句而无法关闭

于 2013-10-28T12:50:36.340 回答
0

解决方法不正确。close()递减一个引用计数器,并且只有当计数器恰好达到零时,才会sqlite3_close()尝试实际的资源处理。在第二次调用时,计数器将为负数,调用将是空操作。

您是正确的,错误代码 5 是SQLITE_BUSY.

现在为了解决实际问题,请提供一些额外的细节,例如您如何打开和配置数据库以及如何开始您的事务。

于 2013-10-28T13:32:08.770 回答