在 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
在数据库中禁用 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();
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
在数据库中禁用 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();