环境

操作系统:CentOS 7 Mysql版本:Mysql 8.0.x Docker版本:Docker version 20.10.10

问题

mysql服务是通过Docker方式部署,一次重启导致mysql容器无法正常启动,查看发现mysql容器一直在不断启动…断开…启动…断开,之所以会这样是因为起初创建mysql容器是设置了:–restart always 就是只要Docker服务活着,该容器就会启动,如果断开了就会自动重启,由于崩溃,Mysql无法启动,然后docker再尝试重启,就这样陷入了循环… 摘取一段mysql容器报错日志

2022-05-23T03:29:02.744075Z 1 [ERROR] [MY-011972] [InnoDB] Your database may be corrupt or you may have copied the InnoDB tablespace but not the InnoDB log files. Please refer to http://dev.mysql.com/doc/refman/8.0/en/forcing-innodb-recovery.html for information about forcing recovery.

查看mysql容器日志看到一段信息,大概意思是存储引擎可能已经损坏,给出一个官方文档地址

解决

既然官方已经给出了解决文档,就去看了一下,文档地址:https://dev.mysql.com/doc/refman/8.0/en/forcing-innodb-recovery.html 翻译了一下网页 官方的意思是,通过设置存储引擎强制恢复的级别来实现暂时能使mysql服务启动,以方便把数据备份出来,一共给了6个级别

[mysqld]
innodb_force_recovery = 1

使用的时候,可以先从小往大一个级别一个级别去设置,不要直接从1调到5/6这样,小编是尝试设置到了3就能正常启动了,不过启动后,mysql只有查询权限,没有写入权限,官方文档里也说了,这样就是为了暂时启动,将数据备份出来 关于如何在docker容器方式部署mysql时修改配置文件,参考:Docker环境下Mysql跳过密码验证

摘取官方

作为安全措施,InnoDB防止 INSERT、 UPDATE、 或 大于 0DELETE时的操作 。只读模式下 4 位或更多位的设置。innodb_force_recoveryinnodb_force_recoveryInnoDB 1 ( SRV_FORCE_IGNORE_CORRUPT) 让服务器即使检测到损坏的 页面也能运行。尝试 跳过损坏的索引记录和页面,这有助于转储表。 SELECT * FROM tbl_name 2 ( SRV_FORCE_NO_BACKGROUND) 阻止主线程和任何清除线程运行。如果在清除操作期间发生意外退出,此恢复值会阻止它。 3 ( SRV_FORCE_NO_TRX_UNDO) 崩溃恢复后 不运行事务 回滚。 4 ( SRV_FORCE_NO_IBUF_MERGE) 防止插入缓冲区合并操作。如果它们会导致崩溃,请不要这样做。不计算表 统计信息。此值可能会永久损坏数据文件。使用此值后,准备删除并重新创建所有二级索引。设置 InnoDB为只读。 5 ( SRV_FORCE_NO_UNDO_LOG_SCAN) 启动数据库时 不查看撤消日志InnoDB:甚至将不完整的事务视为已提交。此值可能会永久损坏数据文件。设置InnoDB为只读。 6 ( SRV_FORCE_NO_LOG_REDO) 不执行与恢复相关的重做日志 前滚。此值可能会永久损坏数据文件。使数据库页面处于过时状态,这反过来可能会给 B 树和其他数据库结构带来更多损坏。设置 InnoDB为只读。 您可以SELECT从表中转储它们。innodb_force_recovery值为 3 或更少时,您可以或 DROP表格 CREATE。DROP TABLE也支持 innodb_force_recovery大于 3的值。DROP TABLE不允许 innodb_force_recovery大于 4 的值。 如果您知道给定表导致回滚时意外退出,则可以将其删除。如果遇到由于批量导入失败而导致的失控回滚ALTER TABLE,您可以终止 mysqld 进程并设置 innodb_force_recovery为 3在不回滚的情况下启动数据库,然后DROP是导致失控回滚的表。 如果表数据中的损坏阻止您转储整个表内容,则带有子句的查询可能能够转储损坏部分之后的表部分。 ORDER BY primary_key DESC innodb_force_recovery 如果start 需要 一个高值InnoDB,则可能存在损坏的数据结构,这可能导致复杂查询(包含WHERE、ORDER BY或其他子句的查询)失败。在这种情况下,您可能只能运行基本SELECT * FROM t 查询。