myisam 表损坏需用 mysqlcheck --repair --use-frm 修复,innodb 表损坏应通过 innodb_force_recovery 导出数据后重建;切勿对 innodb 表执行 repair table 或误用 mysql_upgrade。

先确认是 MyISAM 还是 InnoDB 表损坏
错误信息和日志线索比猜引擎更可靠:Table 'xxx' is marked as crashed 基本锁定 MyISAM;ERROR 2013、Database page corruption 或启动卡在 InnoDB: Starting crash recovery 后崩溃,大概率是 InnoDB。直接查更准:SHOW TABLE STATUS LIKE 'table_name' 看 Engine 字段。别跳过这步——用 REPAIR TABLE 对 InnoDB 表只会报 ERROR 1031 (HY000): Table storage engine for 'xxx' doesn't support repair,纯浪费时间。
MyISAM 表损坏:优先用 mysqlcheck --repair 而不是 REPAIR TABLE
REPAIR TABLE 需要 MySQL 正常连接且表未被锁,生产环境风险高;mysqlcheck 可离线批量操作,更稳。
停服务后执行:
mysqlcheck -u root -p --repair --use-frm database_name table_name
-
--use-frm是关键:当.MYI完全损坏时,强制从.frm重建索引(但若.MYD也坏,可能丢行) -
--quick仅校验索引头,快但不彻底;--force遇错不停,适合批量 - 修完必须重启 mysqld,再跑
CHECK TABLE验证
InnoDB 表损坏:别删 .ibd,逐级试 innodb_force_recovery
这个参数不是修复工具,是“带伤上线”抢数据的临时通道,值 1–6 越高越危险,只读且不能写入。
操作顺序必须严格:
- 编辑
my.cnf,在[mysqld]下加innodb_force_recovery = 1 - 停服务:
systemctl stop mysql,清残留进程和 socket 文件 - 启动:
systemctl start mysql,查错误日志确认是否成功 - 能连上就立刻导出:
mysqldump --single-transaction database_name > backup.sql - 若
SELECT * FROM broken_table LIMIT 1报错,才升到 2,最高只试到 4;5 和 6 极易导致 mysqld 崩溃
导出后立刻停服务,删掉该参数,再重建表或恢复——innodb_force_recovery 本身不修复任何页或索引。
升级后系统库(如 mysql.user)损坏:别碰 mysql_upgrade
MySQL 8.0.16+ 已彻底移除 mysql_upgrade,运行它要么报 command not found,要么静默跳过,甚至引发元数据冲突。你看到的 mysql.user 字段缺失、SHOW GRANTS 返回空,是结构不匹配,不是“漏跑 upgrade”。
真正要做的:
- 停服务,备份整个
/var/lib/mysql/mysql/目录 - 用同版本干净实例导出结构:
mysqldump --no-data --skip-triggers --skip-routines mysql > mysql_struct.sql - 替换原
mysql/下的表定义文件(保留ibdata1和日志) - 若无干净环境,才考虑
mysqld --initialize-insecure --datadir=/var/lib/mysql,但会清空所有用户和角色
最后务必检查 plugin 字段:SELECT user, host, plugin FROM mysql.user WHERE user = 'root',8.0+ 默认用 caching_sha2_password,旧客户端连不上得改插件或密码策略。











