适用场景与操作前的准备
root 密码遗忘是服务器运维中最常见的问题之一:接手一台二手服务器、接手同事维护的机器、或者太久没有登录 MySQL,都可能遇到执行 mysql -u root 后提示 Access denied for user 'root'@'localhost' 的情况。本教程适用于 Linux 服务器上通过命令行或源码安装的 MySQL / MariaDB,使用宝塔等面板的用户同样可以参考。
如果服务器上安装的是 MariaDB,服务名通常是 mariadb 而不是 mysqld,操作前先执行 systemctl status mariadb 确认服务名;MariaDB 10.4 及以上版本同样支持 ALTER USER 语法,更早的版本仍使用 UPDATE mysql.user 的方式修改密码。
需要提前说明的是,本教程的两种方法都需要重启 MySQL 服务,属于有停机影响的操作。执行前请确认三件事:当前是否有业务在连接数据库,能否安排一个短暂的停机窗口;如果库里有重要数据,先确认已有其他可用备份,必要时直接复制一份 /var/lib/mysql 数据目录;操作全程建议保留一个 SSH 会话不要关闭,出现问题时便于回滚。如果你使用的是云数据库 RDS,root 密码一般在云厂商控制台直接重置,不需要本教程的命令行操作。
方法一:--skip-grant-tables 跳过权限表重置密码
这是最通用的方法,思路是让 MySQL 启动时不加载权限表,从而免密码登录,登录后再把密码改回来,适合完全忘记密码、手上没有任何可用账号的场景。
第一步,停止 MySQL 服务。CentOS / RHEL 与 Ubuntu / Debian 的服务名不同,按下面对应执行:
# CentOS / RHEL
systemctl stop mysqld
# Ubuntu / Debian
systemctl stop mysql
如果服务本身已经异常停不掉,先用 ps -ef | grep mysqld 确认没有残留进程,必要时手动 kill 后再继续。
第二步,跳过权限表并禁止远程连接启动:
mysqld_safe --skip-grant-tables --skip-networking &
加上 --skip-networking 是为了在无密码窗口期内禁止任何远程连接,只允许本机登录,这是必须养成的安全习惯。等待几秒后执行 mysql -u root,此时应该能直接进入,不需要密码。
第三步,刷新权限并修改密码。MySQL 8.0 与 5.7 的语法不同,请按版本选择:8.0 执行 FLUSH PRIVILEGES; ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';;5.7 及以下版本执行 FLUSH PRIVILEGES; UPDATE mysql.user SET authentication_string = PASSWORD('新密码') WHERE User = 'root';。新密码建议包含大小写字母、数字和符号,长度 12 位以上。
第四步,退出 MySQL,先正常关闭这个跳过权限表的实例,再按平时方式执行 systemctl start mysqld 重新启动。不要漏掉这一步,跳过权限表的实例一直运行,等于给服务器留了一扇无密码的门。

方法二:--init-file 初始化文件重置(更安全)
如果服务器暴露在公网,或者你对安全性要求较高,更推荐 init-file 方案。它不需要进入"任何人可无密码登录"的状态:MySQL 启动时自动执行一次我们指定的 SQL 文件,改完密码立即恢复正常权限校验,安全窗口期几乎为零。
第一步,创建初始化文件 /root/mysql-reset.sql,内容只有一行:ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';。创建后把权限收紧为 600(chmod 600 /root/mysql-reset.sql),避免明文密码被其他用户读到。
第二步,停止 MySQL 后,带上 init-file 参数启动:
mysqld --init-file=/root/mysql-reset.sql --user=mysql &
MySQL 启动时会自动执行该文件中的语句。确认启动日志没有报错后,用新密码执行 mysql -u root -p 验证登录。验证成功后关闭实例,删除 /root/mysql-reset.sql,再执行 systemctl start mysqld 恢复正常启动。
重置后的验证与安全收尾
密码改完不代表结束,建议按顺序做三件事。第一,用新密码分别从本机和远程各登录一次,确认 mysql -u root -p -h 服务器IP 能通,顺便验证 root 是否仅限本地登录。第二,检查网站配置文件、运维脚本、监控任务里是否还写着旧密码,及时同步,避免业务在几小时后才报数据库连接失败。第三,用 ps -ef | grep mysqld 确认进程参数里没有残留的 --skip-grant-tables。
如果服务器上部署了宝塔面板,也可以在面板「数据库」页面直接重置 root 密码,图形界面操作更直观,底层同样是对 mysql.user 表的修改。不论用哪种方式,都建议把新密码存入密码管理工具,并按需限制 root 的远程登录,只对必要的内网 IP 开放 3306 端口,从源头减少密码丢失带来的暴露面。
常见问题
问题一:执行 mysqld_safe --skip-grant-tables 后登录仍然提示 Access denied?先确认 mysqld 进程真正以跳过权限表模式启动(用 ps -ef | grep mysqld 核对参数),再尝试 mysql -u root --skip-password 登录,个别版本匿名账号会干扰登录用户的选择。
问题二:改完密码重启后还是连不上?先到日志里确认重启过程没有 ERROR,再用 SELECT host, user FROM mysql.user; 检查 root 账号的 host 字段是 localhost 还是 %,两者的密码是分开存储的,改了一个不等于另一个也生效。
问题三:MySQL 5.7 上执行 ALTER USER 直接报错?5.7 请改用 UPDATE mysql.user SET authentication_string = PASSWORD('新密码') WHERE User = 'root';,并且必须再执行一次 FLUSH PRIVILEGES;,两条命令缺一不可,只改表不刷新权限是不会生效的。
问题四:Docker 里部署的 MySQL 忘记密码怎么办?可以进入容器后按方法一操作:docker exec -it 容器名 bash,然后依次执行停止、跳过权限表启动、改密码。如果容器里没有重要数据,更省事的方式是删除容器,重新创建时通过 MYSQL_ROOT_PASSWORD 环境变量指定新密码。
总结
MySQL root 密码忘记并不可怕,--skip-grant-tables 和 --init-file 两种方式都能稳妥找回:前者不挑版本、通用性最好,后者不停"无密码门"、安全窗口更短,可以按服务器暴露程度选择。真正需要重视的是操作习惯:涉及重启数据库的操作先评估停机影响、先确认备份;无密码窗口期务必加 --skip-networking;重置完成后立即恢复正常启动并验证登录。把这三点做到位,重置 root 密码就是一个十分钟内可以安全完成的操作。











暂无评论内容