最近在开发过程中,由于电脑突然死机需要重启,重启后导致mysql启动不了,因为电脑崩溃时mysql数据文件错误,此时可以使用innodb_force_recovery选项来恢复。
下面是对官方的innodb_force_recovery文档翻译
Mysql版本:5.5
为了验证数据库页面是否损坏,可以使用SELECT ... INTO OUTFILE从数据库导出数据表。一般情况下以这种方式获得的数据大多数是完整的。但如果是损坏严重的数据可能导致SELECT * FROM tbl_name语句或InnoDB后台操作崩溃或断言,甚至导致InnoDB回滚恢复崩溃。在这种情况下,可以使用innodb_force_recovery选项让InnoDB存储引擎强制启动,同时防止后台操作运行,这样可以转储表了。例如,您可以在重新启动服务器之前将以下行添加到mysql配置文件的[mysqld]下面:
[mysqld]
innodb_force_recovery = 1
注意
在进行这个操作之前,务必备份数据库。
在紧急情况下,为了可以启动InnoDB并转储表,必须将innodb_force_recovery设置为大于0的值。
4或更高的值可能会永久损坏数据文件。在测试数据库的单独物理副本上操作成功后,才能在生产服务器使用4或更高版本的innodb_force_recovery设置。当InnoDB强制恢复时,应该始终以innodb_force_recovery = 1开始,并根据需要逐渐增加值。为什么从1开始呢,因为1是最保险的,可以看后面对不同值的解释。
innodb_force_recovery默认为0(正常启动)。 innodb_force_recovery的非零值是从1到6。较大的值包括较小值的功能。例如,3包括1和2的所有功能。
innodb_force_recovery值为3或更小时,只有损坏的单个页面上的某些数据丢失。 4或更高的值是危险的,因为数据文件可能永久损坏。6不建议使用,因为数据库页面处于过时状态,这陆续可能在B树和其他数据库结构中引入更多的损坏。
为了安全起见,InnoDB在innodb_force_recovery大于0时会阻止INSERT,UPDATE或DELETE操作。
【Mysql 5.7】
在innodb只读模式下innodb_force_recovery可以设置为4或更大值
1 (SRV_FORCE_IGNORE_CORRUPT)
当检测到损坏的页面时继续让服务器运行。 导出表时尝试SELECT * FROM tbl_name跳过损坏的索引记录和页面。
2 (SRV_FORCE_NO_BACKGROUND)
阻止主线程和任何废止线程运行。 设置为2可以在废止操作期间阻止崩溃。
3 (SRV_FORCE_NO_TRX_UNDO)
崩溃后恢复时不执行事务回滚
4 (SRV_FORCE_NO_IBUF_MERGE)
阻止写入缓冲区合并操作。 如果会造成事故,不做写入,不计算表统计。 此类型可能会永久损坏数据文件。 需要删除并重新创建所有辅助索引。innoDB设置为只读模式【Mysql 5.7】
5 (SRV_FORCE_NO_UNDO_LOG_SCAN)
启动数据库时不查看undo日志:InnoDB会将不完整的事务视为已提交。 设置为此值可能会永久损坏数据文件。innoDB设置为只读模式【Mysql 5.7】
6 (SRV_FORCE_NO_LOG_REDO)
无法将与恢复相关联的重做日志恢复。设置此值可能会永久损坏数据文件。让数据库页面处于过时状态,从而可能会在B树和其他数据库结构中引入更多的损坏。innoDB设置为只读模式【Mysql 5.7】
即使开启了innodb_force_recovery设置也可以使用SELECT from tables导出表数据或者删除、创建表。如果知道在回滚时会引起崩溃,可以直接删除这个表。
【Mysql 5.7】
可以使用 SELECT from tables来导出表数据。innodb_force_recovery设置为3及以下时可以创建和删除表。当然如果mysql版本低于5.7.18,innodb_force_recovery设置为3以上也是可以删除表的,从5.7.18起被禁止了。
您还可以使用它来停止由大量导入失败导致的失控回滚或ALTER TABLE操作:
杀掉mysql进程并将innodb_force_recovery设置为3,让数据库升级而不进行回滚,然后删除导致失控回滚的表。
如果表数据中的损坏而导出不了,可以使用ORDER BY primary_key DESC子句的查询将损坏部分后的数据导出来。
如果innodb_force_recovery必须要设置很大的值才能启动innodb,这可能会导致复杂查询(包含WHERE,ORDER BY或其他子句的查询)失败。这时候只能运行基本的SELECT * FROM t查询。