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

相关推荐
其实防守也摸鱼13 分钟前
前端应用的离线暂停更新策略:构建稳定可靠的渐进式部署方案
服务器·前端·数据库·学习·ai·命令行·linux系统
Leighteen30 分钟前
ORDER BY + LIMIT 的坑:为什么加了 `LIMIT` 结果顺序还乱
数据库
一个天蝎座 白勺 程序猿34 分钟前
复盘之我在金仓生产环境踩过的SQL暗坑,和攒了六年的编码规矩
数据库·sql·kingbasees
Mico181 小时前
MySQL 8.0.35 GTID + 延迟复制 + 过滤复制搭建
mysql·dba
Dylan的码园1 小时前
从Excel到数据库:数据分析全流程与Kettle ETL实战指南
数据库·数据分析·excel
l1t1 小时前
DeepSeek总结的DuckLake 架构深度剖析-1
数据库·架构
花生了什么事o1 小时前
分布式 ID 生成方案:从数据库自增到雪花算法
数据库·分布式·算法
纪伊路上盛名在1 小时前
NVML ERROR_ RM has detected an NVML_RM version mismatch
linux·数据库·gpu·驱动
nVisual1 小时前
01-环境监控集成方案
运维·服务器·开发语言·网络·数据库·数据中心布线·综合布线管理软件