记录日常工作关于系统运维,虚拟化云计算,数据库,网络安全等各方面问题。

设你正在运行使用InnoDB表格的MySQL,糟糕的硬件设备,驱动程序错误,内核错误,不幸的电源故障或某些罕见的MySQL错误使你的InnoDB表空间被损坏了。

在这种情况下,InnoDB的一般会出现这样的输出:


InnoDB: Database page corruption on disk ora failed
InnoDB: file read of page 7.
InnoDB: You may have to recover from a backup.
080703 23:46:16 InnoDB: Page dump in ascii and hex (16384bytes):
... 这里省略很多二进制和十六进制编码...
080703 23:46:16 InnoDB: Page checksum 587461377,prior-to-4.0.14-form checksum 772331632
InnoDB: stored checksum 2287785129, prior-to-4.0.14-form storedchecksum 772331632
InnoDB: Page lsn 24 1487506025, low 4 bytes of lsn at page end1487506025
InnoDB: Page number (if stored to page already) 7,
InnoDB: Database page corruption on disk or a failed


mysqldump导出库时报错如下:

"mysqldump: Error 2013: Lost connection to MySQL server during query when dumping table `; at row:6880"

或是操作对应表时,也会报错。这时数据库会重启。

当时想到的是在修复之前保证数据库正常,不是这么异常的无休止的重启。



二、问题分析

从日志中可以看出是innodb引擎出了问题。日志里提示到 http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.html查看强制恢复的方法。在mysql的配置文件my.cnf里找到 [mysqld]字段下,添加 innodb_force_recovery=1:

[plain] view plain copy
  1. [mysqld]  
  2. innodb_force_recovery = 1  
如果innodb_force_recovery = 1不生效,则可尝试2——6几个数字
然后重启mysql,重启成功。然后使用mysqldump或 pma 导出数据,执行修复操作等。修复完成后,把该参数注释掉,还原默认值0。
配置文件的参数:innodb_force_recovery
innodb_force_recovery影响整个InnoDB存储引擎的恢复状况。默认为0,表示当需要恢复时执行所有的恢复操作(即校验数据页/purge undo/insert buffer merge/rolling back&forward),当不能进行有效的恢复操作时,mysql有可能无法启动,并记录错误日志;
innodb_force_recovery可以设置为1-6,大的数字包含前面所有数字的影响。当设置参数值大于0后,可以对表进行select,create,drop操作,但insert,update或者delete这类操作是不允许的。
  • 1(SRV_FORCE_IGNORE_CORRUPT):忽略检查到的corrupt页。
  • 2(SRV_FORCE_NO_BACKGROUND):阻止主线程的运行,如主线程需要执行full purge操作,会导致crash。
  • 3(SRV_FORCE_NO_TRX_UNDO):不执行事务回滚操作。
  • 4(SRV_FORCE_NO_IBUF_MERGE):不执行插入缓冲的合并操作。
  • 5(SRV_FORCE_NO_UNDO_LOG_SCAN):不查看重做日志,InnoDB存储引擎会将未提交的事务视为已提交。
  • 6(SRV_FORCE_NO_LOG_REDO):不执行前滚的操作。

三、解析方案

一般修复方法参考:

第一种方法

建立一张新表:
create table demo_bak  #和原表结构一样,只是把INNODB改成了MYISAM。
把数据导进去
insert into demo_bak select * from demo;
删除掉原表:
drop table demo;
注释掉 innodb_force_recovery 之后,重启。
重命名:
rename table demo_bak to demo;
最后改回存储引擎:
alter table demo engine = innodb

第二种方法

另一个方法是使用mysqldump将表格导出,然后再导回到InnoDB表中。这两种方法的结果是相同的。
备份导出(包括结构和数据):
mysqldump -uroot -p123 test > test.sql
还原方法1:
use test;
source test.sql
还原方法2(系统命令行):
mysql -uroot -p123 test < test.sql;
注意,CHECK TABLE命令在InnoDB数据库中基本上是没有用的。

第三种方法

1、配置my.cnf

配置innodb_force_recovery = 1或2——6几个数字,重启MySQL

2、导出数据脚本

mysqldump -uroot -p123 test > test.sql
导出SQL脚本。或者用Navicat将所有数据库/表导入到其他服务器的数据库中。
注意:这里的数据一定要备份成功。然后删除原数据库中的数据。

3、删除ib_logfile0、ib_logfile1、ibdata1

备份MySQL数据目录下的ib_logfile0、ib_logfile1、ibdata1三个文件,然后将这三个文件删除

4、配置my.cnf

将my.cnf中innodb_force_recovery = 1或2——6几个数字这行配置删除或者配置为innodb_force_recovery = 0,重启MySQL服务

5、将数据导入MySQL数据库

mysql -uroot -p123 test < test.sql; 或者用Navicat将备份的数据导入到数据库中。
此种方法下要注意的问题:
  1、ib_logfile0、ib_logfile1、ibdata1这三个文件一定要先备份后删除;
  2、一定要确认原数据导出成功了
  3、当数据导出成功后,删除原数据库中的数据时,如果提示不能删除,可在命令行进入MySQL的数据目录,手动删除相关数据库的文件夹或者数据库文件夹下的数据表文件,前提是数据一定导出或备份成功。



转载请标明出处【MySQL崩溃-修复损坏的innodb:innodb_force_recovery 】。

《www.micoder.cc》 虚拟化云计算,系统运维,安全技术服务.

网站已经关闭评论