[特殊字符] 从数据库无法访问到成功修复崩溃表:一次 MySQL 故障排查实录

一次典型的 MySQL 故障排查与修复全过程,涵盖登录失败、表崩溃、innodb_force_recovery 救援、坏表剔除与数据恢复等关键操作。


一、问题背景

某业务系统运行多年,数据库使用的是 MySQL 8.0.18,近期在一次服务器重启后,发现无法正常连接数据库,提示:

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

尝试重启 MySQL,过程似乎正常:

复制代码

sudo service mysql restart # 显示 SUCCESS

但用 mysql -u root -p 登录时依旧提示账号密码错误。开始怀疑是否数据损坏或权限配置有误。


二、排查思路

1. 登录失败:确认密码正确性

  • 使用其他账户尝试连接(如 test 用户)。

  • 发现部分用户仍可登录,说明 数据库服务本身是正常的 ,但 root 权限或数据可能损坏。

2. 可登录用户访问数据时报错

登录后,执行 SQL 删除某张表时报错:

DROP TABLE imp_index_warn_data; ERROR 1036 (HY000): Table 'tablespace_files' is read only

甚至强制设置参数后依旧失败:

SET GLOBAL innodb_fast_shutdown = 0; DROP TABLE imp_index_warn_data; # 报错 3604,存储引擎无法删除该表

结论:该表已严重崩溃,影响了 InnoDB 正常功能。


三、制定解决策略

目标

  • 保住正常表的数据。

  • 剔除坏表 imp_index_warn_data。

  • 尽量避免数据损失与停机时间。

解决方案路线图

  1. 使用 innodb_force_recovery 启动数据库。

  2. 导出除坏表以外的所有数据。

  3. 停止数据库服务,物理删除坏表相关文件。

  4. 启动数据库,删除坏表元数据。

  5. 恢复数据库服务到正常模式。


四、操作步骤详解

步骤 1:修改 my.cnf,启用恢复模式

编辑 /etc/my.cnf:

[mysqld] innodb_force_recovery = 6

含义:略过大部分恢复步骤并只读启动。仅用于应急,不可长期开启。

保存后重启数据库:

sudo service mysql restart


步骤 2:导出正常表数据

使用 mysqldump 排除坏表:

mysqldump -u root -p --skip-lock-tables i18n_demo > i18n_demo.sql

确保 imp_index_warn_data 未导出。


步骤 3:停止数据库服务,删除坏表文件

sudo service mysql stop

进入数据目录(示例路径如下,具体看你的配置):

cd /usr/local/mysql/mysql-8.0.18/data/i18n_demo

备份坏表相关文件:

mkdir ~/bad_table_backup mv imp_index_warn_data.* ~/bad_table_backup/


步骤 4:重启数据库,清除元数据

重启服务:

sudo service mysql start

登录数据库,清理元数据:

DROP TABLE imp_index_warn_data;

此时应该不会再报错。


步骤 5:导入数据并恢复服务正常

取消 innodb_force_recovery:

# /etc/my.cnf 中移除或注释: # innodb_force_recovery = 6

重启服务:

sudo service mysql restart

导入之前备份的数据:

mysql -u root -p i18n_demo < i18n_demo.sql

至此,数据库恢复完成!


五、总结与经验教训

✅ 收获

  • 理解 innodb_force_recovery 各个级别的作用。

  • 掌握 MySQL 启动失败或崩溃时的应急处理手段。

  • 明确了"逻辑删除表"与"物理删除文件"的边界和使用时机。

❌ 教训

  • 未开启 binlog、没有定期全量备份,是很大风险。

  • 某些老旧系统的数据表结构混乱、未做分区或冷热分离,极易出现单表崩溃。


六、附录:常用命令速查

操作 命令
查看服务状态 sudo systemctl status mysql
停止 MySQL sudo service mysql stop
启动 MySQL sudo service mysql start
数据导出 mysqldump -u root -p db_name > backup.sql
数据导入 mysql -u root -p db_name < backup.sql

如果你也遇到类似问题,记得第一时间备份,并小心操作 innodb_force_recovery 的等级!任何强制操作都要以"可恢复"为前提。

相关推荐
小白男神3 天前
MySQL进阶学习四(存储过程、游标、触发器)
mysql
这个DBA有点耶3 天前
MVCC深入:Read View、版本链与快照读——InnoDB并发控制的内核
数据库·mysql·架构
DBA_G3 天前
从地面到云霄:GBase数据库在民航三大场景的落地实践
数据库
自由能燃气设备3 天前
商用全预混低氮冷凝锅炉免费方案vs付费方案对比+选型避坑指南
大数据·数据库·人工智能
科创致远3 天前
科创致远 ESOP 系统核心效能与实战价值展示
大数据·数据库·人工智能·精益工程
kybs19913 天前
全球灾害数据分析可视化 毕业设计-附源码66794
vue.js·spring boot·mysql·安全·django·c#·asp.net
2601_962218613 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法
程序猿_极客3 天前
【免费】分享一套优质的基于SSM的校园失物招领系统的设计与实现,源码+文档+视频详解(讲解)
java·mysql·ssm·课程设计·失物招领系统
张洛闻Eren3 天前
k8s云原生【第十课】:水平 Pod 自动扩缩容
运维·数据库·云原生·kubernetes·github
于平安3 天前
MySQL-触发器
数据库·mysql