记一次断电导致的mysql数据恢复问题

Posted 保融融汇技术团队

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次断电导致的mysql数据恢复问题相关的知识,希望对你有一定的参考价值。

最近在做监控系统选型,我们将监控系统分为两类:监控和追踪,本篇主要讲断电导致的服务器出现的问题以及解决方案,对于监控系统就不多做介绍了。市面上主流的监控系统主要是zabbix、open-falcon、promethues,今天的主角是zabbix,也就是这次是在搭建zabbix并监控jvm以及服务器信息之后出现的断电。

问题
1、服务器启动失败;
2、mysql启动失败;

经过

周五的时候搭建好了zabbix并且在持续运行,一切都正常,周日的时候突然断电导致服务器关机了,本想着重启一下服务器,登上去之后重新启动所有应用即可,结果却连服务器系统都进不去,直接提示进入紧急模式(当时没有截图截图,只能自行脑补了。。),根据提示输入journal查看到日志中提示sda3磁盘分区挂了。

服务器启动失败解决

知道是磁盘分区挂了,就很容易想到是磁盘在持续写入的时候突然断电导致的,那我们要做的就是对磁盘分区进行修复。对于xsf文件系统的修复很简单,出错的时候linux也会提示建议方案,我们只需要根据提示进行修复即可:
xfs_repair /dev/sda3

mysql启动失败

系统终于能够正常进入了,下一步就是启动应用了,对于zabbix,我安装的时候是基于mysql数据库去安装的,所以先启动mysql数据库,本来以为会一步到位,结果mysql又给了我当头一棒,直接启动失败,错误如下:

这个看不出来具体什么原因导致的,下一步去日志里看看,打开日志结果如下:

记一次断电导致的mysql数据恢复问题

从日志中可以看出,断电的时候由于数据还在持续写入,所以数据损坏了,日志里也提到了解决方案:

记一次断电导致的mysql数据恢复问题

于是打开该网址试试:

记一次断电导致的mysql数据恢复问题

加这一行即可,通过资料查到这个是要加在mysql启动的配置文件my.cnf中,但是我找遍了各种路径也找不到my.cnf文件(查看命令:mysqld --verbose --help |grep -A 1 'Default options'),找dba帮我建了一个在etc目录下,加了如下内容:记一次断电导致的mysql数据恢复问题

经过搜索发现mysql不用my.cnf也能启动,只是会用默认值进行启动,而如果你想要覆盖mysql的默认行为,则可以通过my.cnf进行配置。这里把innodb_force_recovery改为1之后还是启动不了,不断往上加,一直到3才终于启动成功。但是这个参数可不是设置越大越好,他只是为了让你能先启动数据库,进行数据备份之类的操作,对于该参数的说明,我也截了一张图:

记一次断电导致的mysql数据恢复问题

看到最后一行备注了吗,大于0的时候就无法进行更改类操作了,所以相当于还是没有用。
网上找了一圈,大体是无法正常使用了,只能先进行数据备份,然后删除坏表或者重建数据库。
在断电的时候,只有zabbix数据库是一直在使用的,所以第一个想到的是删除zabbix数据库(当然正常情况下我们也可以使用check table tableName来检查坏表),这样就删除了坏表了。执行删除操作

记一次断电导致的mysql数据恢复问题

完了,删都删不掉,那只能采用重建数据库的操作了。

重建数据库

首先我们需要将所有数据导出来,这里写了一个脚本方便导出:

backupdir=/usr/local/mysql/dumpdircd ${backupdir}cur_date=`date '+%Y%m%d'`if [ ! -d ${cur_date} ];then mkdir ${cur_date}ficd ${cur_date}cur_time=`date '+%H%M%S'`db_names=(dbName1 dbName2 dbName3)for db_name in ${db_names[*]}do mkdir ${db_name} for table in `mysql -uroot -pyourpassword -e "show tables from ${db_name}" | sed '1d'` do mysqldump -uroot -pyourpassword ${db_name} ${table} >./"${db_name}"/${table}."${cur_time}".sql donedone

记一次断电导致的mysql数据恢复问题

下面开始创建用户
先用root用户直接登录(mysql -uroot),看一下目前的用户

4个用户,mysql8对于密码的认证方式默认使用caching_sha2_password,给root创建一个远程登录权限(我自己用的就是root远程登录),mysql8的话创建用户时记得加with mysql_native_password,如果你的客户端用的是mysql5的驱动。

ok,开始导入数据,同样也写了一个shell脚本进行导入。

for db in `ls /usr/local/dumpdir/20210324/`;do echo "source /usr/local/dumpdir/import/${db}.sql;" >> /usr/local/dumpdir/import.sql echo "CREATE DATABASE IF NOT EXISTS $db DEFAULT CHARSET utf8 COLLATE utf8_general_ci;" >> /usr/local/dumpdir/import/${db}.sql; echo "use ${db};" >> /usr/local/dumpdir/import/${db}.sql; for i in `ls /usr/local/dumpdir/20210324/${db}/` ; do echo "source /usr/local/dumpdir/20210324/${db}/$i;" >> /usr/local/dumpdir/import/${db}.sql; donedone

登录mysql之后,运行以下命令执行导入操作:
source /usr/local/dumpdir/import.sql

到此为止,所有数据都恢复了,当然断电的时候丢失的那部分坏数据是没法恢复了。
最后给对应的用户分配指定数据库的权限就可以了。

附mysql相关脚本:

创建用户:create user 'user'@'host' with mysql_native_password identity by 'password';(8.0客户端不需要加with mysql_native_password)
给用户指定某表所有权限:grant all privileges on databaseName.* to targetUserName@"%";

总结

我们平时的生产环境还是要做好数据备份和数据库高可用,因为一旦出现断电这类问题,恢复时遇到的问题比较多而且造成的损失也很大。

参考资料

https://blog.csdn.net/theoldsod2000/article/details/105988902/

https://blog.csdn.net/edyf123/article/details/81026155

https://blog.csdn.net/weixin_39947812/article/details/113612232

https://blog.csdn.net/qq_36591505/article/details/114688260

https://blog.csdn.net/zengxuewen2045/article/details/52333382

https://www.bootwiki.com/note/mysql-installation-error-failed-find-valid-data-dir.html

以上是关于记一次断电导致的mysql数据恢复问题的主要内容,如果未能解决你的问题,请参考以下文章

记一次虚机强制断电磁盘损坏导致 K8s 集群 部分节点未就绪(NotReady) 问题解决

记一次虚机强制断电磁盘损坏导致 K8s 集群 部分节点未就绪(NotReady) 问题解决

记一次虚机强制断电 K8s 集群 etcd pod 挂掉快照丢失(没有备份)问题处理

记一次虚机强制断电 K8s 集群 etcd pod 挂掉快照丢失(没有备份)问题处理

记一次虚机强制断电 K8s 集群 etcd pod 挂掉快照丢失(没有备份)问题处理

记一次虚机强制断电 K8s 集群 etcd pod 挂掉快照丢失(没有备份)问题处理