如何修复损坏的 Firefox Places.sqlite 数据库?

Bob*_*bby 17 firefox data-recovery database sqlite places.sqlite

我的 RAM 出现了一些问题(蓝屏几次,Windows XP),现在我的 Firefox 数据库已损坏。Firefox的工作,但我的历史消失了,它的报告执行时数不一致和错误pragma integrity_checkplaces.sqlite

数据库磁盘映像格式错误

现在的问题是,如何修复 SQLite 数据库?

bwD*_*aco 26

笔记

由于必须关闭 Firefox 才能执行此过程,因此请务必在其他 Web 浏览器中打开此页面或将其打印出来,然后再继续。


经过几个小时的工作试图恢复 Places 数据库,甚至阅读了 Firefox 源代码,我已经成功了。这是我如何做到的:

  • 下载最新版本的 SQLite shell并将其解压缩到您的配置文件文件夹中。在 Windows Vista 和 Windows 7 上,它位于C:\Users\<username>\AppData\Roaming\Mozilla\Firefox\Profiles\<code>.default文件夹中。
  • 如果正在运行,请关闭 Firefox。
  • Places 数据库位于该places.sqlite文件中。如果文件因损坏而被替换,请使用该places.sqlite.corrupt文件进行恢复。创建文件的备份副本,命名为places.sqlite.bakplaces.sqlite.corrupt.bak
  • 使用 SQLite shell 打开数据库文件(sqlite3 places.sqlitesqlite3 places.sqlite.corrupt),然后输入:
.output dump.sql    -- sends output to file dump.sql
.dump               -- dumps database to file
Run Code Online (Sandbox Code Playgroud)
  • 由于数据库已损坏,因此生成的数据库转储不完整,并且未检索到所有可恢复数据。要确定错误发生的位置,请ERROR在转储文件内的 SQL 注释中搜索单词(全部大写)dump.sql(我使用Notepad++来执行此操作),并读取其INSERT上方的 SQL命令以确定有问题的表。就我而言,损坏的表是moz_places. (可以在此处找到对 Places 数据库中的表的描述,其中包括过时的 ER 图。)我将仅说明如何从该表中恢复其他数据;以下过程可能不适用于其他表格,因此如果涉及的表格不是其他表格,请跳过这些子步骤moz_places。)

    • moz_places表中的每一行都有一个 ID。按照此 ID 的顺序从表中转储行。1 ID 是INSERT语句中左括号后面的第一个值。数据库损坏的区域很可能是这个表中的一小块行;这里的想法是跳过这个损坏的区域并尽可能多地恢复数据。此类块的起始区域在转储中表示为ERROR注释出现之前的行。使用该行的 ID,我们可以确定数据库损坏的位置。我们通过使用SELECT带有 ID 作为条件的语句来实现;这个过程需要一些反复试验。例如,如果错误之前的最后一个 ID 是 49999,并且错误随之而来,则损坏的块从 ID 50000 开始。使用如下语句:

    -- 抑制不必要的输出
    -- 以下命令适用于Windows系统
    -- 对于 Linux 和其他 Unix 和类 Unix 系统,使用 .output /dev/null
    .输出空
    
    SELECT id FROM moz_places WHERE id >= 50100;
    
    • 调整后面的值id >=,重复上面的SELECT命令,直到找到不导致SQLite输出错误的最小值。这是指从我们可以恢复额外数据的行开始的 ID。假设此 ID 为 50200。要转储​​此数据,请输入:

    .output dump2.sql
    .mode 插入
    SELECT * FROM moz_places WHERE id >= 50200;
    
    -- 恢复正常输出行为
    .输出标准输出
    .mode 列表
    
    • 请注意,文件中的INSERT语句以dump2.sql开头INSERT INTO table VALUES,因此请使用文本编辑器中的查找和替换功能将此字符串的所有实例替换为INSERT INTO moz_places VALUES
    • 复制dump2.sql文件的全部内容并将其粘贴到出现注释的dump.sql文件中ERROR
  • ROLLBACK; -- due to errors文件末尾的替换为COMMIT;
  • 将以下代码添加到dump.sql文件顶部。替换<version>为正确的值,这是Firefox根据Firefox的版本确定数据库架构版本所必需的,如下(可在Firefox源文件中找到toolkit/components/places/Database.cpp):
    • Firefox 52:架构版本 35
    • Firefox 53:架构版本 36
    • Firefox 57:架构版本 39
    • Firefox 58:架构版本 41
    • Firefox 60:架构版本 43
    • Firefox 61:架构版本 47
    • Firefox 62:架构版本 52
    • Firefox 69:架构版本 53

PRAGMA user_version=<版本>;
PRAGMA journal_mode = truncate;
PRAGMA page_size = 32768;
真空;
PRAGMA journal_mode = wal;
  • 退出 SQLite shell,删除places.sqlite,然后启动 SQLite shell,places.sqlite使用sqlite3 places.sqlite. 键入.read dump.sql以将 SQL 转储加载到数据库中。
  • 启动 Firefox 并确认您的历史记录和位置栏按预期运行。确认一切正常后,从配置文件文件夹中删除数据库转储文件和 SQLite shell 可执行文件。

更多相关信息可在以下页面找到:

此 MDN 文章中描述了一个简化的过程,但我尚未对其进行测试。尽管如此,我已经合并PRAGMA了那篇文章中的更新命令。


1 SQL 通常不保证以任何顺序给出数据库输出,除非您使用该ORDER BY子句。但是,ORDER BY可能无法在损坏的数据库上生成任何输出(因为 SQLite 需要读取整个表才能生成任何输出)。据我所知,Firefox 总是moz_places使用顺序 ID写入表条目,因此我们可以假设所有输出都是按 ID 排序的。

  • 这是纯粹的敬畏。帮助我从损坏的places.sqlite 中恢复了几乎所有的历史记录。非常感谢!! (4认同)

Dan*_*iel 8

MDN 上描述的这个过程帮助我解决了我访问的新页面没有记录在浏览器历史记录中的问题。我没有places.sqlite.corrupt(或places.sqlite-corrupt)文件,但检查文件的完整性后places.sqlite发现数据库磁盘映像格式错误。

在继续此处之前,请退出 Firefox 并备份您的 Firefox 配置文件。

$ cd /Users/<username>/Library/Application\ Support/Firefox/Profiles/<profile_dir>/
$ cp places.sqlite places.sqlite.bak  # for safety

$ sqlite3 places.sqlite
sqlite> PRAGMA integrity_check;
*** in database main ***
On tree page 2 cell 131: Rowid 20884 out of order
...
Error: database disk image is malformed
sqlite> .clone places-clone.sqlite
moz_places... done
moz_historyvisits... done
... more output like above plus a few errors (which I ignored) like
sqlite_sequence... Error: object name reserved for internal use: sqlite_sequence
SQL: [CREATE TABLE sqlite_sequence(name,seq)]
done
...
sqlite> PRAGMA user_version;
43  <----- TAKE NOTE OF THIS VALUE it may be different for you
sqlite> .exit

$ sqlite3 places-clone.sqlite
sqlite> PRAGMA integrity_check;
ok
sqlite> PRAGMA user_version = 43;  -- use the number you got from PRAGMA user_version; above
sqlite> PRAGMA journal_mode = truncate;
truncate
sqlite> PRAGMA page_size = 32768;
sqlite> VACUUM;
sqlite> PRAGMA journal_mode = wal;
wal
sqlite> .exit

$ mv places-clone.sqlite places.sqlite
Run Code Online (Sandbox Code Playgroud)

启动火狐浏览器。历史应该再次发挥作用。

我使用的是装有 Firefox 60.0.1 的 Mac。您可能需要针对您的平台调整命令。