mysql 5.7 忘记 root 密码时,--skip-grant-tables 是唯一可靠入口,但必须配合 flush privileges 和 alter user 语句重置密码,不可用 password() 函数或直接更新 authentication_string 字段,且需确保 host 匹配并重启服务生效。

直接说结论:MySQL 5.7 忘记 root 密码后,--skip-grant-tables 是可行的,但手动 UPDATE user 失败,几乎全是字段名、函数或权限校验没对上——不是方法失效,是操作细节踩了坑。
为什么 UPDATE user SET authentication_string = PASSWORD('xxx') 不生效
MySQL 5.7.6+ 废弃了 PASSWORD() 函数(虽然部分小版本仍兼容,但行为不稳定),且 authentication_string 字段要求的是加密后的哈希值,不是明文或旧式加密结果。直接用 PASSWORD() 赋值,会导致后续登录时认证插件(mysql_native_password)拒绝该字符串。
-
authentication_string字段必须存入符合当前认证插件格式的哈希值,不能靠PASSWORD()硬塞 - 执行
UPDATE后没运行FLUSH PRIVILEGES,修改不会加载进内存权限系统 - 只改了
user='root',但没限定host,可能匹配到'root'@'%'或'root'@'::1'等多条记录,实际生效的不是你预期那条
正确更新密码必须用 ALTER USER(推荐)
绕过 authentication_string 手动拼接风险,MySQL 5.7.6+ 官方明确要求用 ALTER USER 语句重置密码。它会自动处理插件适配、哈希生成和权限刷新。
- 免密登录后,先执行
USE mysql;,再运行:ALTER USER 'root'@'localhost' IDENTIFIED BY 'your_new_password'; - 如果提示
ERROR 1820 (HY000):说明账户被标记为过期,需先执行SET PASSWORD = PASSWORD('temp');或直接ALTER USER ... PASSWORD EXPIRE NEVER; - 不要漏掉
@'localhost'—— MySQL 5.7 默认建了'root'@'localhost'和'root'@'127.0.0.1'两条,得分别处理或统一用'root'@'%'(不推荐外网暴露)
skip-grant-tables 启动后仍连不上 MySQL 的常见原因
加了 skip-grant-tables 却还是报 Access denied 或连接失败,大概率是配置没生效或冲突项干扰。
- 确认修改的是真正的配置文件:
mysqld --help --verbose | grep "default-authentication-plugin"可反推主配置路径;常见位置是/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf -
skip-grant-tables必须放在[mysqld]段下,若错贴到[client]或文件末尾,完全无效 - 有其他安全限制:比如同时配置了
skip-networking,会导致本地 socket 连接也被禁,此时必须用mysql -S /var/lib/mysql/mysql.sock -u root指定 socket 文件 - SELinux 或 AppArmor 拦截了 mysqld 对配置文件的读取,可临时
setenforce 0测试是否为此问题
修改完不重启服务就无法登录?
改完密码后,即使执行了 FLUSH PRIVILEGES 或 ALTER USER,也必须删掉 skip-grant-tables 并重启 mysqld,否则 MySQL 仍处于免鉴权模式,所有密码验证逻辑被跳过——这不是“生效了”,是“没走验证流程”。
- 重启前务必删除或注释
skip-grant-tables行,否则新密码永远不参与校验 - 重启后首次登录失败,优先检查错误信息是否含
plugin 'caching_sha2_password' cannot be loaded:这是 MySQL 8.0 的插件,5.7 不会出现;若真出现,说明你误装/混用了 8.0 的二进制或配置 - 最易忽略的一点:客户端命令行历史里可能还存着旧密码,用
mysql -u root -p时别下意识回车两次,第二次回车才是输新密码的位置











