必须先停止mysql服务,再用--skip-grant-tables和--skip-networking启动以绕过权限校验并阻止远程访问;登录后须精准更新authentication_string字段、执行flush privileges刷新内存权限,最后彻底清理残留进程与配置文件中的skip-grant-tables项,否则无法生效或导致长期无鉴权风险。

必须停服务、用 --skip-grant-tables 启动、改 authentication_string 字段、执行 FLUSH PRIVILEGES,缺一不可。直接改配置或查原密码是无效的。
为什么不能跳过 --skip-grant-tables 直接登录?
MySQL 5.7 的 root 密码以哈希形式存在 mysql.user 表的 authentication_string 字段里,PASSWORD() 是单向函数,没有原始密码可查。你不是“找回”,而是“重置”——必须先让 mysqld 不加载权限表,才有机会写入新哈希。
常见错误现象:
- 执行
mysql -u root -p提示Access denied,说明校验逻辑还在运行,根本进不去 - 试图用
mysqladmin或普通 SQL 修改密码,报错ERROR 1045 (28000),因为没权限连库
mysqld --skip-grant-tables 启动时为什么必须加 --skip-networking?
不加 --skip-networking,mysqld 仍会监听 3306 端口,任何能访问该端口的客户端(包括远程机器)都能无密码连接并执行任意 SQL,等同于全库裸奔。
实操要点:
- 先停服务:
sudo systemctl stop mysqld(Ubuntu/Debian)或sudo systemctl stop mysql(CentOS/RHEL) - 启动命令必须完整:
sudo mysqld --skip-grant-tables --skip-networking --user=mysql & - Linux 下确认进程已起:
pgrep -f "mysqld.*skip-grant-tables";Windows 下用任务管理器查mysqld.exe进程 - 别用
mysqld_safe:新版系统中它已被弃用,且可能与 systemd 冲突导致启动失败或被自动 kill
登录后执行哪条 SQL 才真正生效?
MySQL 5.7 中字段名、函数、host 匹配都必须精准,错一个就静默失败或报错。
正确操作顺序:
- 新开终端执行:
mysql -u root(不加-p,也不输密码) - 进库后立刻执行:
USE mysql; - 更新语句必须带
host条件:UPDATE user SET authentication_string = PASSWORD('MyNewPass123') WHERE user = 'root' AND host = 'localhost'; - 不能写成
WHERE user = 'root'—— 因为root@'127.0.0.1'和root@'localhost'是两个独立账户 - 不能用
password字段(5.7 已废弃),也不能直接赋值字符串(如'*ABC...'),必须调用PASSWORD()函数 - 必须执行:
FLUSH PRIVILEGES;—— 否则新哈希只写入磁盘,未加载进内存缓存,登录时仍校验旧值
改完密码后最容易忽略的两件事
很多人改完立刻试登录,发现还是免密,问题出在残留状态没清理干净。
- 手动杀掉跳过权限的 mysqld 进程:
sudo kill $(pgrep -f "mysqld.*skip-grant-tables");Windows 下直接关闭运行该命令的 CMD 窗口 - 检查全局配置文件(如
/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf),删掉或注释掉可能存在的skip_grant_tables=1行,否则下次systemctl start mysqld会继承该参数,持续免密 - 验证方式严格用:
mysql -u root -p输入新密码;如果直接进了没提示输密码,说明还有进程或配置残留
整个过程最脆弱的环节不是 SQL 写法,而是进程清理和配置回滚——哪怕只漏掉一行注释,都会让生产环境长期处于无鉴权状态。











