如何刷新 Firefox 存储 SQLite 数据库文件以消除大型 SQLITE-WAL 文件?

如何刷新 Firefox 存储 SQLite 数据库文件以消除大型 SQLITE-WAL 文件?

我注意到WAL(预写日志)与 Firefox Web 浏览器使用的 SQLite 数据库 (*.sqlite) 关联的文件 (*.sqlite-wal) 通常会变得非常大。它们的大小实际上可以是关联的 SQLite 数据库的 150 倍以上,并且会保持该大小数月(数年?永远?)。

根据这个 StackOverflow 答案,一个可能的解决方案可能是在每个受影响的存储数据库上运行以下 SQLite pragma 命令:

PRAGMA schema.wal_checkpoint(TRUNCATE);

理论上,可以使用 Firefox 外部的 SQLite 工具来执行此操作,但据我了解,执行操作之内Firefox 通常能产生最好的效果。 (例如,尝试omni.jar在 Firefox 之外工作...这可能是一个 PITA,因为 Mozilla 使用非典型的 JAR 结构。)

在 Firefox 中,有没有办法刷新其所有 SQLite 存储数据库,以便将其内容完整写入相应的.sqlite文件中?


更新:

我想说的是,发布这个问题的主要目的之一是安全地处理storage-sync-v2.sqlite-wal每个 Firefox 配置文件中不断增长直至达到 32MB 的文件。相应的数据库storage-sync-v2.sqlite也有一个storage-sync-v2.shm文件,但往往保持相当小。为了将重点放在每个问题一个主题,我写了一个相关问题专门解决该目标

答案1

退出使用包含相关数据库的配置文件的 Firefox 实例。

从临时配置文件启动 Firefox。打开浏览器控制台并粘贴以下代码片段。编辑路径字符串,使其指向目标配置文件。按Enter

对每个 sqlite 数据库重复此操作。

希望这会起到奇效,但在尝试任何操作之前备份您的个人资料也无妨。

(()=>{
  let file = new FileUtils.File("/pathToTargetProfile/places.sqlite"); // edit this string
  let db = Services.storage.openDatabase(file);
  let stmt = db.createStatement("PRAGMA wal_checkpoint(TRUNCATE)");
  stmt.executeStep();
  console.log(stmt.row); //this might provide useful info
  stmt.finalize();
  db.close();
})();

答案2

这实际上是一个非常好的问题,但是问的人并不多。

文件.sqlite-wal增长到 32MB 的限制,因为这可能是您(或您的包创建者)在编译 Firefox 的 sqlite 期间定义的交易日志限制。

你可以在编译时调整交易日志限制的指令称为SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT它的定义是字节。就您而言,它是 32MB。

您还可以稍后在 sqlite 中使用以下命令调整交易日志限制:

PRAGMA schema.journal_size_limit = N ;(再次位于字节,负数不设限制)

你必须明白,这是一个软限制,这不是什么难题。如果您有一个正在写入日志的活动进程;即使达到指定的限制,它也会继续写入。即使您定义了 20MB 的限制,它也很容易达到 2GB。

此限制适用于不活跃交易日志。我认为 Firefox 开发人员认为 32MB 是预写日志和速度之间的最佳平衡。

如果您想在编译后调整 PRAGMA 大小,则需要针对每个配置文件进行调整。如果您计划使用多个配置文件/数据库,则可能需要使用该集合重新编译它SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT

引用该人的有效部分:

在 WAL 模式下,预写日志文件不会在检查点之后被截断。相反,SQLite 会重新使用现有文件来记录后续的 WAL 条目,因为覆盖比追加更快。

journal_size_limit 指令可用于限制事务或检查点后文件系统中剩余的回滚日志文件和 WAL 文件的大小。每次提交事务或重置 WAL 文件时,SQLite 都会将文件系统中剩余的回滚日志文件或 WAL 文件的大小与此指令设置的大小限制进行比较,如果日志或 WAL 文件较大,则会将其截断为限制大小。

上面列出的 pragma 的第二种形式用于为指定的数据库设置新的字节限制。负数表示没有限制。要始终将回滚日志和 WAL 文件截断为其最小大小,请将 journal_size_limit 设置为零。上面列出的 pragma 的第一种和第二种形式都返回一个包含单个整数列的单个结果行 - 日志大小限制的值(以字节为单位)。默认日志大小限制为 -1(无限制)。SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT 预处理器宏可用于在编译时更改默认日志大小限制。

此指令仅对指令名称之前指定的单个数据库进行操作(如果未指定数据库,则对“主”数据库进行操作)。无法使用单个 PRAGMA 语句更改所有附加数据库的日志大小限制。必须为每个附加数据库单独设置大小限制。

更新:

我忘了一个重要的 SQLite 参数 wal_autocheckpoint=N;(其中 N 是数字共 32KiB页面在 512KiB 日志中)。 (OP 已提到截断数据时的情况)

您可以将其配置为使用较小的自动检查点。请注意,这会影响 SQLite 的性能,从而影响浏览器的性能。太多的检查点会降低浏览器的速度。

要正确地配置自动检查点点击链接。

值得注意的是,以这种方式启动的检查站被动的。这意味着 SQLite 应该尽可能不阻塞地做更多的事情。

引用被动模式的一段话:

SQLITE_CHECKPOINT_PASSIVE 检查尽可能多的帧,而无需等待任何数据库读取器或写入器完成,然后如果日志中的所有帧都已检查点,则同步数据库文件。在 SQLITE_CHECKPOINT_PASSIVE 模式下,永远不会调用 busy-handler 回调。另一方面,如果有并发读取器或写入器,被动模式可能会使检查点未完成。

与上面的更新说明相同,您也可以在编译时使用以下命令设置此选项SQLITE_DEFAULT_WAL_AUTOCHECKPOINT=<pages>

来自男人:

此宏设置 WAL 自动检查点功能的默认页数。如果未指定,则默认页数为 1000。

相关内容