小明同窗在本机上安装了 MySQL 5.7.17 配合项目进行开发,而且已经有了一部分重要数据。某天小明在开发的时候,须要出去一趟就直接把电脑关掉了,没有让 MySQL 正常关闭,重启 MySQL 的时候,报错以下:html
... [ERROR] InnoDB: Space id and page no stored in the page, read in are [page id: space=3611051955, page number=1571966525], should be [page id: space=86, page number=4] ... [ERROR] InnoDB: Database page corruption on disk or a failed file read of page [page id: space=86, page number=4]. You may have to recover from a backup. ... [ERROR] [FATAL] InnoDB: Aborting because of a corrupt database page in the system tablespace. Or, there was a failure in tagging the tablespace as corrupt. ...
从日志内容来看,MySQL 在机器关机的时候有数据没有落地,表空间损坏,致使重启以后没法正常恢复,线程在数据页中读取不到须要的 page 和数据。mysql
须要作特殊操做,让 MySQL 跳过恢复,启动 MySQL,而后把数据导出来,再重建数据库导入。sql
MySQL 有个一个特性:Forcing InnoDB Recovery,启用这个特性须要设置 innodb_force_recovery 大于 0。数据库
innodb_force_recovery 能够设置为 1-6,大的值包含前面全部小于它的值的影响。安全
1 (SRV_FORCE_IGNORE_CORRUPT): 忽略检查到的 corrupt 页。尽管检测到了损坏的 page 仍强制服务运行。通常设置为该值便可,而后 dump 出库表进行重建。 2 (SRV_FORCE_NO_BACKGROUND): 阻止主线程的运行,如主线程须要执行 full purge 操做,会致使 crash。 阻止 master thread 和任何 purge thread 运行。若 crash 发生在 purge 环节则使用该值。 3 (SRV_FORCE_NO_TRX_UNDO): 不执行事务回滚操做。 4 (SRV_FORCE_NO_IBUF_MERGE): 不执行插入缓冲的合并操做。若是可能致使崩溃则不要作这些操做。不要进行统计操做。该值可能永久损坏数据文件。若使用了该值,则未来要删除和重建辅助索引。 5 (SRV_FORCE_NO_UNDO_LOG_SCAN): 不查看重作日志,InnoDB 存储引擎会将未提交的事务视为已提交。此时 InnoDB 甚至把未完成的事务按照提交处理。该值可能永久性的损坏数据文件。 6 (SRV_FORCE_NO_LOG_REDO): 不执行前滚的操做。恢复时不作 redo log roll-forward。使数据库页处于废止状态,继而可能引发 B 树或者其余数据库结构更多的损坏。
注意:服务器
为了安全,当设置参数值大于 0 后,能够对表进行 select, create, drop 操做,但 insert, update 或者 delete 这类操做是不容许的。MySQL 5.6.15 之后,当 innodb_force_recovery 的值大于等于 4 的时候,InnoDB 表处于只读模式。 在值小于等于 3 时能够经过 select 来 dump 表,能够 drop 或者 create 表。MySQL 5.6.27 后大于 3 的值也支持 DROP TABLE; 若是事先知道哪一个表致使了崩溃则可 drop 掉这个表。若是碰到了由失败的大规模导入或大量 ALTER TABLE 操做引发的 runaway rollback,则可 kill 掉 mysqld 线程而后设置 innodb_force_recovery = 3 使数据库重启后不进行 rollback。而后删除致使 runaway rollback 的表; 若是表内的数据损坏致使不能 dump 整个表内容。那么附带 order by primary_key desc 从句的查询或许可以 dump 出损坏部分以后的部分数据; 若使用更高的 innodb_force_recovery 值,那么一些损坏的数据结构可能引发复杂的查询没法运行。此时可能只能运行最基本的 select * from table 语句。
前面说了,表空间损坏,重启时前滚恢复失败,所以在重启的时候不要执行前滚的操做,在 /etc/mysql/my.cnf 中添加:数据结构
[mysqld] innodb_force_recovery = 6
而后重启 MySQL,当即对数据库用 mysqldump 把数据导出。完成后,去掉 innodb_force_recovery 或者设置为 0,而后从新建立数据库,把数据导入。测试
这个方法仅仅是紧急状况下的一种补救,不能依赖于这个办法,最好是作好数据备份工做,包括全备份和日志备份。肯定要使用该方案是要确保有原始损坏数据的副本。4 以上的值可能永久致使数据文件损坏。务必在测试环境测试经过后再在生产环境使用。spa
MySQL crash 或者 MySQL 服务器 crash 会致使各类各类的问题 ,对于主从复制关系,MySQL 5.6 版本开始新增了 crash-safe 的特性,能够在最大程度上避免 error 1594 的问题,保证数据的安全,如何开启这个功能能够参考上一篇博文:MySQL 5.6 从库开启 crash-safe 功能。线程
做为一个 DBA,遇到问题,要淡定,细心阅读日志,从中找的相关错误提示,而后依据错误找到相关的解决方法来解决问题。