【问题标题】:Disabling sqlite Write-Ahead logging in Android Pie在 Android Pie 中禁用 sqlite Write-Ahead 日志记录
【发布时间】:2018-12-06 20:29:27
【问题描述】:

在 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 文件夹中。 在首次安装期间,数据库会从 assets 复制到 app 文件夹,以便可以使用以下方法对其进行写入:

Copy SQLite database from assets folder

不幸的是,一旦我开始使用 SqlDroid 写入数据库,就会启用 wal,并且原始数据库中的表已经消失,只剩下任何新创建的表。然而,数据库的大小仍然是 20mb+。所有数据库错误都是由于缺少表。 表格复制和写入方法在 Pie 之前的 Android 版本中完美运行。

【问题讨论】:

  • WAL 导致错误你到底在做什么?
  • 如果您使用的是 SQLiteOpenHelper 的子类,请尝试覆盖 onConfigure 方法并在该方法中发出编译指示。
  • 我正在使用 SQLDroid 连接到我的数据库,因为我在我的应用程序和服务器中使用相同的数据库访问代码。 connection = new org.sqldroid.SQLDroidDriver().connect()
  • 相关? stackoverflow.com/questions/43244091/… 如果你可以使用 Root 权限..

标签: android sqlite wal sqldroid


【解决方案1】:

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

public class MyDbHelper extends SQLiteOpenHelper {

    //...

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

    //...
}

这样,所有对数据库的访问都将禁用 WAL 模式。就像您在应用程序的整个实施过程中打开和关闭多个连接一样

【讨论】:

  • 我同意这个答案最适合这个问题。话虽如此,我还将更新您的数据库助手类中的 onCreate 方法,以在此处禁用预写日志:db.disableWriteAheadLogging();
  • 不直接暴露数据库的 ORM(如 Room)怎么样?
  • 使用 db.disableWriteAheadLogging() 方法,我们可以避免“没有这样的表”错误,但现在我们在使用 Pie (9) 版本时无法更新数据库中的任何列。注意:它在 Marshmallow(6) 中工作正常,我可以在这里对 DB 进行更改,请建议我如何在 Pie verison 中对 DB 进行更改
  • @Annie 你有解决 Pie verison 及更高版本数据库无法更新的解决方案吗?
【解决方案2】:

不能使用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 的某些版本中提供了一个索尼运行时资源覆盖功能,我什至无法确认在 Pie 中是否可行。
  • 我发现的另一种可能性是在 config.xml 中覆盖值,但这仅适用于 Android 的自定义构建:stackoverflow.com/questions/49249703/…
  • 选项“a”有助于 onConfigure() 组合。 +1
【解决方案3】:

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

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

【讨论】:

  • 截断与禁用预写日志记录相同吗?
  • 谢谢老哥,成功了
【解决方案4】:

@Rockvole 请分享您面临的错误,帮助我们找到合适的解决方案。

同时,我知道您想在 android pie 中关闭 WAL 并且您正在使用“SQLDroid”库来创建 Sqlite DB。

这个库内部使用“SQLiteDatabase”来本地存储数据,我认为你需要在“SQLiteDatabase中调用“SQLiteDatabase.disableWriteAheadLogging()” strong>" 数据库实例创建包名的类是 "package org.sqldroid;"

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

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

【讨论】:

  • 在我的应用程序的 sqlite 初始化期间,我使用标准 SQLiteDatabase 指令。在那里我可以很好地禁用 WAL - 它可以工作并且我已经验证了这一点。不幸的是,以这种方式禁用 WAL 并不难。因此,当我在 sqldroid 中执行进一步的数据库命令时,WAL 会重新打开。
  • 如果我在 SQLDroid 中使用 PRAGMA 关闭 WAL 仍然为时已晚,因为在我发出 PRAGMA 之前 WAL 已经打开。我相信它需要 SQLDroid 中的 disableWriteAheadLogging() 方法才能正常工作。
  • 我尝试将 config.xml 添加到 values 目录中,并将 db_compatibility_wal_supported 设置为 false,但它什么也没做。
【解决方案5】:

我终于找到了答案。我收到的数据库错误似乎与 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' after copying database from assets

【讨论】:

  • 那个答案根本不符合问题。 meta.stackexchange.com/questions/16065/…
  • 我意识到 - 如果您查看其他相关答案,您会发现 wal 是某些人的罪魁祸首。在我的情况下这是一个红鲱鱼,因为启用 wal 是 Android Pie 的一个重大变化,同时数据库文件保持打开的方式也发生了变化。
  • 好吧,这可能与在 R/W 模式下打开文件时的独占文件访问有关 - 标志 OPEN_READONLY 可能仍会改变行为 - 特别是当给定情况只需要 R/O 时使用权。即使正确调用.close() 具有相同的效果,该问题没有提供任何代码,因此很难发现问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-17
  • 2011-06-22
  • 2015-04-21
  • 2015-02-01
  • 2012-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多