我的代码中有一个例外。
10-10 22:05:33.866 5725 5725 E AndroidRuntime: Caused by: net.sqlcipher.database.SQLiteDiskIOException: error code 10: disk I/O error
10-10 22:05:33.866 5725 5725 E AndroidRuntime: at net.sqlcipher.database.SQLiteStatement.native_execute(Native Method)
10-10 22:05:33.866 5725 5725 E AndroidRuntime: at net.sqlcipher.database.SQLiteStatement.execute(SQLiteStatement.java:58)
10-10 22:05:33.866 5725 5725 E AndroidRuntime: at net.sqlcipher.database.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:2074)
这只发生过一次(到目前为止)成千上万次成功插入和选择,所以我怀疑在尝试访问同一个数据库的同一进程中不同线程之间存在某种竞争条件。
实际代码并不重要,这只是新记录的简单插入,并且on conflict参数表示忽略任何冲突:
ContentValues values = new ContentValues();
// values.put(); calls go here, nothing strange about the data
db.insertWithOnConflict("Sample", null, values, SQLiteDatabase.CONFLICT_IGNORE);
从架构上讲,我的服务中有一个单独的对象,它封装了一个连续打开的数据库连接,并且前面有一个缓存。多个线程从服务中的不同位置调用对象以插入数据,这些通常是记录诸如GPS位置,电池状态等内容的侦听器。读取通常来自缓存而不会访问数据库。
我的第一个想法是,也许我需要同步数据库访问流的类(它闻起来像两个不同的线程可能试图在几乎完全相同的时间插入,实际上很少会发生),但是{{ 3}}似乎在说我应该能够毫无问题地做到这一点。 "插入,更新,删除和读取通常可以来自多个线程"值得注意的是,异常表示" I / O错误"没有"数据库被锁定"。
更新:我添加了logcat跟踪和异常捕获每个数据库访问。之后我还有两个例外。在这两种情况下,只有一个数据库访问正在进行中。两者都是简单的插入。第一个在插入开始后1.2秒抛出异常,这看起来令人难以置信地高。第二个只花了38毫秒,看起来很平均。
问题是存储空间不足:我有27GB的免费空间。我很难相信这也是闪存的一个问题,因为我没有看到写入它的任何其他错误。我还没有看到任何类似的问题,使用相同的SQLCipher库但在每次插入后关闭数据库的旧应用程序。
更新2:在异常处理程序中,我添加了代码以立即重试插入,到目前为止,我还没有收到第二个异常:
try {
ret = db.insertWithOnConflict("Sample", null, values, SQLiteDatabase.CONFLICT_IGNORE);
} catch (Exception e) {
Log.d(logtag,"exception:"+e);
try {
ret = db.insertWithOnConflict("Sample", null, values, SQLiteDatabase.CONFLICT_IGNORE);
} catch (Exception e1) {
Log.d(logtag,"exception2:"+e1);
}
return 0;
}