在版本3.7中引入的预写日志功能的SQLite documentation中,有一些评论让我感到困惑。
链接页面说“只要应用程序愿意牺牲掉电后的耐用性”,就不需要“将内容同步到磁盘”。然后几段落后,它说“检查点确实需要同步操作,以避免在断电或硬重启后数据库损坏的可能性”。
如果我使用WAL,那么我的数据库是否存在更大的断电损坏风险?
答案 0 :(得分:5)
要完全回答,我们需要知道您设置的PRAGMA synchronous
是什么,因为这会影响调用fdatasync()
的时间,从而影响缓冲区在物理驱动器上刷新的时间。
当您引用“只要应用程序愿意牺牲掉电后的耐用性”时,这指的是synchronous=NORMAL
。这里WAL仅在检查点发生时同步到磁盘(一个fdatasync()
用于WAL,一个用于主DB在合并后)。你应该受到很好的保护,但是可能会有一些写入从未进入拼盘并因此丢失:因此失去了耐久性。虽然优势远不如实际同步数据的慢fdatasync()。
要获得最佳的数据丢失,您可能需要synchronous=FULL
。这会重新获得持久性,但每次写入事务的成本为fdatasync()
。但是,这仍然比非WAL模式好,其中有两个fdatasync()
调用 - 一个用于事务日志,一个用于主DB。
答案 1 :(得分:4)
WAL没有增加腐败的风险(因为它在检查点时使用同步操作)。
但是,如果发生崩溃(断电或硬重启),您将丢失自上一个检查点以来的任何交易;这就是“牺牲耐久性”的含义。
答案 2 :(得分:0)
只要对您的操作系统进行同步调用就能完美运行,您就没有损坏数据库的风险。但是,这可能是也可能不是 - 请参阅sqlite文档以获得更详细的解释。
纠正Doug Currie(参见MattR的帖子):如果@ synchronous = NORMAL @,你只会冒失去交易的风险。如果@ synchronous = FULL @(这是默认值),你不会牺牲耐久性。有关详细信息,请参阅http://www.sqlite.org/draft/wal.html。
我认为WAL日记实际上比“经典”日记更安全(在系统同步不完美的情况下),因为在我理解WAL日记的情况下,db在给定时刻执行某些操作的可能性较低。但是我目前没有硬数据来支持这一点。