InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 5.
InnoDB: You may have to recover from a backup.
2021-07-16 09:42:50 7f20d1de5740 InnoDB: Page dump in ascii and hex (16384 bytes):
len 16384; hex
MySQL 故障
突然收到MySQL报警,从库的数据库挂了,一直在不停的重启,打开错误日志,发现有张表坏了。
错误日志,里面的信息:
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 30506.
InnoDB: You may have to recover from a backup.
130509 20:33:48 InnoDB: Page dump in ascii and hex (16384 bytes):
很多十六进制的代码
查阅互联网得知:
innodb表损坏不能通过repair table 等修复myisam的命令操作。
因为被破坏的地方只在索引的部分,所以当使用innodb_force_recovery = 1运行 InnoDB 时,操作如下:
执行check,repair table 都无效
一般做法:
建立一张表:
create table email_status_bak #和原表结构一样,只是把INNODB改成了MYISAM。
把数据导进去
insert into email_status_bak select * from email_status;
删除掉原表:
drop table email_status;
注释掉innodb_force_recovery 之后,重启。
重命名:
rename table edm_email_status_bak to email_status;
最后该回存储引擎
alter table edm_email_status engine = innodb
我的数据表很多,查看日志无法知道某个数据表有问题,于是决定先导出所有数据库,然后导入到新MySQL。
启动故障MySQL
修改 /etc/my.cnf 加入:
innodb_force_recovery = 1
启动MySQL
service mysql start
导出故障MySQL数据
(base) [root@web-devops-00 \~]# cat /data/tmp/bak.sh
#!/bin/bash
database=\`mysql -ubak -pbak@2021 -e "show databases;"|sed 1,2d\` #这里是反引号
echo $database
for data in $database
do
mysqldump -ubak -pbak@2021 -B $data > mysqlbak/${data}\`date +%Y%m%d\`.sql #date后面必须要有空格
done
(base) [root@web-devops-00 \~]# du -sh /data/tmp/mysqlbak/
3\.4G /data/tmp/mysqlbak/
(base) [root@web-devops-00 \~]# du -sh /data/tmp/mysqlbak/\*
32K /data/tmp/mysqlbak/davinci0.320210716.sql
1\.2G /data/tmp/mysqlbak/hl_bi_new20210716.sql
13M /data/tmp/mysqlbak/xxxxcloud20210716.sql
1\.8G /data/tmp/mysqlbak/zabbix20210716.sql
......
新建 同版本 新MySQL
1 停止旧MySQL
service mysql stop
2 初始化目录
mkdir -p /data/app/mysql56/conf
mkdir -p /data/app/mysql56/logs
mkdir -p /data/app/mysql56/data
3 启动 新MySQL
docker run -itd --name mysql56 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -v /data/app/mysql56/conf/my.cnf:/etc/mysql/cnf.d -v /data/app/mysql56/logs:/etc/mysql/logs -v /data/app/mysql56/data:/var/lib/mysql mysql:5.6
导入数据到新MySQL
for sqlfile in \`ls -1 mysqlbak/\*\`;do echo $sqlfile;mysql -uroot -p123456 -P3306 -h127.0.0.1 < $sqlfile;done
登录新Mysql验证所有表是否存在。
用户密码可能被旧数据库覆盖。
其他方法
在原来的故障MySQL上恢复数据。
遍历所有数据表,然后 insert into newtable select \* from oldtable,最后该回存储引擎为 InnoDB
参考
MySQL数据库INNODB表损坏修复处理过程分享
https://www.jb51.net/article/40289.htm
MySQL损坏page问题分析
https://zhuanlan.zhihu.com/p/209060238
14\.21.2 Forcing InnoDB Recovery
https://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.html
mysql innodbindexstats_innodb_index_stats详解
https://blog.csdn.net/weixin_30231153/article/details/113344432