利用.ibd和.frm文件恢复mysql数据

起因

正常重启服务器,导致mysql数据丢失。没有备份,没有备份。所以看完数据库文件之后,都是 table_name.ibd和table_name.frm文件,就因此看看能否恢复。

数据小常识

.frm存放数据库的表结构
.ibd存放数据内容

恢复表结构

创建数据库。一定要注意字符集和排序规则和之前的数据库要一样。任意数据库名称,当前使用game_master

创建表。一定要和恢复的表名称是一样的,假设需要恢复的表是games

在执行上面的创建表语句之后,使用net stop mysql关闭数据库服务,然后用需要恢复的games.frm覆盖这个新建的game_master数据库的games表的物理文件games.frm,接着对配置文件(my.ini)设置innodb_force_recovery = 6,然后使用net start mysql启动服务,接着使用:desc games查看该表结构,会出现下面错误信息:

针对这个问题,我们可以通过查看mysql的日志文件来解决,查看mysql安装目录下的data文件夹里面.err结尾的文件,你会发现出现下面所示的错误信息:[Warning] InnoDB: Table wangyi/songlyric contains 1 user defined columns in InnoDB, but 6 columns in MySQL.原来是因为,我们要恢复的表有6个字段,而我们在创建表的时候只创建了1个字段。
解决方案:删除games表重新创建一个包含6个字段的表,具体这6个字段是什么不用管的。具体执行过程为使用net stop mysql停掉服务,然后在配置文件my.ini中将innodb_force_recovery = 6注释掉(#或;均可),再net start mysql启动服务。接着在控制台先执行drop tablegames;删除表,再执行创建表语句,我执行的是下面的创建表语句:create table games(id int,id1 int,id2 int,id3 int,id4 int,id5 int);
紧接着按照前面的方式,使用net stop mysql关闭数据库服务,然后用需要恢复的games.frm覆盖这个新建的game_master数据库的games表的物理文件games.frm,接着对配置文件(my.ini)设置innodb_force_recovery = 6,然后使用net start mysql启动服务,接着使用:desc games查看该表结构,输出下面结果表示恢复表结构成功:

复制创建games表的语句,我们需要通过创建表的语句重新创建表,当然在创建表之前需要将已经创建好的games删除掉,具体获取创建表的语句可以通过navicat来实现,在navicat中选中games表,右键对象信息,出现下面截图信息,选中DDL,里面的内容就是我们创建games表的sql语句了:

接着在控制台执行drop table games;删除games表,当然在执行删除games命令之前,还需要将my.ini中的innodb_force_recovery = 6删除或者注释掉。接着执行下面命令重新创建表即可:

CREATE TABLE `games` (
 `game_id` int(11) NOT NULL AUTO_INCREMENT,
 `game_name` varchar(96) DEFAULT NULL COMMENT '游戏名称',
 `game_type` int(11) DEFAULT '0' COMMENT '0小程序1H5',
 `status` tinyint(1) DEFAULT '0' COMMENT '0正常 1删除',
 `create_time` int(11) DEFAULT '0' COMMENT '时间',
 `update_time` int(11) DEFAULT '0' COMMENT '更新时间',
  PRIMARY KEY (`game_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; row_format=compact;

可以看到和之前通过navicat查看得到的创建表的sql语句相比,末尾多了ROW_FORMAT=COMPACT;

恢复表数据

恢复表数据需要首先将原先的.ibd文件与原先的.frm文件解除绑定,具体就是在控制台执行下面命令:
alter table games discard tablespace;
接着执行net stop mysql停掉服务,将需要恢复的games.ibd文件覆盖这个新建的game_master数据库的games表的物理文件games.ibd,执行net start mysql开启服务。
将复制过来的games.ibd文件与games.frm文件发生联系。具体执行下面命令:
alter table games import tablespace;
如果都没有报错,恭喜你数据恢复成功。

结束语

不管操作服务器任何项目,一定要定期备份,不要嫌麻烦。开始操作了,最好就是再备份一次最近的数据。
没有遇到问题是不可能滴,折腾了一通宵。
数据库版本一定要一样,这样你能少N多事情。大多数问题,是数据库版本不一致导致的。
alter table 表名 import tablespace;后会报1808号错误,类似错误内容格式如下:
ERROR 1808 (HY000): Schema mismatch (Table has ROW_TYPE_DYNAMIC row format, .ibd file has ROW_TYPE_COMPACT row format.)
究其原因是从MySQL5.7.7版本中innodb_file_format参数(该参数表示innodb文件格式)的默认值发生了变化,在MySQL5.7.7以前innodb_file_format参数默认是Antelope,而默认的行格式是(ROW_FORMAT)是COMPACT,从MySQL5.7.7以后版本innodb_file_format默认值为Barracuda,默认的行格式是(ROW_FORMAT)是DYNAMIC,所以需要在创建表结构时指定row_format=compact

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注