能恢复,但必须用--skip-grant-tables启动mysqld并手动重建root记录:先insert基础行(含mysql_native_password插件),再update赋权,最后强制flush privileges刷新内存缓存,否则仍报error 1045。

能恢复,但必须用 --skip-grant-tables 启动 mysqld 并手动重建 root 记录——这不是“重设密码”,而是从零补全 mysql.user 表里缺失的行和权限字段;漏掉 plugin 或 FLUSH PRIVILEGES,新 root 仍无法登录。
为什么 mysql -u root -p 会报 ERROR 1045?
不是密码错了,是 mysql.user 表里压根没 'root'@'localhost' 这条记录。MySQL 启动时加载权限表,查不到用户就直接拒绝连接。所有依赖登录的命令(mysqladmin、SET PASSWORD、ALTER USER)都走不通——你连执行它们的入口都没有。
常见错误现象:
- 输入任意密码都报
ERROR 1045 (28000): Access denied for user 'root'@'localhost' - 用
mysqld_safe --skip-grant-tables启动后,mysql -u root却连不上,卡在Can't connect to MySQL server - 成功连上后执行
CREATE USER 'root'@'localhost'报错ERROR 1290或插入后仍无法认证
MySQL 8.0+ 必须手动 INSERT + UPDATE,不能 CREATE USER
MySQL 8.0 的 CREATE USER 在 --skip-grant-tables 模式下仍会校验插件兼容性、字段非空约束等内部逻辑。若 mysql.user 表中完全无 root 记录,它大概率失败或生成一个 authentication_string 为空、plugin 为默认值(如 caching_sha2_password)的无效用户。
稳妥做法是直接写表:
- 先
USE mysql; - 插入基础行:
INSERT INTO user (Host, User, authentication_string, plugin, account_locked) VALUES ('localhost', 'root', '', 'mysql_native_password', 'N'); - 批量开权限:
UPDATE user SET Select_priv='Y', Insert_priv='Y', Update_priv='Y', Delete_priv='Y', Create_priv='Y', Drop_priv='Y', Grant_priv='Y', Super_priv='Y', Create_user_priv='Y' WHERE User='root' AND Host='localhost'; -
plugin字段必须显式设为mysql_native_password,否则 Navicat、DBeaver、老脚本连不上,报ERROR 1251
启动命令和 host 匹配是两大易踩坑点
MySQL 用户是 'user'@'host' 二元组,'root'@'localhost' 和 'root'@'127.0.0.1' 完全不同。你修哪一行,就只能用对应 host 登录。
启动命令差异:
- Linux/macOS:
sudo mysqld --skip-grant-tables --skip-networking --socket=/var/run/mysqld/mysqld.sock &(--skip-networking是关键,禁 TCP,只留 socket) - Windows:
mysqld --console --skip-grant-tables --shared-memory(缺--console或--shared-memory都连不上)
检查当前有哪些 root:
- 连上后立刻执行:
SELECT User, Host FROM mysql.user WHERE User = 'root'; - 如果常用
mysql -u root -h 127.0.0.1,但只修了localhost,就会继续报Access denied - 生产环境建议一并修复:
UPDATE user SET ... WHERE User='root' AND Host IN ('localhost', '127.0.0.1', '%');
FLUSH PRIVILEGES 不执行,前面全白干
MySQL 启动时把权限表加载进内存缓存。--skip-grant-tables 只跳过加载,不跳过缓存机制。你 INSERT/UPDATE 的是磁盘上的 mysql.user 表,但服务仍在用旧缓存。
必须执行:
-
FLUSH PRIVILEGES;—— 强制重新读取磁盘表并更新内存缓存 - 这步漏掉,
mysql -u root -p仍会报错,哪怕表里数据已正确 - 执行后别急着退出,先验证:
SELECT User, Host, plugin FROM mysql.user WHERE User='root'; - 确认无误再关掉安全模式进程,移除配置文件里的
skip-grant-tables,正常重启服务
最常被忽略的是:改完权限后没查 plugin 值,也没验证 FLUSH PRIVILEGES 是否真生效——这两处出问题,恢复操作等于没做。











