Small. Fast. Reliable.
Choose any three.
校验和VFS Shim

1.概述

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

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

2.编译

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

要将校验和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:

整数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计数(*),verify_checksum(数据)
  从sqlite_dbpage
 GROUP BY 2;

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

如果一切正常,则上面的查询应返回第二行为1的单行。其他任何结果都表明存在校验和错误,或者禁用了校验和验证。

6.控制校验和验证

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

PRAGMA checksum_verification; -查询状态
PRAGMA checksum_verification = OFF; -禁用验证
PRAGMA checksum_verification = ON; -重新启用验证

如果分别启用或禁用校验和验证,则“ checksum_verification”编译指示将返回“ 1”(真)或“ 0”(假)。在这种情况下,“验证”表示如果在读取时检测到校验和不匹配,则会导致SQLITE_IOERR_DATA错误的功能。只要数据库的保留字节值为8,校验和就始终保持最新状态 ,而与该编译指示的设置无关。可以禁用校验和验证(例如)以对以前报告校验和错误的数据库进行取证分析。

如果数据库文件的保留字节值不为8,则“ checksum_verification”编译指示将始终以“ 0”响应。如果未加载cksumvfs扩展名,则编译指示将根本不返回任何行。