【问题标题】:Is it possible to disable WAL on Android SQLite database?是否可以在 Android SQLite 数据库上禁用 WAL?
【发布时间】:2012-08-10 12:14:03
【问题描述】:

在这几款启用了 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 文档中描述的单个数据库文件吗?

【问题讨论】:

    标签: android sqlite


    【解决方案1】:

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

    setJournalMode(RoomDatabase.JournalMode.TRUNCATE)

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

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

        请参阅此文档了解更多信息

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

        【讨论】:

          猜你喜欢
          • 2021-11-13
          • 1970-01-01
          • 1970-01-01
          • 2012-10-22
          • 1970-01-01
          • 2017-01-09
          • 1970-01-01
          • 1970-01-01
          • 2014-02-10
          相关资源
          最近更新 更多