Режим миграции базы данных журнала из DELETE в WAL - PullRequest
1 голос
/ 27 июня 2019

Я предлагаю некоторую функцию экспорта / импорта внутри моего приложения, и теперь я вижу, что это создает проблемы, если старый экспорт импортируется в более новую версию Android, потому что на многих телефонах с Android 9 или выше базы данных SQLite используютjournal_mode WAL вместо DELETE, которое они использовали на старых телефонах.

Информация / наблюдения:

  • Я НЕ установил журнал вручнуюрежим внутри моего приложения (например, внутри SQLiteOpenHelper)
  • не во всех телефонах Android 9 эта функция включена (мой S9 под управлением PIE по-прежнему использует режим DELETE), поэтому восстановление старых резервных копий на моем телефоне работает отлично
  • на телефонах, не использующих режим DELETE, восстановленное резервное копирование приводит к сбою моего приложения, поскольку база данных кажется пустой для моего приложения - о которой я не позабочусь.Конечно, забота о пустой базе данных не решает проблему, так как мне нужны импортированные данные ...

Вопросы:

Выше приведено следующее3 вопроса:

  • как я могу узнать, использует ли текущий телефон WAL или DELETE по умолчанию?
  • , как я могу узнать режим данного *.db файл?
  • как я могу изменить этот режим для данного *.db файла?

Чего я не хочу

Я не хочу полностью отключать WAL внутри своего приложения, я предпочитаю какое-то решение на основе миграции

1 Ответ

2 голосов
/ 27 июня 2019

как узнать, использует ли текущий телефон режим WAL или DELETE по умолчанию?

Если устройство использует Android 9+, то при правильной реализации оно должно по умолчанию переходить в режим WAL. Однако поставщики устройств могут предоставлять пользовательские / устаревшие реализации. Таким образом, вам необходимо проверить, как показано / ответ ниже (на самом деле, используя метод ниже, нет необходимости проверять).

Причина сбоя, вероятно, заключается в том, что вы не создаете резервные копии дополнительных файлов -wal и -shm, которые существуют, когда активен режим WAL.

Я использую приведенный ниже код перед созданием резервной копии

  • очевидно DBConstants.DBNAME - это имя базы данных
  • и база данных хранится в расположении по умолчанию ( data / data / the_package / database / ))

: -

private void checkpointIfWALEnabled(Context context) {
    final String TAG = "WALCHKPNT";
    Cursor csr;
    int wal_busy = -99, wal_log = -99, wal_checkpointed = -99;
    SQLiteDatabase db = SQLiteDatabase.openDatabase(context.getDatabasePath(DBConstants.DATABASE_NAME).getPath(),null,SQLiteDatabase.OPEN_READWRITE);
    csr = db.rawQuery("PRAGMA journal_mode",null);
    if (csr.moveToFirst()) {
        String mode = csr.getString(0);
        //Log.d(TAG, "Mode is " + mode);
        if (mode.toLowerCase().equals("wal")) {
            csr = db.rawQuery("PRAGMA wal_checkpoint",null);
            if (csr.moveToFirst()) {
                wal_busy = csr.getInt(0);
                wal_log = csr.getInt(1);
                wal_checkpointed = csr.getInt(2);
            }
            //Log.d(TAG,"Checkpoint pre checkpointing Busy = " + String.valueOf(wal_busy) + " LOG = " + String.valueOf(wal_log) + " CHECKPOINTED = " + String.valueOf(wal_checkpointed) );
            csr = db.rawQuery("PRAGMA wal_checkpoint(TRUNCATE)",null);
            csr.getCount();
            csr = db.rawQuery("PRAGMA wal_checkpoint",null);
            if (csr.moveToFirst()) {
                wal_busy = csr.getInt(0);
                wal_log = csr.getInt(1);
                wal_checkpointed = csr.getInt(2);
            }
            //Log.d(TAG,"Checkpoint post checkpointing Busy = " + String.valueOf(wal_busy) + " LOG = " + String.valueOf(wal_log) + " CHECKPOINTED = " + String.valueOf(wal_checkpointed) );
        }
    }
    csr.close();
    db.close();
}

Это работает в любом случае, поскольку эффективно устраняет файлы -wal и -shm (очищает их) путем проверки контрольной точки базы данных. Таким образом, нет необходимости копировать файлы -wal и -shm , если нет ожидающих транзакций, которые необходимо зафиксировать. Работает в любом режиме.

как узнать режим данного * .db файла?

Строка csr = db.rawQuery("PRAGMA journal_mode",null); - это строка, которая опрашивает режим журнала, также есть метод SQLiteDatabase isWriteAheadLoggingEnabled , который возвращает true или false.

В отношении: -

как я могу изменить этот режим для данного * .db файла?

Если вы используете Android SDK, вы можете использовать метод SQLiteDatabase enableWriteAheadLogging или disableWriteAheadLogging , или вы можете установить его, используя journal_mode pragma , НО отмечая ограничения относительно того, когда это может быть предпринято. Запись с записью впереди

...