【问题标题】:Disable WAL mode禁用 WAL 模式
【发布时间】:2020-01-28 17:24:14
【问题描述】:

我的解决方案似乎不起作用,我不知道为什么。这是我尝试的方法:

逻辑

我的应用程序有一个数据库实例,如果创建了这个实例,则执行以下操作:

  1. 获取当前数据库模式
  2. 如果当前数据库模式 == wal 模式,我将其更改为持久化
  3. 将模式更改为持久化
  4. 检查新模式是否持续
  5. 创建单个数据库实例并在应用进程存在期间重复使用它

代码

// this object holds the ONLY instance of my database and initialises it lazily!
object DBManagerImpl : IDBManager {

    val TAG = "DB-MANAGER"

    internal val database: Database by lazy {

        // 1) change db mode if necessary
        DBJournalUtil.logInfos(null)
        val mode = DBJournalUtil.getDBMode(null)
        L.tag(DBJournalUtil.TAG_WAL_MODE).d { "DB journal_mode: $mode" }
        if (mode.equals(DBJournalUtil.JOURNAL_MODE_WAL, true))
        {
            DBJournalUtil.disableWALMode()
            val mode2 = DBJournalUtil.getDBMode(null)
            L.tag(DBJournalUtil.TAG_WAL_MODE).d { "DB journal_mode - AFTER DISABLE: $mode2" }
        }

        // 2) create single database instance
        L.tag(TAG).d { "database variable created!" }
        val database = Database()

        database
    }
}

总的来说,这是主要的代码部分:

    // 1) disable the wal journal mode and change it to persist
    DBJournalUtil.disableWALMode()
    // 2) check the new journal mode => Problem: it's still WAL and not persist
    val mode2 = DBJournalUtil.getDBMode(null)

问题

看起来我的代码确实正确更改了数据库模式(基于日志第 8 行),但随后在日志第 10 行它再次报告回 wal 模式。为什么?我在这里遗漏了什么或做错了什么?

产生的日志输出

1 [[ DBJournalUtil:14 b]]: LOG 2 - journal_mode: wal

2 [[ DBManagerImpl$database:6 e]]: DB journal_mode: wal

3 [[ DBJournalUtil:23 a]]:将 DB journal_mode 从 WAL 更改为 PERSIST - current journal_mode = wal

4 [[ DBJournalUtil:35 b]]: wal_checkpoint - wal 之前 (TRUNCATE): Busy = 0, LOG = 0, CHECKPOINTED = 0

5 [[ DBJournalUtil:6 c]]:检查点(TRUNCATE):count = 1

6 [[ DBJournalUtil:35 b]]: wal_checkpoint - 之后 wal(TRUNCATE): Busy = 0, LOG = 0, CHECKPOINTED = 0

7 [[ DBJournalUtil:48 a]]: setJournalMode: count = 1

8 [[ DBJournalUtil:32 a]]:新的 journal_mode:persist //

9 [[ DBJournalUtil:42 a]]:将 DB journal_mode 从 WAL 更改为 PERSIST!

10 [[ DBManagerImpl$database:12 e]]: DB journal_mode - AFTER DISABLE: wal //

11 [[ DBManagerImpl$database:15 e]]: 数据库变量已创建!

代码 - DBJournalUtil

object DBJournalUtil {

    val TAG_WAL_MODE = "DB-WAL-MODE"

    val JOURNAL_MODE_WAL = "WAL"
    val JOURNAL_MODE_PERSIST = "PERSIST"

    val JOURNAL_MODE_DELETE = "DELETE"
    val JOURNAL_MODE_TRUNCATE = "TRUNCATE"

    fun logInfos(db: SQLiteDatabase?) {

        var csr: Cursor? = null
        var dbToUse: SQLiteDatabase? = null

        val dbName = DBManagerProvider.get().dbFileName()
        val dbFile = AppProvider.get().context.getDatabasePath(dbName)

        val logFile = { file: File ->
            val path = file.absolutePath
            val exists = file.exists()
            val size = file.length()
            L.tag(TAG_WAL_MODE).d { "LOG 1 - file: $path | exists: $exists | size: $size" }
        }

        // 1) Dateien loggen
        logFile(dbFile)
        logFile(File(dbFile.getPath() + "-wal")) // WAL Mode file
        logFile(File(dbFile.getPath() + "-shm")) // WAL Mode file

        try {
            dbToUse = db
                    ?: SQLiteDatabase.openDatabase(dbFile.path, null, SQLiteDatabase.OPEN_READWRITE)

            // 2) journal-mode loggen
            csr = dbToUse!!.rawQuery("PRAGMA journal_mode", null)
            if (csr.moveToFirst()) {
                val mode = csr.getString(0)
                L.tag(TAG_WAL_MODE).d { "LOG 2 - journal_mode: $mode" }
            }

        } catch (e: Exception) {
            L.tag(TAG_WAL_MODE).e(e)
        } finally {
            csr?.close()
            if (db == null)
                dbToUse?.close()
        }
    }

    fun getDBMode(db: SQLiteDatabase?): String? {

        var mode: String? = null
        var csr: Cursor? = null
        var dbToUse: SQLiteDatabase? = null

        val dbName = DBManagerProvider.get().dbFileName()
        val dbFile = AppProvider.get().context.getDatabasePath(dbName)

        try {
            dbToUse = db
                    ?: SQLiteDatabase.openDatabase(dbFile.path, null, SQLiteDatabase.OPEN_READWRITE)

            csr = dbToUse!!.rawQuery("PRAGMA journal_mode", null)
            if (csr.moveToFirst())
                mode = csr.getString(0)
        } catch (e: Exception) {
            L.tag(TAG_WAL_MODE).e(e)
        } finally {
            csr?.close()
            if (db == null)
                dbToUse?.close()
        }

        return mode
    }

    fun disableWALMode() {

        val modeFrom = JOURNAL_MODE_WAL
        val modeTo = JOURNAL_MODE_PERSIST

        val dbName = DBManagerProvider.get().dbFileName()
        val dbFile = AppProvider.get().context.getDatabasePath(dbName)

        var db: SQLiteDatabase? = null

        try {

            // 1) Datenbank öffnen
            db = SQLiteDatabase.openDatabase(dbFile.path, null, SQLiteDatabase.OPEN_READWRITE)

            // 2) Modus auslesen
            val mode = getDBMode(db)
            L.tag(TAG_WAL_MODE).d { "Change DB journal_mode from $modeFrom to $modeTo - current journal_mode = $mode" }

            if (mode == null || mode.equals(modeTo, true)) {
                L.tag(TAG_WAL_MODE).d { "Abbruch da aktueller journal_mode = $mode" }
            } else {

                // 3) wal_checkpoint ausführen
                walCheckpoint(db, "BEFORE wal(TRUNCATE)")

                // 4) wal_checkpoint(TRUNCATE) ausführen um pending operations in DB zu übertragen
                walTruncate(db)

                // 5) wal_checkpoint ausführen
                walCheckpoint(db, "AFTER wal(TRUNCATE)")

                // 6) journal_mode ändern
                setJournalMode(db, modeTo)

                // 7) nochmals aktuellen journal_mode holen
                val newMode = getDBMode(db)
                L.tag(TAG_WAL_MODE).d { "New journal_mode: $newMode" }
            }
        } catch (e: Exception) {
            L.tag(TAG_WAL_MODE).e(e)
        } finally {
            db?.close()
        }

        L.tag(TAG_WAL_MODE).d { "Changed DB journal_mode from $modeFrom to $modeTo!" }
    }

    private fun walCheckpoint(db: SQLiteDatabase, logTag: String) {
        var wal_busy = -99
        var wal_log = -99
        var wal_checkpointed = -99

        var csr: Cursor? = null

        try {
            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)
            }
        } catch (e: Exception) {
            L.tag(TAG_WAL_MODE).e(e)
        } finally {
            csr?.close()
        }

        L.tag(TAG_WAL_MODE).d { "wal_checkpoint - $logTag: Busy = $wal_busy, LOG = $wal_log, CHECKPOINTED = $wal_checkpointed" }
    }

    private fun walTruncate(db: SQLiteDatabase) {
        var csr: Cursor? = null
        try {
            // Checkpoint - Pending Operationen in DB überführen
            csr = db.rawQuery("PRAGMA wal_checkpoint(TRUNCATE)", null)
            val count = csr.count
            L.tag(TAG_WAL_MODE).d { "Checkpoint (TRUNCATE): count = $count" }
        } catch (e: Exception) {
            L.tag(TAG_WAL_MODE).e(e)
        } finally {
            csr?.close()
        }
    }

    private fun setJournalMode(db: SQLiteDatabase, mode: String) {
        var csr: Cursor? = null
        try {
            // Checkpoint - Pending Operationen in DB überführen
            csr = db.rawQuery("PRAGMA journal_mode=$mode", null)
            val count = csr.count
            L.tag(TAG_WAL_MODE).d { "setJournalMode: count = $count" }
        } catch (e: Exception) {
            L.tag(TAG_WAL_MODE).e(e)
        } finally {
            csr?.close()
        }
    }
}

【问题讨论】:

  • 为什么首先需要更改 WAL 模式? Sqlite 应该可以在默认的 db/wal 设置下正常工作
  • 我不“需要”它,我只是想要它。我的数据库始终加载在基于 rx 的内存结构中,因此无需启用任何数据库优化。我更喜欢简单截断模式

标签: android sqlite


【解决方案1】:

如果您查看https://sqlite.org/wal.html 的第 3.3 节,您只能坚持打开 WAL 模式,不能坚持关闭 WAL 模式。您只能将 WAL 模式作为每个连接的一部分关闭,当您关闭数据库时,该设置将被遗忘。

【讨论】:

    猜你喜欢
    • 2013-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    相关资源
    最近更新 更多