假设没有断电或灾难性的操作系统崩溃,那么fsync()
调用成功,并且数据库更改真正写入Oxid。
由于PRAGMA integrity_check
实际上并不检测SQLite数据库中的数据损坏,因此开发人员需要自己想出一种检测数据损坏的方法。
存储整个数据库文件的校验和是可行的,但是效率太低,不能用于每个行插入(假设数据库大小为数GB)。
为每一行保留一个校验和是显而易见的解决方案,但这不会检测到数据损坏导致整行被删除的情况。因此,我们需要一种方法来检测表中的行是否已被删除。
我想出的检测丢失行的方法是保存所有校验和的XOR和。这是高效的,因为每次更新一行时,我们只需将和与该行的旧校验和进行异或运算,然后将和与行的新校验和进行异或运算。我突然想到,这不是最好的方法,但我还没有找到任何更有效的更好的替代方法,所以欢迎建议。
编辑:我想到了一种替代方法,它要求所有表都是仅追加的。在仅追加的表中,我们可以假设ROID是连续的,这意味着我们可以很容易地注意到除了最后一行之外的任何缺少的行,我们可以将其存储在某个地方。
参考资料:
1.https://www.sqlite.org/pragma.html
1条答案
按热度按时间lzfw57am1#
以下是一个应该奏效的方案:
在该表中,添加一个“prev”和一个“Next”列,它们分别保存前一行和下一行的主键,因此您可以将该表视为一个双向链接列表。这意味着,当通过数据损坏从表中删除一行时,对表的扫描将发现“Next”键与下一行的键不匹配,或者“prev”键与前一行的键不匹配。这些列也应该是唯一的,这样两行不能有相同的“NEXT”或“PREV”行,它们也应该有外键约束。
错误答案见下图:
Pragma integrity_check
实际上将检测丢失的行,请查看它显示的位置:Missing or surplus index entries
因此,如果您输掉了一行,它会这样说:
row 12345 missing from index some_index
编辑:这个答案实际上是不正确的。
row x missing
消息仅指示行在索引中没有对应的条目,并不意味着索引中的条目没有对应的行(如果行被删除就会发生这种情况)。