在 Android Pie 中禁用 sqlite 预写日志记录

Disabling sqlite Write-Ahead logging in Android Pie

In Android Pie sqlite 预写日志记录 (WAL) 已默认启用。这导致我现有的代码仅在 Pie 设备中出错。 由于我访问数据库的方式,我无法使用 SQLiteDatabase.disableWriteAheadLogging()PRAGMA journal_mode 成功关闭 WAL。我想使用名为 db_compatibility_wal_supported 的 Android 设置完全禁用 WAL :

Compatibility WAL (Write-Ahead Logging) for Apps

有人知道如何配置吗?我不知道这个文件是否可以在启动时以编程方式更改,或者是否可以手动更改。


有关问题的更多详细信息

我的应用程序中有一个 sqlite 数据库(20mb+ / 250k 条记录)。这个数据库是在我的服务器上使用纯 java 生成的。它包含一个食物数据库,应用程序的用户可以添加到数据库(并且服务器已更新)。这存储在 android 的资产文件夹中。 在第一次安装过程中,数据库从 assets 复制到 app 文件夹,以便可以写入,有效地使用此方法:

Copy SQLite database from assets folder

不幸的是,一旦我开始使用 SqlDroid wal 写入数据库,原始数据库中的 tables 就消失了,只剩下新创建的 tables。然而,数据库的大小仍然是 20mb 以上。所有数据库错误都是由于缺少 table 造成的。 table 复制和写入方法在 Pie 之前的 Android 版本中完美运行。

@Rockvole 请分享您遇到的错误,这有助于我们找到合适的解决方案。

与此同时,我了解到您想关闭 android 派中的 WAL,并且您正在使用 "SQLDroid" 库来创建 Sqlite 数据库。

这个库内部使用“SQLiteDatabase”在本地存储数据,我想你需要调用“SQLiteDatabase.disableWriteAheadLogging()" in "SQLiteDatabase" class 其中数据库实例创建的包名称是 "package org.sqldroid;"

获取内部SQLiteDatabase实例并调用disableWriteAheadLogging()。

第二种解决方案是在 values 文件夹中创建 "config.xml" 并写入 "<bool name="db_compatibility_wal_supported">false</bool>" 和 运行 并检查其工作。

不能使用 SQLDroidDriver.ADDITONAL_DATABASE_FLAGS,因为没有可用的 constant,这会否定标志 ENABLE_WRITE_AHEAD_LOGGING

仍然可以通过创建以下任一方案来禁用 WAL:

a) 设置标志 OPEN_READONLY(适用于 R/O 访问就足够的情况)。

b) 运行 PRAGMA journal_mode=DELETE 作为第一个查询,为了覆盖 PRAGMA journal_mode=WAL.

c) 针对 SQLDroidConnection.java 提出问题, 为了在驱动程序级别上支持 .enableWriteAheadLogging().disableWriteAheadLogging()

我终于找到了答案。看来我收到的数据库错误与 WAL 没有直接关系。这是因为广泛使用的从资产复制数据库的代码中有一个错误,即在复制操作期间数据库处于打开状态。这才开始在 Android P 中引起问题。 解决方法是获取数据库文件名后关闭数据库。

SQLiteDatabase destinationDatabase = sqLiteOpenHelper.getWritableDatabase();
String dbFileName=destinationDatabase.getPath();
destinationDatabase.close();
// Now write the destinationDatabase using the dbFileName

此处更详细: Android P - 'SQLite: No Such Table Error' 从资产复制数据库后

在数据库中禁用 WAL 模式的最好和最简单的方法如下:

public class MyDbHelper extends SQLiteOpenHelper {

    //...

    @Override
    public void onOpen(SQLiteDatabase db) {
        db.disableWriteAheadLogging();  // Here the solution
        super.onOpen(db);
    }

    //...
}

这样,对数据库的所有访问都将禁用 WAL 模式。在您的 App

的整个实施过程中打开和关闭多个连接

如果您使用的是 Room,您将无法直接访问数据库,但您可以在 building/opening 数据库时设置日志模式:

db = Room.databaseBuilder(context, Database.class, "Database")
         .setJournalMode(JournalMode.TRUNCATE)
         .build();