SQLite数据库文件损坏的可能几种情况(一)

  返回:SQLite—系列文章目录   

上一篇:SQLiteC/C++接口详细介绍sqlite3_stmt类(十三)

下一篇:SQLite使用的临时文件(二)

概述

SQLite数据库具有很强的抗损坏能力。如果应用程序崩溃,或操作系统崩溃,甚至电源故障发生在事务中间,部分写入的事务应在下次自动回滚将访问数据库文件。恢复过程已完全完成自动,不需要用户采取任何行动或应用程序。尽管SQLite可以抵抗数据库损坏,但它也不能幸免。本文档介绍了SQLite数据库可能引起的各种损坏情况。

1.被恶意线程或进程覆盖文件
SQLite数据库文件是普通的磁盘文件。这意味着任何进程都可以打开文件和用垃圾覆盖它。没有什么是SQLite的图书馆可以做些什么来防御这种情况。
1.1.关闭文件描述符后继续使用文件描述符
我们已经看到多个案例,其中文件描述符在文件上打开,然后,该文件描述符被关闭并在SQLite数据库上重新打开。后来,其他一些线程继续写入旧文件描述符,没有意识到原始文件已关闭已经。但是由于文件描述符已被SQLite重新打开,打算进入原始文件的信息最终被覆盖SQLite数据库的某些部分,导致数据库。
其中一个例子发生在2013-08-30左右的规范存储库上用于化石DVCS。在这种情况下,文件描述符2(标准错误)在sqlite3_open_v2()之前被错误地关闭(我们怀疑是stunnel),因此文件描述符用于存储库数据库文件为2。稍后,应用程序错误导致assert()语句发出通过调用write(2,...)发出的错误消息。但是由于文件描述符2是现在连接到数据库文件,错误消息覆盖了部分数据库。为了防范这种问题,SQLite版本3.8.1(2013-10-17)后来拒绝使用低编号的文件描述符对于数据库文件。(有关其他信息,请参阅SQLITE_MINIMUM_FILE_DESCRIPTOR。
使用已关闭文件导致的损坏的另一个示例Facebook工程师在2014年8月12日的一篇博客文章中报告了描述符。
2019-07-11针对Fossil报告了此错误的另一个示例。文件描述符将打开以调试输出,但随后由SQLite关闭并重新打开。但是调试逻辑继续写入原始文件描述符。请参阅论坛讨论,了解错误报告和修复程序的链接。
1.2.在事务处于活动状态时进行备份或恢复
在后台运行自动备份的系统可能会尝试在SQLite数据库文件处于中间时制作备份副本交易。然后,备份副本可能包含一些旧的和一些的新内容,因此被损坏。
制作SQLite数据库可靠备份副本的最佳方法是利用作为SQLite库一部分的备份API。如果做不到这一点,那么制作SQLite数据库文件的副本是安全的因为任何进程都没有正在进行的事务。如果以前的事务失败,那么任何回滚日志都很重要(*-journal文件)或预写日志(*-wal文件)与数据库文件本身一起复制。
1.3.删除热日志
SQLite通常将所有内容存储在单个磁盘文件中。然而在执行事务时,恢复崩溃或电源故障后的数据库存储在辅助数据库中日志文件。此类日志文件被描述为“热”。日志文件与原始数据库文件,并添加了的-journal或-wal后缀。
SQLite必须查看日志文件才能从崩溃中恢复或电源故障。如果热日志文件被移动、删除或重命名崩溃或电源故障后,自动恢复将不起作用并且数据库可能会损坏。
此问题的另一个表现是由于8+3文件名的使用不一致而导致的数据库损坏。
1.4.数据库文件和热日志配对错误
前面的示例是更一般问题的特定案例:SQLite数据库的状态由数据库文件和日志文件。在静止状态下,日记文件不存在,只有数据库文件很重要。但是,如果日志文件确实存在,则它必须是与数据库一起保存以避免损坏。以下这些行为都可能导致腐败:
在两个不同的数据库之间交换日志文件。

你可能感兴趣的:(人工智能,数据库,SQLite,数据库,sqlite,c++)