小巧。快速。可靠。
三选二。
校验和 VFS 扩展

1. 概述

校验和 VFS 扩展是一个VFS 扩展,它会在 SQLite 数据库中每个页面的末尾添加一个 8 字节的校验和。校验和在写入每个页面时添加,并在读取每个页面时进行验证。校验和旨在帮助检测由大容量存储设备中的随机位翻转引起的数据库损坏。

校验和 VFS 扩展需要 SQLite 3.32.0(2020-05-22)或更高版本。它不适用于早期版本的 SQLite。

2. 编译

校验和 VFS 模块是一个可加载扩展。它不包含在合并版本中。它必须在编译时或运行时添加到 SQLite 中。校验和 VFS 模块的源代码位于 SQLite 源代码树中的ext/misc/cksumvfs.c源文件中SQLite 源代码树

要将校验和 VFS 模块构建为运行时可加载扩展,请使用类似于以下的命令

当然,您可能希望根据项目的需要添加其他编译器选项。

要将此扩展静态链接到您的产品中,请像编译任何其他 C 语言模块一样编译它,但添加“-DSQLITE_CKSUMVFS_STATIC”选项,以便此模块知道它是被静态链接而不是动态链接。

3. 加载

要将此扩展加载为共享库,您首先必须启动一个虚拟 SQLite 数据库连接以用作sqlite3_load_extension() API 调用的参数。然后,您调用sqlite3_load_extension() API 并关闭虚拟数据库连接。随后打开的所有数据库连接都将包含此扩展。例如

sqlite3 *db;
sqlite3_open(":memory:", &db);
sqlite3_load_extension(db, "./cksumvfs");
sqlite3_close(db);

如果此扩展使用 -DSQLITE_CKSUMVFS_STATIC 编译并静态链接到应用程序,则使用单个 API 调用初始化它,如下所示

sqlite3_cksumvfs_init();

Cksumvfs 是一个VFS 扩展。加载后,“cksmvfs”将成为新的默认 VFS,并且它使用之前的默认 VFS 作为堆栈中的下一个 VFS。这通常是您想要的。但是,在加载多个 VFS 扩展的复杂情况下,确保 cksumvfs 以正确的顺序加载可能很重要,以便它以正确的顺序将其自身排序到默认 VFS 扩展堆栈中。

4. 使用

像往常一样,使用sqlite3_open()sqlite3_open_v2()接口打开数据库连接。普通的数据库文件(没有校验和)将正常运行。如果遇到包含无效校验和的页面,则具有校验和的数据库将返回 SQLITE_IOERR_DATA 错误。

校验和仅适用于保留字节值为 8 的数据库。保留字节的默认值为 0。因此,新创建的数据库文件默认会省略校验和。要创建包含校验和的数据库,请通过运行类似于以下代码的代码将保留字节值更改为 8

int n = 8;
sqlite3_file_control(db, 0, SQLITE_FCNTL_RESERVE_BYTES, &n);

如果您在创建新的数据库文件后立即执行此操作,在任何其他内容写入文件之前,那么这可能是您需要做的全部操作。否则,上述 API 调用应后跟

sqlite3_exec(db, "VACUUM", 0, 0, 0);

运行 VACUUM 从来没有坏处,即使您不需要它。如果数据库处于 WAL 模式,则应在继续之前关闭并重新打开所有数据库连接。

从 CLI 中,使用“.filectrl reserve_bytes 8”命令,然后是“VACUUM;”。

请注意,SQLite 允许增加保留字节的数量,但不允许减少。因此,如果数据库文件已具有大于 8 的保留字节值,则无法激活该数据库上的校验和,除非转储并还原数据库文件。还要注意,其他扩展也可能使用保留字节。校验和将与这些其他扩展不兼容。

5. 校验和验证

如果任何校验和不正确,“PRAGMA quick_check”命令将找到它。要验证校验和是否已启用并正在运行,请使用以下 SQL

SELECT count(*), verify_checksum(data)
  FROM sqlite_dbpage
 GROUP BY 2;

verify_checksum() 函数有三种可能的输出:1、0 和 NULL。如果校验和正确,则返回 1。如果校验和不正确,则返回 0。如果页面不可读,则返回 NULL。如果启用了校验和,则如果校验和错误,则读取将失败,因此在错误的校验和上 verify_checksum() 的通常结果是 NULL。

如果一切正常,则上述查询应返回一行,其中第二列为 1。任何其他结果都表示要么存在校验和错误,要么校验和验证已禁用。

6. 控制校验和验证

cksumvfs 扩展实现了一个新的 PRAGMA 语句,可用于禁用、重新启用或查询校验和验证的状态

PRAGMA checksum_verification;          -- query status
PRAGMA checksum_verification=OFF;      -- disable verification
PRAGMA checksum_verification=ON;       -- re-enable verification

如果校验和验证分别已启用或禁用,“checksum_verification” pragma 将返回“1”(真)或“0”(假)。在此上下文中,“验证”是指如果在读取时检测到校验和不匹配则会导致 SQLITE_IOERR_DATA 错误的功能。只要数据库的保留字节值为 8,校验和始终保持最新,而无论此 pragma 的设置如何。可以禁用校验和验证(例如)以对先前报告校验和错误的数据库进行取证分析。

如果数据库文件没有 8 的保留字节值,“checksum_verification” pragma 将始终响应“0”。如果未加载 cksumvfs 扩展,则 pragma 根本不会返回任何行。

此页面上次修改于2022-01-08 05:02:57 UTC