昨天我将 MySQL 数据库转储到 SQL 文件中,并重命名了 ibdata1 文件。然后我重新创建它并导入 SQL 文件,并将新的 ibdata1 文件移动到我的 MySQL 数据目录,删除旧文件。
我以前这样做过,没有问题,但这次有些不对劲。当我检查(个人,不是 MySQL 配置)数据库时,它们都在那里,但它们是空的……差不多。数据目录仍然包含具有正确内容的 .ibd 文件,我可以查看表列表在数据库中,而不是表本身。(我已启用每个表一个文件,并且将 InnoDB 作为所有操作的默认设置。)
例如网址数据库及其网址表,我可以成功打开mysql.exe或phpMyAdmin和use urls;
。我甚至可以show tables;
看到预期的表,但是当我尝试describe urls;
或时select * from urls;
,它会抱怨该表不存在(即使它只是列出它)。 (MySQL 管理员列出了数据库,但甚至没有列出表,这表明数据库完全是空的。)
现在的问题是我已经删除了 SQL 文件(即使彻底检查硬盘也无法恢复)。所以我想找到一种方法来修复这些数据库/表。我无法使用表修复功能,因为它会抱怨表不存在,我也无法转储它们,因为它再次抱怨表不存在。
就像我说的,数据本身仍然存在于 .ibd 文件中,并且表名称也存在。我只需要一种方法让 MySQL 识别出数据库中存在这些表(我可以使用十六进制编辑器在 ibdata1 文件中找到相关表的列名)。
知道如何修复此类损坏吗?我不介意卷起袖子,埋头苦干,采取一系列措施来修复它。
多谢。
答案1
我尝试了很多东西,研究了很多命令、开关和结构(毫不奇怪,MySQL 文档是最有帮助的,如果内容很广泛的话——needle/haystack)。最终我的一些技巧奏效了(事实证明其他人也想到了同样的技巧,尽管我没有看到两个主要部分——恢复表结构和恢复数据——放在一个地方,所以我在这里将它们一起发布)。
我所要做的是重新创建 IBDATA1 文件。不幸的是,在运行守护进程检测数据库(目录)时,它不会获取其中的 Innodb 表(IBD/FRM 文件)。所以我所做的是:
- 清空数据目录(或移动原始目录并创建一个空目录)
- 运行守护进程,让它创建一个新的空 IBDATA1 文件
- 使用 SQL 脚本导入系统表
…\MySQL\share
- 创建同名的虚拟数据库和表
- 复制原始 FRM 文件
- 使用其中一种
DESCRIBE
或更好的方法SHOW TABLE CREATE
来提取表结构 - 接下来,我
DISCARD TABLESPACE
在桌子上使用 - 复制原始 IBD 文件
- 然后我用
IMPORT TABLESPACE
- 最后,我重新运行守护进程
innodb-force-recovery=6
- 我跑去
mysqldump
提取结构和数据
当然,过程并不总是一帆风顺的。有些表没问题,但有些需要在之后删除表和数据库SHOW TABLE CREATE
,然后使用它来重新创建表,然后再尝试导入数据。其他的甚至没有那么顺利,我不得不使用十六进制编辑器从 FRM 文件中手动获取列的注释和名称(尽管弄清楚数据类型和属性、键等是什么是一件很困难的事情)。此外,守护进程和客户端重新启动的次数太多了。
(我仍在寻找一种可以直接解析 FRM/IBD 文件的工具(或者至少可以显示 FRM 文件中的表结构),但看起来没有人费心去“逆向工程”它们,尽管它是开源的并且文件格式是公开的。似乎每个人都对使用官方 MySQL 工具感到自满——从而为数据恢复公司和专有/商业工具创造了绝佳的机会。)
关键是始终使用绝对最小值(例如,仅 MYSQL 目录 — 即系统表)。不幸的是,虽然这意味着事情会变得简单和更容易处理,但也意味着一次只能恢复一个表 — 这对我来说不是什么大问题,但对某些人来说可能就是大问题。
无论如何,在过去几天里,我看到了互联网上的许多 MySQL 恢复页面,其中一小部分非常有用,我会在搜索历史记录后将它们添加上去。
希望这可以帮助其他处于类似情况的人。
答案2
能够列出所有表和数据库通常意味着 *.frm 文件在那里。这并不意味着它们有任何数据。您是否尝试过启动 mysqld 进程强制 innodb 恢复? 如果没有,请尝试一下,如果是,启动时 mysql 日志说了什么?
完成后:永远不要再尝试使用这样的备份。