Android 安卓&;SQLite-偶然错误';由于未完成的报表';
我似乎经常在代码的(插入量很大的)部分遇到上述错误。我知道这通常意味着连接中有一个打开的游标,但我已经检查了所有游标是否在try finally块中并已关闭。 同样在logcat中,错误读取'sqlite3_close(…)failed:5,我认为这意味着数据库正忙 如果我在数据库连接关闭的finally块中添加以下代码,则可以“忽略”该错误Android 安卓&;SQLite-偶然错误';由于未完成的报表';,android,sqlite,Android,Sqlite,我似乎经常在代码的(插入量很大的)部分遇到上述错误。我知道这通常意味着连接中有一个打开的游标,但我已经检查了所有游标是否在try finally块中并已关闭。 同样在logcat中,错误读取'sqlite3_close(…)failed:5,我认为这意味着数据库正忙 如果我在数据库连接关闭的finally块中添加以下代码,则可以“忽略”该错误 finally { writer.endTransaction(); boolean successAtClose = false
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次,并且只在其中一次抛出错误。此外,错误不会在发生一次后立即再次发生,而是以随机间隔继续弹出
有人知道为什么会发生这种情况吗?还是比上面的最终代码更好的恢复方法?(因为我需要很长时间才能将其添加到所有数据库代码中。)
增加:
数据库是用一个自定义的SQLiteOpenHelper
打开的,这个自定义的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);
}
作为进一步的测试,我进一步添加了对finally代码的
Thread.sleep()
调用(在我的例子中是12秒),在close()
之前,但在endTransaction()
之后,它似乎已经停止了错误,并确认这不是一个打开的游标,但我宁愿不依赖计时器。如果有更好的方法,可能是预先检查数据库是否忙,请共享。这主要发生在您未关闭光标时,意味着对数据库的某些引用无效
请参阅此链接,解决方法不正确
close()
递减参考计数器,只有当计数器正好达到零时,才是实际的资源处置,即sqlite3\u close()
尝试。在第二次呼叫时,计数器将为负值,呼叫将为禁止操作
错误代码5是SQLITE\u BUSY
,这是正确的
现在,为了解决实际问题,请提供一些其他详细信息,例如如何打开和配置数据库以及如何开始事务。如果使用SQLiteStatement或SQLiteQuery对象处理数据库,则需要确保它们也被关闭。如果它是SQLiteClosable,您需要关闭它。正如我所说,我已经检查过了。如果是这样的话,不是每次代码运行时都会发生吗?上面的循环不会永远退出吗?我已经添加了更多的细节,但我认为我没有做任何特别的事情。你是说解决方案是错误的,因为即使第二次没有抛出异常,它仍然没有关闭?@user2145222解决方案中的
while
循环是无用的。不会引发异常,因为引用计数不完全为零,并且根本不会调用将引发异常的代码。更新后的问题代码中没有明显的错误,但您可以显示getDatabaseAccess()
中的内容。添加了,但这只是设置了锁的基本代码(我也为上面的代码添加了释放锁调用,类似地,这只调用unlock())。如上所述,我在close()之前添加了一个thread.sleep错误也消失了。我猜我所做的插入次数意味着在调用close()时endTransaction()还没有完成。我已经做了更多的测试。我将坏while循环“fix”更改为while(writer.isOpen())。根据您在.close()中所说的幕后操作,我假设这将是无休止的循环(因为close失败一次后,它将永远不会再次运行,这意味着isOpen始终为true),或者它将运行一次(因为尽管失败,调用close仍会将此标志设置为false/closed),但与以前一样,它在第二次迭代中出现“忙”错误时退出。这是否意味着,如果关闭失败,因为它很忙,它会自己尽快关闭?毕竟,我很惭愧地说,一旦我经历了这一切,并把所有的东西都放在try finally块中,问题已经解决了。无论是什么样的声明被错过了,现在都在呼唤。我猜如果它看起来像只鸭子,嘎嘎叫起来像只鸭子……@user2145222我自己也去过那里。