我有一个只读数据库连接。有时,当使用SELECT
查询从数据库中读取数据时,会抛出SQLiteReadOnlyDatabaseException
。
我打开这样的连接:
return SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
查询是:
Select * FROM BudgetVersions WHERE entityId = ?
我使用db.rawQuery()
从数据库中读取数据,如下所示:
String query = ...;
Cursor c = db.rawQuery(query, new String[]{ activeBudgetId });
try {
if (c.moveToFirst()) {
bv.versionName = c.getString(c.getColumnIndexOrThrow("versionName"));
return bv;
} else {
return null;
}
} finally {
c.close();
}
很少,我在c.moveToFirst()
的调用中遇到了这样的崩溃:
Caused by: android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 776)
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:845)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:144)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:133)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:197)
at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:237)
作为一种解决方法,我可以尝试使用可写数据库连接,但我想知道崩溃发生的原因。
我读的表是一个标准的SQLite表:
CREATE TABLE BudgetVersions (
entityId VARCHAR PRIMARY KEY NOT NULL UNIQUE,
budgetId VARCHAR NOT NULL,
versionName VARCHAR NOT NULL,
dateFormat VARCHAR,
currencyFormat VARCHAR,
lastAccessedOn DATETIME,
isTombstone BOOL NOT NULL,
deviceKnowledge NUMERIC NOT NULL
);
我发现KitKat仿真器和运行Lollipop的设备都发生了崩溃。
单独的可写连接打开到同一个数据库同时,由WebView拥有。数据库正在通过WebView中的Javascript代码进行更新,并使用此只读连接从本机Android / Java层中读取。
我希望这可能是问题的最终原因,但我想详细了解为什么只读连接会干扰单独的可写连接。
我很清楚,一般的建议是使用与数据库的单一连接,但由于可写连接由WebView
拥有,因此我无法从Java轻松访问它代码。
答案 0 :(得分:16)
通过将其更改为可写数据库连接来解决。线索在documentation for the 776 error code:
(776)SQLITE_READONLY_ROLLBACK
SQLITE_READONLY_ROLLBACK错误代码是一个扩展错误代码 SQLITE_READONLY。 SQLITE_READONLY_ROLLBACK错误代码表示 数据库无法打开,因为它有一个热门日志 需要回滚但不能,因为数据库是只读的。
在开发过程中,我经常打断当前正在运行的应用程序以安装和运行新版本。这会导致当前正在运行的应用程序被系统强制停止。如果WebView中的Javascript代码在应用程序被破解时通过其单独的可写连接写入数据库,那么hot journal将被遗忘。
当新版本的应用程序启动时,将打开本机Java代码中的只读数据库连接。当此连接发现日志时,它会尝试回滚期刊。因为它是只读连接,所以它失败了。
(这适用于我做出改变后在启动时立即观察到的崩溃。)
因此,正确的修复是使Java连接成为可写连接。此连接在正常操作期间从不尝试写入,但必须在通过WebView的可写连接从先前中断的写入中恢复时进行写入。