我似乎经常在我的代码的(插入重的)部分中遇到上述错误。我通常知道这意味着连接中有一个打开的光标,但我已经检查了我所有的光标都在 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()
,这似乎已经停止了错误并确认它不是打开光标的情况,但我宁愿不依赖计时器。如果有更好的方法,或许可以预先检查数据库是否繁忙,请分享。