0

在这些启用了 WAL(预写日志记录)的少数 Android 设备上,我在数据库备份/恢复方面确实存在很多问题。创建这样的数据库后是否可以将其关闭?

我的想法是:

1.) 使此工作在较旧的 Android 设备上运行的包装器:

public class SQLiteDatabaseWalWrapper {

    private boolean        available;
    private Method         disableWriteAheadLogging;
    private Method         enableWriteAheadLogging;
    private Method         isWriteAheadLoggingEnabled;
    private SQLiteDatabase sqliteDatabase;

    public SQLiteDatabaseWalWrapper(final SQLiteDatabase sqliteDatabase) {
        this.sqliteDatabase = sqliteDatabase;

        available = false;

        try {
            disableWriteAheadLogging = SQLiteDatabase.class.getMethod("disableWriteAheadLogging");
            enableWriteAheadLogging = SQLiteDatabase.class.getMethod("enableWriteAheadLogging");
            isWriteAheadLoggingEnabled = SQLiteDatabase.class.getMethod("isWriteAheadLoggingEnabled");

            available = true;
        } catch (NoSuchMethodException noSuchMethodException) {
        }
    }

    public boolean checkAvailable() {
        return available;
    }

    public void disableWriteAheadLogging() {
        if (disableWriteAheadLogging != null) {
            try {
                disableWriteAheadLogging.invoke(sqliteDatabase);
            } catch (IllegalAccessException illegalAccessException) {
            } catch (IllegalArgumentException illegalArgumentException) {
            } catch (InvocationTargetException invocationTargetException) {
            }
        }
    }

    public boolean enableWriteAheadLogging() {
        boolean result = false;

        if (enableWriteAheadLogging != null) {
            try {
                result = (Boolean) enableWriteAheadLogging.invoke(sqliteDatabase);
            } catch (IllegalAccessException illegalAccessException) {
            } catch (IllegalArgumentException illegalArgumentException) {
            } catch (InvocationTargetException invocationTargetException) {
            }
        }

        return result;
    }

    public boolean isWriteAheadLoggingEnabled() {
        boolean result = false;

        if (isWriteAheadLoggingEnabled != null) {
            try {
                result = (Boolean) isWriteAheadLoggingEnabled.invoke(sqliteDatabase);
            } catch (IllegalAccessException illegalAccessException) {
            } catch (IllegalArgumentException illegalArgumentException) {
            } catch (InvocationTargetException invocationTargetException) {
            }
        }

        return result;
    }
}

2.)在带有 AsyncTask 的扩展应用程序中,我将发出一个完整的检查点并关闭 WAL:

public class MyApplication extends Application {

    private class MyAsyncTask extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected Boolean doInBackground(final Void... voids) {
            // Make a full checkpoint
            sqliteDatabase.execSQL("PRAGMA wal_checkpoint(FULL);");

            // switch WAL off
            sqliteDatabaseWalWrapper.disableWriteAheadLogging();
        }

        @Override
        protected void onPostExecute(final Boolean result) {
        }
    }

    private Context                  context;
    private SQLiteDatabase           sqliteDatabase;
    private SQLiteDatabaseWalWrapper sqliteDatabaseWalWrapper;
    private MySQLiteOpenHelper       sqliteOpenHelper;
    private MyAsyncTask              task;

    @Override
    public void onCreate() {
        super.onCreate();

        context = getApplicationContext();

        sqliteOpenHelper = new MySQLiteOpenHelper(context);
        if (sqliteOpenHelper != null) {
            sqliteDatabase = sqliteOpenHelper.getWritableDatabase();
            if (sqliteDatabase != null) {

                if (Build.VERSION.SDK_INT >= 16) {
                    sqliteDatabaseWalWrapper = new SQLiteDatabaseWalWrapper(sqliteDatabase);
                    if (sqliteDatabaseWalWrapper != null && sqliteDatabaseWalWrapper.checkAvailable() && sqliteDatabaseWalWrapper.isWriteAheadLoggingEnabled()) {
                        task = new MyAsyncTask();
                        task.execute();
                    }
                }
            }
        }
    }

    @Override
    public void onTerminate() {
        if (sqliteDatabase != null) {
            sqliteDatabase.close();
        }

        if (sqliteOpenHelper != null) {
            sqliteOpenHelper.close();
        }

        super.onTerminate();
    }
}

这行得通吗?这会删除 SQLite 在启用 WAL 的数据库上创建的各种附加文件吗?这会导致返回到 Android 文档中描述的单个数据库文件吗?

4

3 回答 3

3

您可以通过这行代码将数据库模式更改为 TRUNCATE mote:

setJournalMode(RoomDatabase.JournalMode.TRUNCATE)

于 2019-10-29T03:38:04.457 回答
1

在数据库上执行PRAGMA journal_mode=DELETE应该移除 Wal 模式并返回到正常的操作方法。

完整文档在这里:http ://www.sqlite.org/wal.html

于 2013-01-29T11:04:51.987 回答
0

我们可以通过编程方式启用和禁用 WAL 模式。它从 API 级别 11 开始就存在

有关更多信息,请参阅此文档

http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#enableWriteAheadLogging()

于 2013-10-12T12:10:48.303 回答