Отключение ведения журнала sqlite с опережающей записью в Android Pie

В Android Pie sqlite ведение журнала с опережающей записью (WAL) включено по умолчанию. Это вызывает ошибки для моего существующего кода только на устройствах Pie. Мне не удалось успешно отключить WAL с помощью SQLiteDatabase.disableWriteAheadLogging() или PRAGMA journal_mode из-за способа доступа к базе данных. Я хотел бы полностью отключить WAL с помощью параметра Android под названием db_compatibility_wal_supported:

Совместимость WAL (ведение журнала с опережающей записью) для приложений

Кто-нибудь знает, как это настроить? Я не знаю, можно ли изменить этот файл программно при запуске или его можно изменить вручную.


Дополнительные сведения о проблеме

У меня есть база данных sqlite (20 МБ+/250 тыс. записей) в моем приложении. Эта база данных создается с использованием простой Java на моем сервере. Он содержит базу данных продуктов питания, и пользователь приложения может добавлять в базу данных (и сервер обновляется). Это хранится в папке активов в android. Во время первой установки база данных копируется из ресурсов в папку приложения, чтобы в нее можно было записать, эффективно используя этот метод:

Копировать базу данных SQLite из папки с ресурсами

К сожалению, как только я начинаю писать в базу данных с помощью SqlDroid, wal включается, и таблицы, которые были в исходной базе данных, исчезают, и остаются только вновь созданные таблицы. Однако размер базы данных по-прежнему составляет 20 МБ+. Все ошибки базы данных связаны с отсутствующими таблицами. Метод копирования и записи таблицы отлично работает в версиях Android до Pie.


person Rockvole    schedule 06.12.2018    source источник
comment
Какого черта вы делаете, что WAL вызывает ошибки?   -  person Shawn    schedule 06.12.2018
comment
Если вы используете подкласс SQLiteOpenHelper, попробуйте переопределить метод onConfigure и ввести прагму в этом методе.   -  person MikeT    schedule 07.12.2018
comment
Я подключаюсь к своей базе данных с помощью SQLDroid, так как использую один и тот же код доступа к базе данных в своем приложении и на своем сервере. connection = new org.sqldroid.SQLDroidDriver().connect()   -  person Rockvole    schedule 07.12.2018
comment
Связанный? stackoverflow.com/questions/43244091/ если вы можете использовать права root..   -  person KYHSGeekCode    schedule 09.12.2018


Ответы (5)


Лучший и самый простой способ отключить режим WAL в вашей базе данных:

public class MyDbHelper extends SQLiteOpenHelper {

    //...

    @Override
    public void onOpen(SQLiteDatabase db) {
        db.disableWriteAheadLogging();  // Here the solution
        super.onOpen(db);
    }

    //...
}

Таким образом, весь доступ к вашей базе данных будет осуществляться с отключенным режимом WAL. Столько, сколько вы открываете и закрываете несколько соединений во время реализации вашего приложения.

person Carlos Henrique    schedule 23.02.2019
comment
Я согласен, что этот ответ лучше всего подходит для вопроса. При этом я бы также обновил метод onCreate в вашем вспомогательном классе базы данных, чтобы также отключить там ведение журнала с опережающей записью: db.disableWriteAheadLogging(); - person shagberg; 03.05.2019
comment
Как насчет ORM (например, Room), где база данных не отображается напрямую? - person Prof; 11.08.2019
comment
используя метод db.disableWriteAheadLogging(), мы можем избежать ошибки «Нет такой таблицы», но теперь мы не можем обновить ни один столбец в БД при использовании версии Pie (9). ПРИМЕЧАНИЕ. Он отлично работает в Marshmallow (6), я могу записать изменения в БД здесь, пожалуйста, предложите мне, как записать изменения в БД в версии Pie. - person Annie; 18.06.2020

нельзя использовать SQLDroidDriver.ADDITONAL_DATABASE_FLAGS просто потому, что нет доступной константы , что отменяет флаг ENABLE_WRITE_AHEAD_LOGGING.

WAL по-прежнему можно отключить, создав любой из этих сценариев:

а) установить флаг OPEN_READONLY (применяется к ситуациям, когда R/O доступа достаточно).

б) запустить PRAGMA journal_mode=DELETE в качестве первого запроса, чтобы переопределить PRAGMA journal_mode=WAL.

c) подать заявку на SQLDroidConnection. java, чтобы .enableWriteAheadLogging() и .disableWriteAheadLogging() поддерживались на уровне драйвера.

person Martin Zeitler    schedule 13.12.2018
comment
Из обширного чтения я не верю, что на самом деле возможно изменить настройку стены так, как я просил в своем вопросе. В некоторых версиях Android была доступна функция наложения ресурсов времени выполнения Sony, но я не могу подтвердить, что она возможна даже в Pie. - person Rockvole; 15.12.2018
comment
Другая возможность, которую я нашел, заключалась в наложении значений в config.xml, но это будет работать только в пользовательской сборке Android: stackoverflow.com/questions/49249703/ - person Rockvole; 15.12.2018
comment
опция a помогла с комбинацией onConfigure(). +1 - person Alok Vishwakarma; 24.05.2020

@Rockvole, пожалуйста, поделитесь ошибкой, с которой вы столкнулись, это поможет нам найти подходящее решение.

Между тем, я понимаю, что вы хотите закрыть этот WAL в круговой диаграмме Android, и вы используете библиотеку «SQLDroid» для создания базы данных Sqlite.

Эта библиотека внутренне использует "SQLiteDatabase" для локального хранения данных, я думаю, вам нужно вызвать "SQLiteDatabase.disableWriteAheadLogging()" в "SQLiteDatabase" class, в котором экземпляр БД создал пакет с именем "package org.sqldroid;"

или Получите внутренний экземпляр SQLiteDatabase и вызовите disableWriteAheadLogging().

Второе решение - создать "config.xml" внутри папки значений и запустить "<bool name="db_compatibility_wal_supported">false</bool>", запустить и проверить его работу.

person Parkash    schedule 09.12.2018
comment
Во время инициализации sqlite в моем приложении я использую стандартные инструкции SQLiteDatabase. Там я могу отключить WAL в порядке - он работает, и я это проверял. К сожалению, отключение WAL таким образом не является липким. Поэтому, когда я делаю дальнейшие команды базы данных в sqldroid, WAL снова включается. - person Rockvole; 10.12.2018
comment
Если я отключу WAL в SQLDroid с помощью PRAGMA, будет слишком поздно, потому что WAL уже был включен до того, как я выполню PRAGMA. Я считаю, что для правильной работы потребуется метод disableWriteAheadLogging() в SQLDroid. - person Rockvole; 10.12.2018
comment
Я попытался добавить config.xml в каталог значений с db_compatibility_wal_supported, установленным в false, и это ничего не дало. - person Rockvole; 11.12.2018

Если вы используете Room, у вас не будет прямого доступа к базе данных, но вместо этого вы можете установить режим журнала при создании/открытии базы данных:

db = Room.databaseBuilder(context, Database.class, "Database")
         .setJournalMode(JournalMode.TRUNCATE)
         .build();
person Prof    schedule 10.08.2019
comment
Является ли усечение тем же, что и отключение ведения журнала с опережающей записью? - person mliu; 25.11.2020

Я наконец нашел ответ. Кажется, что ошибки базы данных, которые я получал, не имели прямого отношения к WAL. Это связано с тем, что в широко используемом коде для копирования базы данных из активов есть ошибка, из-за которой база данных остается открытой во время операции копирования. Это только начало вызывать проблему в Android P. Решение состоит в том, чтобы закрыть базу данных после того, как вы получите имя файла базы данных.

SQLiteDatabase destinationDatabase = sqLiteOpenHelper.getWritableDatabase();
String dbFileName=destinationDatabase.getPath();
destinationDatabase.close();
// Now write the destinationDatabase using the dbFileName

Подробнее об этом читайте здесь: Android P - "SQLite: нет такой ошибки таблицы" после копирования базы данных из активов

person Rockvole    schedule 13.12.2018
comment
этот ответ просто не соответствует вопросу, вообще. meta.stackexchange.com/questions/ 16065/ - person Martin Zeitler; 15.12.2018
comment
Я понимаю, что если вы просмотрите другие связанные ответы, вы увидите, что для некоторых людей виновником является стена. В моем случае это был отвлекающий маневр, поскольку включение wal было серьезным изменением в Android Pie, в то же время было внесено изменение в способ, которым файлы базы данных остаются открытыми. - person Rockvole; 15.12.2018
comment
ну, это может быть связано с эксклюзивным доступом к файлу при открытии файла в режиме R/W - флаг OPEN_READONLY все еще может изменить поведение, особенно когда в данной ситуации требуется только доступ R/O. даже если правильный вызов .close() имеет тот же эффект, вопрос не содержит никакого кода, поэтому обнаружить проблему было совершенно невозможно. - person Martin Zeitler; 15.12.2018