Подтвердить что ты не робот

Попытка написать базу данных только для чтения... но я не

У меня есть соединение с базой данных только для чтения. Иногда при чтении данных из базы данных с запросом 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. База данных обновляется с помощью кода Javascript в WebView и читается на собственном уровне Android/Java с помощью этого подключения только для чтения.

Я ожидаю, что это может стать основной причиной проблемы, но я хотел бы подробно понять, почему соединение только для чтения будет мешать отдельному записываемому соединению.

Мне хорошо известно, что общий совет - использовать одно соединение с базой данных, но поскольку доступное для записи соединение принадлежит WebView, у меня нет легкого доступа к нему из кода Java.

4b9b3361

Ответ 1

Решено, изменив его на доступное для записи соединение с базой данных. Ключ был в документации для кода ошибки 776:

(776) SQLITE_READONLY_ROLLBACK

Код ошибки SQLITE_READONLY_ROLLBACK - это расширенный код ошибки для SQLITE_READONLY. Код ошибки SQLITE_READONLY_ROLLBACK указывает что база данных не может быть открыта, поскольку она имеет горячий журнал, который нужно откатить, но не может, потому что база данных только для чтения.

Во время разработки я часто прерываю текущее приложение для установки и запуска новой версии. Это приводит к тому, что текущее приложение будет принудительно остановлено системой. Если код Javascript в WebView находится в середине записи в базу данных через отдельное записываемое соединение, когда приложение запущено, тогда