2

我们有一个数据库,该数据库是由使用 sqlite3 模块的 Python 编写的程序写入的。数据库执行了大量的插入语句,但事务从未被提交结束。

结果是我们有两个文件:

     Size             Time       Name
855117824 2010-12-14 15:27 db
  1665240 2010-12-14 15:27 db-journal

数据库文件很大,但是大部分数据是未提交的,所以当我们从数据库中选择时,我们只得到几行。当我们执行 sql 命令 'VACUUM' 时,数据库缩小到大约 3MB。

有什么办法可以找回数据吗?

4

1 回答 1

2

我使用sqlite3shell 程序进行了一些测试。

假设 sqlite3 Python 模块的行为方式相同,似乎没有办法可靠地恢复未提交的事务。

对于相对少量的语句,未提交的事务似乎只完全保留在应用程序内存中,并且没有数据写入文件系统。一旦数据库连接关闭或应用程序终止,这些插入将完全丢失。

对于较大的事务块,数据写入文件系统,但一旦关闭数据库连接或(如果应用程序崩溃)下次打开数据库时,数据就会被清除。简单来说,为未提交的事务分配新的 DB 页,但如果未提交事务,则它们被视为可用空间,这就是VACUUM减小 DB 大小的原因。这些页面将在下次写入 DB 文件时被写入(并且它们的数据会丢失)。如果它们位于 DB 文件的末尾,则文件会在清理时被截断。

只要之后没有执行其他写入事务,您可以从执行的最后一个未提交事务中恢复一些数据。从您的问题的措辞方式来看,听起来好像整个数据库是在单个程序运行和单个事务中创建和填充的(尽管VACUUM那时不会产生这么大的文件)。在这种情况下,事情可能会容易一些。

这在很大程度上取决于行为不端的程序是如何终止的。如果您允许它正常终止,它可能有时间进行清理,在这种情况下这是不可取的。既然你有 DB 日志,我会假设它有一个更暴力的结局。

无论如何,您至少必须深入研究 sqlite3 DB 文件格式并修改库代码以解析未提交的数据。您仍然会丢失保留在应用程序内存中的那些事务部分。

如果DELETE数据库文件中有空闲页面(例如来自语句),则可能还有旧事务的片段,尽管解释这些片段是另一回事。

在我看来,整个操作将过于接近(如果不是直接进入)计算机取证和数据恢复领域以及所有相关问题。除非您拥有无法通过其他任何方式获得的非常重要的数据,否则我怀疑这是否足够容易,值得麻烦。

于 2010-12-18T20:55:51.557 回答