2024年2月18日发(作者:)

利用frm 和 idb文件批量还原数据

最近碰到一个问题,一个平时不怎么用数据库在一次搬机器过程中弄挂了,然后在重启过程中不小心把ibdata给弄坏了。于是无奈只能通过frm和idb文件来做数据恢复。因为是整个库的数据有问题,因此在这过程中写了一些脚本来帮助恢复。

下面是这次操作的过程:

首先说明,本方案只适用于 innodb_file_per_table = 1 这种情况下的做数据恢复。

下面是用来说明恢复案例的环境:

原数据库数据文件的位置: /data/dbdata

库名称: user

新库的用户名、密码:root/111111

新库的数据文件位置:/data/newdata

1、首先做好frm和idb文件的备份,并准备一个全新的MySQL环境,至于为什么要全新的,稍后就会明白。

2、通过frm文件导出表结构

如果你本身就有创建数据的schema的sql脚本,这一步可以略过。

a、首先创建user库;

> create database user;

b、接下来需要在user库创建原库的frm对应的表,这一步可通过 create_init_【/iamxhu/devops_tools/blob/master/mysql/recovery/create_init_】生成创建表的脚本。具体使用方法参加文件中的说明。

$ ./create_init_ /data/dbdata/user root 111111 user

运行上面的脚本后,会生成三个文件:create_tmp_,discard_,import_。在这一步只需要将create_tmp_导入到mysql中。

> mysql -uroot -p user < create_tmp_

这样表就都创建好了。

c、 关闭mysql,修改 在[mysqld]段中增加如下配置:

innodb_force_recovery = 6

d、将需要恢复的frm文件替换新的库是的frm文件

$ cp /data/dbdata/user/*.frm /data/newdata/user/

e、重启mysql 这时登录就可以看到恢复好的表结构了。

3、恢复idb中的数据

a、首先需要找出原来的idb中的space id,可通过下面的方法完成/iamxhu/devops_tools/blob/master/mysql/recovery/find_mysql_ 。

$ ./find_mysql_ /data/dbdata/user root 111111 user

脚本将会生成一个文件:export_table_。 这个文件主要是用来导出新生成表的建表语句create_。生成的create_需要再手动处理一下,删除开头的表名。

因为针对一个库,可能其中表的space id不一定是连续的,因此第一步生成的表不能直接使用需要重新建表。create_会根据space id的之间的差值,自动插入一些临时表来填充space id。

b、注释掉innodb_force_recovery = 6 重启mysql继续下面的操作。

c、找出最小的space id,在MySQL中填充好space id。

这一步需要注意,不要填多了,否则又要重新弄一个新的MySQL环境了。最好分两部做,先留100个space id,在生成完第一批表之后查看一下最后生成的表的space id再填充后面的space id。

填充space id可以使用 fill_table_ 脚本来完成。用法如下:

$./fill_table_ 100 root 111111

d、填充完成后,执行导入表结构。

如下操作:

$ mysql -uroot -p user < create_

e、执行discard_脚本,做discard tablespace操作。

$ ./discard_

f、将原来的idb文件拷贝到现在的user库目录下,并修改权限

$ chown /data/newdata/user/*.idb

g、执行import_

$./import_

h、在中将innodb_force_recovery = 6 的注释打开,然后重启MySQL。

这时候可以登录进去看看数据是不是都存在了。如果一切都OK的话,接下来可以执行export_table_脚本,导出数据了。 然后你也可以直接dump出sql文件。

本文作者胡星,现任职于华强北商城,原文转自博客:/