从未提交的事务中恢复数据库行

时间:2010-12-14 23:34:15

标签: sql database sqlite pysqlite

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

结果是我们有两个文件:

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

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

有没有办法让数据恢复?

1 个答案:

答案 0 :(得分:2)

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

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

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

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

可能能够从上次执行的未提交事务中恢复某些数据,只要之后没有执行其他写入事务。从你的问题的表达方式来看,听起来似乎整个数据库是在单个程序运行和单个事务中创建和填充的(尽管VACUUM不会产生如此大的文件)。在这种情况下,事情可能会更容易一些。

这在很大程度上取决于如何行为不端的程序被终止。如果你允许它优雅地终止它可能有时间清理,在这种情况下是不可取的。由于你有数据库日记,我会认为它有更暴力的结局。

在任何情况下,您都必须至少深入研究sqlite3数据库文件格式并修改库代码以解析未提交的数据。您仍将丢失保留在应用程序内存中的事务部分。

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

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