在MySQL运维当中难免会碰到崩溃或损坏的情况。这时就需要对数据库进行尝试恢复。innodb_force_recovery是对MySQL InnoDB存储引擎的“紧急恢复模式”的仅有的一个参数。通过设置不同的值来尝试修复数据。
按照官方对innodb_force_recovery参数的说明,可以选择7个范围值。
取值 | 说明 |
---|---|
0 | 默认值,不启用恢复模式,执行所有的恢复操作。 |
1 | SRV_FORCE_IGNORE_CORRUPT,忽略检查到的损坏页。 |
2 | SRV_FORCE_NO_BACKGROUND,阻止主线程的运行,例如阻止需要执行full purge操作的主线程,否则可能导致崩溃。 |
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,不执行前滚操作,这是一个较为极端的恢复级别,通常作为最后的手段使用。 |
重要点:较大的值包括较小值的功能。例如,值3包括值1和2的所有功能。
在启动innodb_force_recovery修复期间,无论设置成任何值都允许执行SELECT语句,但已4为分界线,一些结构,数据更改操作受到限制。(也有可能数据库服务无法正常处理一些维护任务,会发生一些不确定的行为。)
小于4的情况下
- DML中INSERT,UPDATE,DELETE不允许.
- DDL 中CREATE TABLE,DROP TABLE ,TRUNCATE TABLE支持
其他操作会提示如下信息:
#错误日志记录信息:
ERROR 1881 (HY000): Operation not allowed when innodb_force_recovery > 0.
复制
大于等于4的情况下,除了SELECT语句,其他语句无法执行
#错误日志记录信息:
ERROR 1036 (HY000): Table '**' is read only
ERROR 1881 (HY000): Operation not allowed when innodb_force_recovery > 0.
ERROR 3604 (HY000): Storage engine can't drop table '*'
复制
当i大于6时,MySQL服务会自动选择6值,错误日志也会进行提示。
#vim /etc/my.cnf
innodb_force_recovery=8
#错误日志记录信息:
[InnoDB] !!! innodb_force_recovery is set to 6 !!!
复制
使用场景
当然在进行修复之前,整个数据目录备份必不可少。之后从MySQL错误日志里判断修复级别。选择合适的修复级别非常重要。
场景1:
page损坏,那么MySQL错误日志会记录如下类似信息
[InnoDB] InnoDB: Corrupt page resides in file: .db/t1.ibd
复制
这时需要 innodb_force_recovery改成1,之后重新启动MySQL服务,之后执行DROP TABLE IF EXISTS 命令删除表。就可以。
当然也可以绕过损坏的page,读取没有损坏的页的数据。那这时候 就需要改成3 或 更高值,使得其他数据得以正常读取。
场景2:
长时间未提交的事务。如,在大表操作中,突然断电,内存OOM,磁盘满等情况,最终导致MySQL服务Crash损坏情况,并且无法正常启动,那就可以推断Undo 或 Redo方面没有完成。这时只要跳过事务回滚或提交操作,就可以让服务MySQL服务运行下来。
备注:初始就选择最大级别恢复,甚至可能导致更严重的损坏。所以建议先从最小的级别开始尝试。
总结
innodb_force_recovery是MySQL数据的“止损剂”。跳过某些恢复步骤(1-6),让MySQL服务尽可能启动起来。但可能导致数据不一致 或 部分数据无法恢复。更深入理解每个级别的具体影响,如何在实践中正确使用这个参数,同时避免数据丢失。
当然仅靠InnoDB崩溃恢复y参数还是不够,实际场景中,也存在无法修复,启动MySQL服务失败的情况。所以还必须依赖备份和高可用架构。
参考:
https://dev.mysql.com/doc/refman/8.4/en/forcing-innodb-recovery.html
评论
