先确认是否真损坏:能用--skip-grant-tables登录并查到mysql.user表即非损坏,plugin或authentication_string异常属数据问题;报table 'mysql.user' doesn't exist才是真损坏,myisam需myisamchk修复,innodb须--initialize-insecure重建。

确认是不是真损坏,而不是字段值异常
很多“认证失败”根本不是表损坏,只是 plugin 或 authentication_string 字段值不对。先绕过权限登录验证:停服务后用 --skip-grant-tables 启动,再执行 mysql -u root(不加 -p)能进就说明物理结构还在。
进库后立刻查:SELECT User, Host, plugin, authentication_string FROM mysql.user WHERE User = 'root';
- 如果
plugin是auth_socket、caching_sha2_password或为空/NULL,属于数据异常,不是损坏,不用重建 - 如果报错
Table 'mysql.user' doesn't exist或Incorrect information in file: './mysql/user.frm',才是真损坏 - 如果能查但返回空行,说明
user表记录被删了,也属数据异常,非文件级损坏
MySQL 5.7 默认 MyISAM,必须用 myisamchk 修复
5.7 的 mysql 系统库默认用 MyISAM 引擎,REPAIR TABLE mysql.user 在命令行里看似能跑,但实际无效——它只对当前连接生效,且不修复索引文件(.MYI)损坏。真正有效的只有离线 myisamchk。
- 彻底停掉 mysqld:
sudo systemctl stop mysql,再ps aux | grep mysqld确认无残留进程 - 备份整个
/var/lib/mysql/mysql/目录,别只拷.frm或.MYD - 逐个修复关键表:
sudo myisamchk -r /var/lib/mysql/mysql/user.MYI,同样修db.MYI、tables_priv.MYI - 若报
Key file is old,加-o强制重建:myisamchk -o -r /var/lib/mysql/mysql/user.MYI - 修完重启,立刻运行
mysql_upgrade --force补字段和索引,否则新版客户端可能连不上
修复后仍登录失败?大概率漏了 FLUSH PRIVILEGES 或 plugin 不匹配
--skip-grant-tables 模式下改完表,不执行 FLUSH PRIVILEGES,修改只在内存中,重启即丢;而只设 plugin 不同步 authentication_string,MySQL 认证链直接断裂。
- 必须在
--skip-grant-tables环境下执行:FLUSH PRIVILEGES;(这步漏掉,后续ALTER USER会报错) - 推荐用
ALTER USER一次性更新插件和密码:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码'; - 如果报
ERROR 1396(用户不存在),改用UPDATE:UPDATE mysql.user SET authentication_string = PASSWORD('新密码'), plugin = 'mysql_native_password' WHERE User = 'root' AND Host = 'localhost'; - 改完必须再
FLUSH PRIVILEGES;,然后注释掉配置文件里的skip-grant-tables,再重启服务
为什么不能直接 INSERT 新用户或还原旧 dump?
手动插入或还原 5.7 以前的 mysqldump --all-databases 备份极大概率失败,因为 mysql.user 表字段顺序、默认值、索引、生成列都随版本变化,硬写容易触发启动拒绝或认证静默失效。
-
INSERT INTO mysql.user会忽略password_last_changed、account_locked等新增字段,导致用户被锁或无法登录 - 5.7+ 默认
innodb_file_per_table=ON,即使你用 MyISAM 存系统表,mysql.user的元数据一致性也依赖mysql_upgrade补全 - 还原旧 dump 时若出现
Unknown column 'password'或Select_priv='Y'被置空,说明字段映射失败,权限已丢失 - 真正安全的做法是:先用
myisamchk修物理文件,再用mysql_upgrade --force对齐逻辑结构
最常被忽略的是修完 .MYI 文件后没跑 mysql_upgrade,或者改完 plugin 忘了 FLUSH PRIVILEGES——这两步一漏,重启后照样 Access denied,而且错误日志里不会提示原因。











