本文介绍了是否可以在 Android SQLite 数据库上禁用 WAL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I do have a lot of problems with database backup/restore on these few Android devices that do have WAL (write ahead logging) enabled. Is it possible to switch that off after such a database has been created?

我的想法是:

1.) 使此功能适用于旧版 Android 设备的包装器:

1.) A wrapper that makes this work on older Android devices:

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:

2.) Within an extended Application with AsyncTask I will issue a FULL checkpoint and switch WAL off:

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 文档中描述的单个数据库文件吗?

Will this work? Will this delete the various additional files that SQLite does create on WAL-enabled databases? Will this lead back to that single database file that's described in the Android docs?

推荐答案

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

You can change database mode to TRUNCATE mote by this line of code:

setJournalMode(RoomDatabase.JournalMode.TRUNCATE)

这篇关于是否可以在 Android SQLite 数据库上禁用 WAL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-04 07:26