引言
生产环境,某表末尾添加一个字段,保存造成数据库崩溃,idb 文件损坏,数据库版本号 8.0.29,表数据 5K 多条
起因
2022-08-12 12:20 左右,中午吃饭回来打算更新线上程序,同事操作表添加一列,数据库出问题了
线上站点打开缓慢或打不开,接着排查问题
查看服务状态 systemctl status mysqld
正常
客户端连接数据库打开任意表,极慢或打开失败
查看数据库日志发现有错误信息输出
[InnoDB] InnoDB initialization has started.
[InnoDB] InnoDB initialization has ended.
类似
的错误信息:https://github.com/gitpod-io/gitpod/issues/9314 ,还有锁表关键字 lock TABLES
打开任意表,有些能打开有些不能,问题定位到具体某一张表 A (A 表就是添加字段的表,此前没有反应过来)
只要访问 A 表,或关联访问,查看 DDL 等操作都会造成实例重启,均有日志输出
所以,解释了为什么打开缓慢或打不开,因为线上应用程序在持续查询 A 表,实例在不断重启
解决
首先,停止线上应用程序,开始还原数据库备份文件
我们做了数据库备份任务(12 小一次),最新备份为中午 12 点 8 分
接着修改生产环境表 A 为 A2,重新创建表 A,从还原的数据库恢复表 A
对比系统日志记录,备份数据表 A 为最新,万幸!!!
至此,重启应用,一切正常
接着
此时表 A2 就像一个地雷,一踩就爆,我们有定时任务备份,表 A2 肯定会有影响,计划晚上 6 点删除表 A2
嘿嘿,很简单,结果执行删除表 A2,数据库又崩了
先进行了数据库备份
-- 跳过锁表
mysqldump -u root -p --quick --skip-lock-tables -R db > /tmp/db.sql
-- 排除某表
mysqldump -u root -p --ignore-table=db.A2 -R db > /tmp/db_2.sql
接着开始删除表 A2 计划:
- 修改现有数据库 db 为 db2,重新创建数据库 db,再把数据恢复到 db,排除表 A2,再删除数据库 db2
- MySQL 不能直接修改数据库名称,所以通过修改表名
rename table db.table to new_db.table;
- 没考虑到还有视图、存储过程,又改回来
- 期间有不少尝试:
- 拷贝表 A2 的 idb 文件进行恢复,
alter table A2 import tablespace
,但失败了 - 重启服务器,重启数据库服务,改一些配置文件等等都没用
- 问题越来越明确到是 idb 文件损坏造成的,突然想到通过截断把数据清空
- 执行
truncate table A2
,竟然成功了,再接着删除表 A2,也成功了!!!
一切都恢复正常,好像很简单就解决了,而过程却是那么的真实。