[特殊字符] 从数据库无法访问到成功修复崩溃表:一次 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 的等级!任何强制操作都要以"可恢复"为前提。

相关推荐
k↑12 分钟前
微服务之注册中心与ShardingSphere关于分库分表的那些事
数据库·微服务·架构·shardingsphere
柏油1 小时前
MySQL 字符集 utf8 与 utf8mb4
数据库·后端·mysql
我科绝伦(Huanhuan Zhou)2 小时前
异构数据库兼容力测评:KingbaseES 与 MySQL 的语法・功能・性能全场景验证解析
数据库·mysql
Apple_羊先森2 小时前
Oracle数据库操作深入研究:备份、数据删除与性能优化
数据库·oracle·性能优化
BTU_YC2 小时前
docker compose部署mysql
mysql·adb·docker
麦麦大数据4 小时前
F004 新闻可视化系统爬虫更新数据+ flask + mysql架构
爬虫·mysql·flask·可视化·新闻
xiao-xiang11 小时前
redis-保姆级配置详解
数据库·redis
白鹭12 小时前
MySQL(多表查询练习)
数据库·mysql
xiao-xiang16 小时前
redis-sentinel基础概念及部署
数据库·redis·sentinel