Linux MySQL服务异常断电恢复方法
异常断电无法启动原因
现在MySQL一般都是用的innodb这种存储引擎,在开始一个事务进行数据的修改时,数据会首先写入到InnoDB的重做日志(redo log),到了一定的程度(例如,达到了特定的时间间隔或日志大小)才会写入到硬盘的文件中。
如果这个时候服务突然崩溃了,例如断电。然后再重新启动MySQL得时候,MySQL会检测到InnoDB数据文件和重做日志之间存在不一致性,然后就会通过一些方法来使得硬盘上的数据何redo log中的数据一致,如果重做日志本身受到损坏就没法完成这个数据的恢复过程,无法保证数据的一致性,MySQL就不给启动。
解决方法
1、启用 innodb_force_recovery
设置 innodb_force_recovery 参数后,InnoDB引擎会尝试跳过某些操作,从而忽略一些错误来启动数据库,当innodb_force_recovery的值从4开始时,数据库就会变为只读模式。
innodb_force_recovery可以设置6个值
-
0:默认值。不采取特殊措施
-
1 :让服务器忽略某些潜在的损坏页面错误
-
2 :阻止主线程的运行,这避免了创建新的 redo log 项
-
3 :不执行事务回滚操作
-
4 :阻止插入缓冲区的合并操作
-
5 :不查看撤销日志,这意味着不会尝试恢复任何未完成的事务
-
6 :不执行 redo 日志回放
当使用 innodb_force_recovery 选项时,通常先将其值设为1,并尝试重启服务。如果服务启动失败,则逐步将该值从1增加到6,每次修改后尝试重新启动服务。
例如:
[mysqld]
innodb_force_recovery=6
2、检查数据表
MySQL服务正常启动用后,使用mysqlcheck检查是否表是否损坏,如果损坏进行修复
mysqlcheck -u [username] -p --auto-repair --check --all-databases
说明:
-
--auto-repair 选项会在检测到问题时自动尝试修复表
-
--check 选项用于检查表的完整性
-
--all-databases 选项确保检查所有数据库中的所有表
如果指向检查特定的数据库:
mysqlcheck -u [username] -p [database_name]
如果向修复特定数据库的所有表
mysqlcheck -u [username] -p --repair [database_name]
如果想修复特定数据库的特定表:
mysqlcheck -u [username] -p --repair [database_name] [table_name]
3、数据备份
如果检查无误后,通过mysqldump工具备份数据库,如果数据量不是太大的情况,可以直接使用全备份。
mysqldump -uroot -p -A -F --single-transaction --flush-privileges --default-character-set=utf8 > mysqlall_back.sql
4、重置数据目录
先停止MySQL服务,然后将原有的数据目录进行重命名,并且重新创建一个数据目录。
例如:假设MySQL的数据目录为/var/lib/mysql
mv /var/lib/mysql /var/lib/mysql_bak
mkdir /var/lib/mysql
chown mysql:mysql /var/lib/mysql
5、初始化基本数据
使用mysqld --initialize 或 mysqld --initialize-insecure 初始化mysql的基本数据。
# 初始化得root用户无密码,可以无密码登录
mysqld --initialize-insecure
# 这个命令会为root用户创建一个临时随机密码 在MySQL错误日志中找到这个随机生成的临时密码
mysqld --initialize
说明:
mysqld --initialize 和 mysqld --initialize-insecure 是从MySQL 5.7.6 开始引入的,用以替代旧的mysql_install_db工具
初始化基本数据注意事项:
1、需要确保MySQL的数据目录是空的,即里面没有任何内容
2、需要确保MySQL服务的进行是停止状态,不然只会再数据目录生成部分文件。例如:只会生成一个auto.conf文件
3、需要确保MyQL配置文件中的 innodb_force_recovery 选项不是启用状态
4、用户必须有足够的权限来创建、写入和修改MySQL的数据目录中的文件和子目录,所以可以用root用户身份来执行,如果不成功就用mysql用户来下执行。sudo -u mysql mysqld --initialize-insecure
6、重启MySQL
重新启动MySQL服务
systemctl start mysql.service
7、数据还原
将上面备份的数据进行还原
sudo systemctl start mysql.service
mysql -uroot -p < mysqlall_back.sql
重新导入数据能恢复正常的原因
1、 清除损坏数据: 在导入数据之前,您通常会首先清空或删除原始数据库中的所有数据。这意味着所有的损坏数据、损坏的索引和其他可能的问题都将被移除。
2、 重建数据: 重新导入数据时,数据文件将从头开始重新创建。这意味着任何受损的数据页、损坏的索引或其他底层结构都会被新的、整洁的结构替代。
3、 重新生成redo log: 从备份重新导入数据时,MySQL会在事务提交时写入新的redo log条目。因此,任何受损的、旧的redo log条目都会被忽略,并且不会影响新导入的数据。