Я предлагаю некоторую функцию экспорта/импорта внутри своего приложения, и теперь я вижу, что это создает проблемы, если старый экспорт импортируется в более новую версию Android, потому что на многих телефонах с Android 9 или выше SQLite базы данных используют journal_modeWAL вместо DELETE который они использовали на старых телефонах.
Информация/наблюдения:
SQLiteOpenHelper)DELETE), поэтому восстановление старых резервных копий на моем телефоне работает отлично.DELETE, восстановленная резервная копия приводит к сбою моего приложения, потому что база данных кажется пустой для моего приложения, что меня не волнует. f конечно, забота о пустой базе данных не решает проблему, так как мне нужны импортированные данные...Вопросы:
Выше приводит к следующим 3 вопросам:
WAL или DELETE по умолчанию?*.db файла?*.db файла?Чего я не хочу
Я не хочу полностью отключать WAL внутри своего приложения, я предпочитаю решение на основе миграции.
how can I find out if the current phone uses WAL or DELETE by default?
Если устройство использует Android 9+, то при правильной реализации оно должно по умолчанию работать в режиме WAL. Однако поставщики устройств могут предоставлять собственные/устаревшие реализации. Таким образом, вам нужно будет проверить, как показано/отвечено ниже (на самом деле, используя приведенный ниже метод, нет необходимости проверять).
Причина сбоя, вероятно, заключается в том, что вы не создаете резервные копии дополнительных файлов -wal и -shm, которые существуют, когда активен режим WAL.
Я использую приведенный ниже код перед тем, как сделать резервную копию
:-
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();
}
Это работает в любом случае, так как эффективно удаляет файлы -вал и -шм (очищает их) путем создания контрольных точек в базе данных. Таким образом, нет необходимости копировать файлы -вал и -шм, если нет незавершенных транзакций, которые необходимо зафиксировать. Он работает для любого режима.
how can I find out the mode of a given *.db file?
Строка csr = db.rawQuery("PRAGMA journal_mode",null); — это строка, которая опрашивает режим журнала, также есть метод SQLiteDatabase isWriteAheadLoggingEnabled, который возвращает true или false.
В отношении :-
how can I change this mode for a given *.db file?
Если вы используете Android SDK, вы можете использовать метод SQLiteDatabase включитьWriteAheadLogging или отключитьWriteAheadLogging, или вы можете установить его с помощью Прагма журнал_режим, НО принимая во внимание ограничения относительно того, когда это может быть выполнено. Ведение журнала с опережающей записью
@ prom85, да, это звучит правильно. Обратите внимание, что приведенный выше код предполагает, что соединение dbHelper было закрыто (в любом случае закрытие должно зафиксировать / контрольная точка).
после перезапуска приложения оно точно закрывается, так что большое спасибо за очень полезную помощь
Если я решу отключить режим WAL во всех версиях Android, все, что мне нужно сделать, это следующее: 1) в моей следующей версии приложения я удостоверюсь, что моя база данных еще не открыта, чтобы код не обращался к базе данных 2) я выполняю дольше блок кода, который вы разместили выше, это гарантирует, что все изменения будут записаны в файл базы данных. 3) Я открываю свою базу данных с помощью моего
SQLiteOpenHelper, как всегда, и вызываюdisableWriteAheadLoggingв нем, когда я настраиваю базу данных. Это должно быть сохранено для всех устройств и убедиться, что все устройства используют старый режим журнала, верно?