文章摘要
SQLite在WAL模式下默认使用synchronous=NORMAL,不会在每次提交时调用fsync,这可能导致事务在断电或系统崩溃后回滚。若需确保每次提交的持久性,应设置synchronous=FULL,此时每次提交后会额外同步WAL文件,增强事务的持久性。
文章总结
标题: SQLite(使用WAL模式)在默认设置下不会在每次提交时执行fsync
主要内容:
SQLite提供了WAL(Write-Ahead Logging)模式,该模式默认情况下不会在每次提交时调用fsync操作。WAL模式通常用于提高写入吞吐量。SQLite的PRAGMA synchronous配置项用于控制fsync的调用方式,默认值为NORMAL。在NORMAL模式下,WAL文件在每次检查点之前同步,数据库文件在每次检查点完成后同步,WAL文件头在检查点后重新使用时同步,但在大多数事务期间不会执行同步操作。这意味着在NORMAL模式下,事务在电源丢失或系统崩溃后可能会回滚,从而影响数据的持久性。
如果需要在每次提交时调用fsync,可以将PRAGMA synchronous设置为FULL。在FULL模式下,每次事务提交后都会额外同步WAL文件,以确保事务在电源丢失时仍然持久。
更新:
文章作者最初认为默认的SQLite3在macOS上的行为是PRAGMA synchronous=1,但通过Homebrew安装的SQLite3版本显示PRAGMA synchronous=2。此外,编译时选项SQLITE_DEFAULT_SYNCHRONOUS和SQLITE_DEFAULT_WAL_SYNCHRONOUS可以设置默认的同步模式,如果没有在编译时覆盖,默认值为FULL(即2)。
相关讨论: 有人向作者推荐了一篇关于SurrealDB牺牲数据持久性以优化基准测试的文章,并询问SQLite的工作原理。
评论总结
评论主要围绕SQLite的默认设置、性能与数据持久性之间的权衡展开,以下是总结:
默认设置与性能:
- SQLite默认使用
FULL同步模式,但某些包装器可能会更改默认设置(评论5)。 - 默认设置可能出于性能考虑,但现代SSD的频繁
fsync可能会影响其寿命(评论2)。
- SQLite默认使用
数据持久性与应用场景:
- 在嵌入式数据库中,电源丢失可能导致应用和SQLite同时“忘记”已提交的数据,因此默认设置是合理的(评论3)。
- 对于客户端应用,SQLite默认是
FULL同步,而SurrealDB作为远程服务器默认关闭fsync,两者场景不同(评论11)。
文档与用户责任:
- SQLite的文档清晰,用户应理解其行为并根据应用需求调整设置(评论3, 评论12)。
- 默认设置应优先保证安全,而非性能,用户不应假设所有默认设置都是安全的(评论7)。
WAL模式的限制:
- WAL模式需要所有客户端共享内存,并且会禁用附加数据库的ACID事务,启用前需充分理解其限制(评论6)。
具体使用建议:
- 在Apple平台上,建议使用
F_FULLFSYNC而非fsync以确保数据持久性(评论1)。 - 使用Lightstream时,文档建议使用
synchronous=NORMAL,但用户应根据需求决定是否恢复为FULL(评论13)。
- 在Apple平台上,建议使用
总结:SQLite的默认设置在不同场景下有其合理性,用户应根据具体需求理解并调整相关配置,确保数据安全与性能的平衡。