admin 管理员组

文章数量: 887617

摘要:

在实际工作中遇到了mysql服务器硬盘挂掉的情况,并且无slave无备份。此时就只能去恢复硬盘的数据了。本文根据一次实战操作整理,分别用4种办法尝试修复数据。我们首先拿到了坏硬盘上的文件,在新服务器上安装同样版本的mysql准备恢复。

普通恢复:

此方式是把mysql的数据目录与myf文件拷贝到新数据库目录,正常启动数据库。如果数据目录没有损坏,正常启动后应能正常读写数据,error日志无报错。

但是我们恢复时报了大量的错误,由此可见ibdata文件或redo日志已经被损坏,继续使用其他方式恢复。

附部分error信息:

InnoDB: Database page corruption on disk or a failed

InnoDB: file read of page 5.

InnoDB: You may have to recover from a backup.

InnoDB: See also http://dev.mysql/doc/refman/5.5/en/forcing-innodb-recovery.html

InnoDB: about forcing recovery.

InnoDB: Starting crash recovery.

InnoDB: Reading tablespace information from the .ibd files...

InnoDB: Error: space id in fsp header 3221244024, but in the page header 268454008

InnoDB: Error: tablespace id 4294967295 in file .\game\area_element_table.ibd is not sensible

InnoDB: Cannot continue operation.

InnoDB: You can try to recover the database with the myf

InnoDB: option:

InnoDB: innodb_force_recovery=6

InnoDB: If you get repeated assertion failures or crashes, even

InnoDB: immediately after the mysqld startup, there may be

InnoDB: corruption in the InnoDB tablespace. Please refer to

InnoDB: http://dev.mysql/doc/refman/5.5/en/forcing-innodb-recovery.html

InnoDB: about forcing recovery.

innodb_force_recovery方式:

我们根据上面的error日志提供的信息,在myf的[mysqld]里面加入参数innodb_force_recovery,使用1-6级逐步尝试恢复。参考链接:http://who0168.blog.51cto/253401/551068

这种方式对于常规的数据库崩溃或服务器崩溃是奏效的,可以绕过损坏的redo log。但我们实际操作时将级别提升至6仍无法启动,说明ibdata可能有损坏。继续下面的修复方式。

附部分error信息:

error日志和上面的差不多,这里仅贴出有差异的部分

InnoDB: The user has set SRV_FORCE_NO_LOG_REDO on

InnoDB: Skipping log redo

InnoDB: Database page corruption on disk or a failed

InnoDB: file read of page 7.

InnoDB: Error: trying to access page number 16766859 in space 0,

InnoDB: space name .\ibdata1,

InnoDB: which is outside the tablespace bounds.

InnoDB: Byte offset 0, len 16384, i/o type 10.

InnoDB: If you get this error at mysqld startup, please check that

InnoDB: your myf matches the ibdata files that you have in the

InnoDB: MySQL server.

修复ibdata方式:

独立表空间模式下,ibdata的作用是存放内部数据字典和重作日志。 在ibdata文件丢失或损坏的情况下,利用frm和ibd文件,以及数据库的表结构,也可以尝试恢复数据。

1、DISCARD、IMPORT TABLESPACE方式:

注:此方式未修复成功,仅供参考

1)新建数据库,创建需要恢复的数据库的表结构。

2)service mysqld stop,将需要恢复的frm文件覆盖刚刚新建的frm,并设置权限为mysql。service mysqld start,启动时加上参数innodb_force_recovery=6。

3)ALTER TABLE xx DISCARD TABLESPACE; 复制ibd文件到数据目录。service mysqld stop

4)service mysqld start,启动时加上参数innodb_force_recovery=6。再ALTER TABLE xx IMPORT TABLESPACE;

2、修改ibd文件方式:

注:此方式亲测可用

1)新建数据库,创建需要恢复的数据库的表结构。

2)使用vim打开此表的ibd文件,16进制查看

[root@localhost test]# vim -b tmp.ibd

:%!xxd

3)使用vim打开要恢复的ibd文件,16进制查看

4)修改要恢复的ibd文件,将红方框中的值修改的和刚刚创建的新表的ibd文件一致。看到后面大段的0000没,我们只需要修改文件头就可以了。00000c0以后的不用修改。

[root@localhost test]# vim -b tmp.ibd:%!xxd -r     #一定要先执行这一步

:wq

5)拿需要恢复的ibd文件覆盖刚刚创建的新表的ibd文件。修改文件权限为mysql用户。

6)重启mysql,重启时加上参数innodb_force_recovery = 6。

7)执行select操作,读取正常,但无法执行更新操作。将数据dump出来,重建表。找回数据成功。

mysqlbinlog方式:

在沟通的过程中我们了解到,在此前他们对数据库进行过一次清空操作。如果能找到当时清空数据库的时间点,利用mysqlbinlog进行一次日志回放,也是可行的。

实际操作过程中对方无法提供清空数据库的准确时间点,回放binlog时错误不断,数据的准确性无法保证,最终作罢。

此方式的适用场景:

1)有此前的数据库备份及备份后的binlog

2)能查到清空数据库的时间点

参考资料:

1.http://dev.mysql/doc/refman/5.5/en/forcing-innodb-recovery.html

2.http://who0168.blog.51cto/253401/551068

3.Mysql ibdata 丢失或损坏如何通过frm&ibd 恢复数据 http://www.lanceyan/tech/mysql/lost-ibdata-recover-data.html

4.MySQL:如何从ibd文件中恢复数据  http://www.dedecms/knowledge/data-base/mysql/2012/0819/7558.html

本文标签: 数据恢复 硬盘 服务器 电脑 MySQL