忠人之事受人之托 起因是因为一位朋友的数据库服务器被重装了,只剩下一个zbp_post.frm和zbp_post.ibd文件。咨询我能不能恢复,确实我只用过mysqldump这种工具导出数据 然后进行恢复到数据库。这种直接备份物理存储文件还没有尝试过。

前提是需要历史ibd文件的所属数据库版本 需要和还原新库数据库版本保持一致,这样才能少踩坑。

创建表结构

要想恢复数据,表结构需要和.ibd里面的结构保持一致,如果不一致将恢复不成功 可能会报如下错误。或者其他异常。

[ERROR] InnoDB: Trying to access page number 426442752 in space 24, space name test1/zbp_post, which is outside the tablespace bounds. Byte offset 0, len 16384, i/o type read. If you get this error at mysqld startup, please check that your my.cnf matches the ibdata files that you have in the MySQL server.
获取表结构

如果明确知道表结构 这一步可跳过。不知道表结构可从这一步操作中获取到表结构。

借助了mysql utilities工具来查看表结构。

安装mysql utilities

这里我适用window 其他系统也是类似的操作 下载后安装好。

https://downloads.mysql.com/archives/get/p/30/file/mysql-utilities-1.6.5-winx64.msi

其他系统下载地址 https://downloads.mysql.com/archives/

进入zbp_post.frm目录中执行获取表结构命令。

cd zbp_post
mysqlfrm --diagnostic ./zbp_post.frm

执行完mysqlfrm命令后 输出如下表结构

CREATE TABLE `zbp_post` (
`log_ID` int(11) NOT NULL AUTO_INCREMENT,
`log_CateID` int(11) NOT NULL,
`log_AuthorID` int(11) NOT NULL,
`log_Tag` varchar(1000) NOT NULL,
`log_Status` tinyint(4) NOT NULL,
`log_Type` int(11) NOT NULL,
`log_Alias` varchar(1000) NOT NULL,
`log_IsTop` tinyint(4) NOT NULL,
`log_IsLock` tinyint(4) NOT NULL,
`log_Title` varchar(1000) NOT NULL,
`log_Intro` text,
`log_Content` longtext,
`log_CreateTime` int(11) NOT NULL,
`log_PostTime` int(11) NOT NULL,
`log_UpdateTime` int(11) NOT NULL,
`log_CommNums` int(11) NOT NULL,
`log_ViewNums` int(11) NOT NULL,
`log_Template` varchar(1000) NOT NULL,
`log_Meta` longtext,
`log_BdPush` int(11) NOT NULL,
PRIMARY KEY `PRIMARY` (`log_ID`),
KEY `zbp_log_TPISC` (`log_Type`,`log_PostTime`,`log_IsTop`,`log_Status`,`log_CateID`),
KEY `log_CateID` (`log_CateID`),
KEY `log_AuthorID` (`log_AuthorID`),
KEY `log_PostTime` (`log_PostTime`),
KEY `log_CommNums` (`log_CommNums`),
KEY `log_ViewNums` (`log_ViewNums`),
KEY `log_Title` (`log_Title`)
) ENGINE=InnoDB;

数据库配置修改

编辑MySQL的配置文件,通常是my.cnf或my.ini文件,在[mysqld]部分添加以下行:

这将确保每个表有单独的.ibd文件。

[mysqld]
innodb_file_per_table=1
wait_timeout=600 #600秒(10分钟)

wait_timeout=600 这个配置可以不加 访问还原数据比较大。执行超时的情况。需要根据场景酌情配置。

开始恢复数据

创建新数据库

创建一个数据库 任意数据库名。

create database test1;
创建表

进入到新创建的数据库中(use test1),复制上一步中的表结构SQL。执行创建表结构操作。

使用.ibd文件恢复数据到新表

卸载表空间 执行此步会自动删除新表对应的.ibd文件

ALTER TABLE zbp_post DISCARD TABLESPACE;

拷贝备份的.ibd文件到新创建数据库对应的目录中。

一般目录在mysql保存数据库的目录。如我当前的服务器mysql数据保存的目录在/usr/local/mysql/data,数据库名 test1 ,表名 zbp_post。

那么拷贝.ibd文件的目录为 /usr/local/mysql/data/zbp_post/test1中。

装载表空间

ALTER TABLE zbp_post IMPORT TABLESPACE;

完成以上步骤后,您应该能够成功还原.ibd文件。请注意,这种方法仅适用于InnoDB引擎的表。如果.ibd文件损坏或不匹配,可能需要使用MySQL的数据恢复工具来修复数据库。

验证

果然完美

mysql> select count(1) from zbp_post;
+----------+
| count(1) |
+----------+
| 785216 |
+----------+
1 row in set (0.15 sec)

如果有朋友遇到类似问题可以和我联系。