SQLite:Fsyncing with journal_mode = wal 和 synchronous = normal

Posted

技术标签:

【中文标题】SQLite:Fsyncing with journal_mode = wal 和 synchronous = normal【英文标题】:SQLite: Fsyncing with journal_mode = wal and synchronous = normal 【发布时间】:2015-03-17 15:40:19 【问题描述】:

我在 Debian 7 上使用 SQLite 3.7.13 时遇到了一个有趣的问题。

我正在使用带有“PRAGMA journal_mode = wal”和“PRAGMA synchronous = normal”的 SQLite 来尝试避免 Python 程序的主事件循环中的 fsync。正如文档所建议的,我已禁用自动检查点,并定期在 不同线程 中运行“PRAGMA wal_checkpoint”以将最新数据同步到磁盘。

这是可行的,但是我发现 主程序线程 中的检查点之后的 first 插入操作会导致 WAL 文件本身的一次性 fsync 调用.任何进一步的插入操作都不会导致 fsync。我已经使用 strace 验证了这一点。

查看它说的 SQLite 文档:

WAL 文件在检查点后开始被重用时同步 WAL 文件头

我正在寻找一种方法来防止在主线程中发生任何 fsync,但这仍然允许我从另一个线程执行定期检查点。在检查点线程中是否可以做更多的事情来避免主线程中的 fsync?

我查看了“同步 = 关闭”,但这也阻止了检查点的 fsync。

注意:我为两个线程中的每一个线程都有一个单独的数据库连接(如果相关的话)

进一步说明:文档似乎在其他地方说不应该有 fsync,但观察到的行为明显不同:

请注意,当 PRAGMA 同步设置为 NORMAL 时,检查点是发出 I/O 屏障或同步操作的唯一操作(unix 上的 fsync() 或 windows 上的 FlushFileBuffers())。因此,如果应用程序在单独的线程或进程中运行检查点,则执行数据库查询和更新的主线程或进程将永远不会阻塞同步操作。

谢谢

【问题讨论】:

【参考方案1】:

要将 fsync 移动到另一个线程,请执行第一个更改该线程中数据库的操作。 你可以使用像PRAGMA user_version = 42 这样无害的东西(假设你不使用user version)。

【讨论】:

这似乎是一个有效的解决方法(我已经在我的场景中对其进行了测试)但是我希望有一些东西可以保证主线程永远不会最终调用 fsync,我在这里假设主线程在另一个线程中对“PRAGMA wal_checkpoint”和“PRAGMA user_version = 42”的调用之间有很小的机会命中数据库。

以上是关于SQLite:Fsyncing with journal_mode = wal 和 synchronous = normal的主要内容,如果未能解决你的问题,请参考以下文章

PHP日期moins/加n jours/mois

sqlite3-树形递归查询-with

rechercher les fichiers modifiés depuis 1 jours(unix)公司

html Spip - Dateur:exclure des jours et les WE du datepicker

SQLite with Foreign Key + Models Android Studio CRUD

sh 检查,倒入申请donnée,les processus qui sont plus vieux qu'un jour