SQLite:Wal2 模式
SQLite: Wal2 Mode

原始链接: https://www.sqlite.org/cgi/src/doc/wal2/doc/wal2.md

《Wal2模式笔记》简单总结 如果您希望 SQLite 数据库性能更好并且不会导致其预写日志无限增长,请考虑切换到“wal2 模式”。 与传统的“wal 模式”类似,wal2 模式创建 wal(预写日志的缩写)文件,用于跟踪对数据库所做的更改。 然而,与 wal 模式不同,wal2 模式允许同时使用多个 wal 文件('-wal' 和 '-wal2')。 一旦主 wal 文件变得太大,wal2 模式会自动切换到辅助 wal 文件,从而允许检查和清除前者。 通过这些技术限制增长,wal2 模式减少了由于冗长的读取操作导致的文件膨胀,防止检查点在检查点进程期间继续完成或写入日志文件。 熟悉传统 wal 模式的开发人员会认识到许多相似之处。 总体而言,与传统的“wal 模式”相比,wal2 由于更高效的资源管理而提供了更快的性能,最终降低了内存使用量并提高了整体速度。

不幸的是,没有明确的迹象表明 Wal2 模式何时可以在 SQLite 项目中普遍使用。 根据 Djikstra 于 2020 年 2 月发布到邮件列表的文章“WAL 重组提案”,他表示“补丁集 [...] 可能很快就会准备好”,暗示可能在几个月甚至几周内可用, 但如此重大的功能变化似乎不太可能以这样的速度实现。 在官方存储库中两年没有与 WAL2 相关的更新之后,此功能的进展已大大放缓。 一些开发人员认为它在某些配置中不稳定,或者它给现有工作流程带来了问题,其他开发人员则声称由于缺乏测试而存在错误。 最终,仍然不确定 Wal2 模式何时以及以何种形式正式用于一般 SQLite 应用程序,以及它最终是否会成功与该特定领域的其他替代方案竞争。 尽管如此,我们鼓励那些希望尝试此功能以提供有关错误、限制或附加功能的反馈的感兴趣的各方加入各个论坛中正在进行的讨论,参与相关的审核周期,并为提高整体质量做出贡献。 该功能,包括在代表性基础设施上进行测试。
相关文章

原文

Activating/Deactivating Wal2 Mode

"Wal2" mode is very similar to "wal" mode. To change a database to wal2 mode, use the command:

 PRAGMA journal_mode = wal2;

It is not possible to change a database directly from "wal" mode to "wal2" mode. Instead, it must first be changed to rollback mode. So, to change a wal mode database to wal2 mode, the following two commands may be used:

 PRAGMA journal_mode = delete;
 PRAGMA journal_mode = wal2;

A database in wal2 mode may only be accessed by versions of SQLite compiled from this branch. Attempting to use any other version of SQLite results in an SQLITE_NOTADB error. A wal2 mode database may be changed back to rollback mode (making it accessible by all versions of SQLite) using:

 PRAGMA journal_mode = delete;

The Advantage of Wal2 Mode

In legacy wal mode, when a writer writes data to the database, it doesn't modify the database file directly. Instead, it appends new data to the "-wal" file. Readers read data from both the original database file and the "-wal" file. At some point, data is copied from the "-wal" file into the database file, after which the wal file can be deleted or overwritten. Copying data from the wal file into the database file is called a "checkpoint", and may be done explictly (either by "PRAGMA wal_checkpoint" or sqlite3_wal_checkpoint_v2()), or automatically (by configuring "PRAGMA wal_autocheckpoint" - this is the default).

Checkpointers do not block writers, and writers do not block checkpointers. However, if a writer writes to the database while a checkpoint is ongoing, then the new data is appended to the end of the wal file. This means that, even following the checkpoint, the wal file cannot be overwritten or deleted, and so all subsequent transactions must also be appended to the wal file. The work of the checkpointer is not wasted - SQLite remembers which parts of the wal file have already been copied into the db file so that the next checkpoint does not have to do so again - but it does mean that the wal file may grow indefinitely if the checkpointer never gets a chance to finish without a writer appending to the wal file. There are also circumstances in which long-running readers may prevent a checkpointer from checkpointing the entire wal file - also causing the wal file to grow indefinitely in a busy system.

Wal2 mode does not have this problem. In wal2 mode, wal files do not grow indefinitely even if the checkpointer never has a chance to finish uninterrupted.

In wal2 mode, the system uses two wal files instead of one. The files are named "-wal" and "-wal2", where "" is of course the name of the database file. When data is written to the database, the writer begins by appending the new data to the first wal file. Once the first wal file has grown large enough, writers switch to appending data to the second wal file. At this point the first wal file can be checkpointed (after which it can be overwritten). Then, once the second wal file has grown large enough and the first wal file has been checkpointed, writers switch back to the first wal file. And so on.

Application Programming

From the point of view of the user, the main differences between wal and wal2 mode are to do with checkpointing:

  • In wal mode, a checkpoint may be attempted at any time. In wal2 mode, the checkpointer has to wait until writers have switched to the "other" wal file before a checkpoint can take place.

  • In wal mode, the wal-hook (callback registered using sqlite3_wal_hook()) is invoked after a transaction is committed with the total number of pages in the wal file as an argument. In wal2 mode, the argument is either the total number of uncheckpointed pages in both wal files, or - if the "other" wal file is empty or already checkpointed - 0.

Clients are recommended to use the same strategies for checkpointing wal2 mode databases as for wal databases - by registering a wal-hook using sqlite3_wal_hook() and attempting a checkpoint when the parameter exceeds a certain threshold.

However, it should be noted that although the wal-hook is invoked after each transaction is committed to disk and database locks released, it is still invoked from within the sqlite3_step() call used to execute the "COMMIT" command. In BEGIN CONCURRENT systems, where the "COMMIT" is often protected by an application mutex, this may reduce concurrency. In such systems, instead of executing a checkpoint from within the wal-hook, a thread might defer this action until after the application mutex has been released.

联系我们 contact @ memedata.com