一、引言:先别慌,root 密码遗忘其实很好解决

很多开发者和运维人员在日常工作中都会遇到同一个尴尬场景:想登录本机 MySQL,却发现完全想不起 root 密码,或者由于换了电脑、接手了别人留下的环境、长时间未使用,导致 root 账号无法进入。这个时候第一反应往往是卸载重装,但实际上,MySQL 提供了一系列非常成熟、安全的密码重置方案,既不会丢失已有数据,也不用重装数据库。

本文将以「超详细」为目标,围绕 MySQL root 密码遗忘这一核心问题,从原理讲起,逐步覆盖 Windows、Linux、macOS、Docker 等不同环境下的完整操作步骤。同时会重点说明 MySQL 5.7 与 8.0 两个大版本之间的差异,因为如果照搬网上旧教程,很容易在 8.0 上执行失败或越改越乱。

阅读完本文后,你将能够做到:

  • 理解 MySQL 权限与密码存储的基本原理;
  • 根据操作系统和 MySQL 版本选择正确的重置方法;
  • 在重置前做好必要的数据与配置备份;
  • 正确使用 skip-grant-tables--init-file 等方式绕过认证;
  • 通过 ALTER USER 等语句安全地更新 root 密码;
  • 处理重置过程中遇到的各种常见报错;
  • 在重置完成后及时进行安全加固,避免留下隐患。

重要提醒:本文介绍的所有操作都用于恢复你自己拥有合法管理权限的数据库实例。未经授权尝试重置他人服务器上的 MySQL 密码属于违法行为,请务必在合规、合法的前提下进行操作。

二、为什么你会忘记 root 密码?先理解问题本质

在动手重置之前,先搞清楚 MySQL 的账号体系,有助于后续操作不迷路。MySQL 的账号由「用户名」和「主机名」两部分组成,例如 root@localhostroot@% 是两个不同的账号,它们可以拥有完全不同的密码和权限。很多人以为改了 root 密码,但登录时仍然被拒绝,往往就是因为只改了其中一个账号,而客户端实际匹配到了另一个账号。

MySQL 的密码并不是以明文形式存储的,而是经过哈希算法处理后的字符串。不同版本的存储字段和认证插件有所区别:

  • MySQL 5.6 及更早版本:主要使用 mysql.user 表中的 password 字段;
  • MySQL 5.7:改用 authentication_string 字段存储认证信息,并默认使用 mysql_native_password 认证插件;
  • MySQL 8.0:继续使用 authentication_string 字段,但默认认证插件升级为 caching_sha2_password,同时移除了旧版的 PASSWORD() 函数。

因此,在重置密码时,最稳妥的方式并不是手写哈希值,而是让 MySQL 自己根据 SQL 语句重新生成认证信息。这也是为什么官方推荐使用 ALTER USERSET PASSWORD 来修改密码,而不是直接 UPDATE 一张表并手动塞入哈希值。

常见的密码遗忘原因主要有以下几种:

  • 使用一键安装包或云镜像创建数据库后,没有记录初始密码;
  • 长时间未登录,密码混乱,多个 root 账号密码不一致;
  • 同事或上一任管理员离职,没有留下文档;
  • 测试环境密码被临时修改,之后忘记改回;
  • 尝试过修改密码但中途失败,导致认证信息损坏;
  • 升级 MySQL 版本后,旧密码策略不兼容导致登录失败。

理解了这些背景后,下面进入正式重置环节。无论原因是什么,步骤的核心思路是完全一致的:以验证绕过模式启动 MySQL,进入数据库后修改认证信息,再恢复正常模式。

三、重置前的准备工作:备份、预判与安全确认

虽然常规的密码重置不会影响业务数据,但任何对数据库服务的启停和参数修改都建议提前做好准备工作,尤其当这台 MySQL 上有正在使用的业务库时。以下是正式操作前必须完成的检查和备份步骤。

3.1 确认 MySQL 版本

不同版本的命令差异较大,先确认版本可以避免照搬错误教程。如果你还能通过其他账号登录,直接执行查询即可;如果完全无法登录,可以查看安装包信息、启动日志或二进制文件版本。

能登录时查看版本:

SELECT VERSION();
SHOW VARIABLES LIKE 'version';

无法登录时,在服务器终端查看:

# Linux / macOS
mysqld --version
Windows(在 MySQL 安装目录的 bin 下)
mysqld.exe --version

获取到类似 8.0.365.7.44 的版本号后,就能确定后续应使用哪一组命令。

3.2 备份配置文件

重置过程中通常不需要修改配置文件,但在 Windows 上通过服务参数操作、或在 Linux 上手动启动 mysqld 时,建议先复制一份配置文件,以便出问题后快速回滚。常见配置文件位置如下:

  • Linux:/etc/my.cnf/etc/mysql/my.cnf,也可能是 /etc/mysql/mysql.conf.d/mysqld.cnf
  • Windows:MySQL 安装目录下的 my.ini
  • macOS Homebrew:/usr/local/etc/my.cnf/opt/homebrew/etc/my.cnf

复制配置文件的示例:

# Linux / macOS
sudo cp /etc/mysql/my.cnf /etc/mysql/my.cnf.bak
Windows PowerShell(管理员)
Copy-Item "C:\ProgramData\MySQL\MySQL Server 8.0\my.ini" "C:\ProgramData\MySQL\MySQL Server 8.0\my.ini.bak"

3.3 备份数据目录

密码重置理论上只修改系统表,不涉及业务数据。但如果你从未做过备份,或者数据库非常重要,建议趁重启前的窗口做一次一致性备份。最简单的方式是直接对数据目录做冷备,但必须确保 MySQL 已完全停止后再复制,否则可能出现文件不一致。

# 1. 停止 MySQL 服务(根据不同系统选择)
sudo systemctl stop mysql        # Linux systemd
sudo service mysql stop          # Linux SysVinit
net stop mysql                   # Windows CMD(管理员)
2. 复制数据目录(路径以实际为准)
sudo cp -a /var/lib/mysql /var/lib/mysql_bak_20260830
3. 重新启动
sudo systemctl start mysql

如果你确认数据库当前没有业务连接,或只是本机开发环境,这一步可以省略,但养成备份习惯总没有坏处。

3.4 确认启动方式和权限

在 Linux 上要确认 MySQL 是用 systemd 管理、用 init.d 脚本管理,还是通过 Docker 容器运行,因为三者的重置路径不同。在 Windows 上要确认 MySQL 是否注册为 Windows 服务,以及你有没有管理员权限的 CMD 或 PowerShell。

确认 Linux 服务管理方式:

systemctl status mysql 2>/dev/null || echo "未使用 systemd"
ps aux | grep mysqld

确认 Docker 容器:

docker ps | grep mysql

确认 Windows 服务:

sc query mysql
sc query mysql80

请记住服务名称,可能是 mysqlmysql57mysql80MySQL 等,不同安装方式命名不同,后续停服和启服都需要用到。

四、核心思路:为什么可以通过「跳过授权表」重置密码

MySQL 在每次处理连接请求时,都会检查 mysql 系统库中的授权表,确认「你是谁、从哪里来、密码对不对、能干什么」。这套检查机制由 grant tables(授权表)驱动。

skip-grant-tables 是 MySQL 服务端提供的一个特殊启动参数。当以该参数启动时,MySQL 会跳过所有授权表的检查,允许任何本地连接以任意账号进入,并且不需要密码。此时的 MySQL 处于「无访问控制」状态,主要用于紧急恢复:重置 root 密码、修复权限表损坏、找回误删账号等。

关键点在于:

  • 该模式只应在本地维护窗口使用,因为它会绕过所有认证和权限校验,任何能连到该端口的客户端都可能获得极高权限;
  • 在旧版本中,skip-grant-tables 还会自动启用 skip-networking,即禁止远程 TCP 连接,只能通过本机 socket 或命名管道连接,从而降低风险;
  • MySQL 8.0 中该参数不会自动禁用网络,因此建议同时手动加上 skip-networking,或者临时停止对外网络访问、修改监听端口;
  • 重置完成后必须立即去掉该参数并恢复正常启动,否则数据库将长期处于无保护状态。

除了 skip-grant-tables,MySQL 还提供了 --init-file 启动参数。它可以让 MySQL 在启动时自动执行一个指定的 SQL 文件,常用于在无法交互式进入数据库的场景下自动完成密码修改,该方法在 Linux 下尤其推荐,后文会详细演示。

接下来先从最通用、最经典的 skip-grant-tables 方法讲起,再逐步介绍其他备选方案。

五、方法一:使用 skip-grant-tables 重置密码(最通用方案)

这是 MySQL 文档和无数运维手册中最常见的方案,核心流程只有四步:停止服务、以跳过授权表模式启动、修改密码、恢复正常启动。下面按操作系统分别展开,请根据你的实际环境选择对应小节。

5.1 通用流程概述

  1. 正常停止 MySQL 服务;
  2. --skip-grant-tables 参数启动 MySQL;
  3. 无密码登录 MySQL,修改 root 密码或清空认证信息;
  4. 退出、停止当前进程,恢复标准启动;
  5. 用新密码验证登录。

特别注意:MySQL 8.0 中,若处于 skip-grant-tables 模式,直接执行 ALTER USER 可能报错,需要先执行 FLUSH PRIVILEGES 让授权表重新加载,才可以使用 ALTER USER 修改密码。5.7 及更早版本则常使用 UPDATE mysql.user 来直接更新认证字段。下面会分别给出对应命令。

5.2 Windows 环境操作步骤

第 1 步:以管理员身份打开 CMD 或 PowerShell。这一步非常关键,普通权限无法停止服务或启动 mysqld。可以按 Win 键搜索「CMD」或「PowerShell」,右键选择「以管理员身份运行」。

第 2 步:停止 MySQL 服务。服务名需要替换为你本机实际的名称:

net stop mysql80

如果不知道服务名,先查询:

sc query state= all | findstr /i "mysql"

第 3 步:进入 MySQL 的 bin 目录。默认常见路径如下,请以实际安装目录为准:

cd "C:\Program Files\MySQL\MySQL Server 8.0\bin"

第 4 步:以跳过授权表模式启动。为了便于观察报错,建议前台运行,保持当前窗口不要关闭:

mysqld --console --skip-grant-tables --shared-memory

解释一下:--console 表示把日志输出到当前窗口;--skip-grant-tables 跳过授权检查;--shared-memory 在 Windows 上启用共享内存连接,便于本机无密码登录。若你觉得存在网络暴露风险,可以再加 --skip-networking

窗口出现类似 ready for connections 或持续刷日志且不再返回命令提示符,说明 MySQL 已在该模式下启动成功。

第 5 步:新开一个管理员窗口,无密码登录。

mysql -u root -p

当提示输入密码时,直接按回车即可,因为授权检查已被跳过。

第 6 步:根据版本执行修改密码语句。

MySQL 5.7 及更早版本:

USE mysql;
UPDATE user SET authentication_string = PASSWORD('你的新密码') WHERE User = 'root' AND Host = 'localhost';
FLUSH PRIVILEGES;

MySQL 8.0:

FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';
FLUSH PRIVILEGES;

如果 8.0 中的 ALTER USER 提示错误,请先检查是否成功执行了第一条 FLUSH PRIVILEGES。执行完成后,输入 exit 退出客户端。

第 7 步:回到第一个窗口,按 Ctrl + C 终止前述 mysqld 进程。确认进程退出后再继续。

第 8 步:正常启动 MySQL 服务。

net start mysql80

第 9 步:验证新密码。

mysql -u root -p

输入新密码后如果能进入 MySQL,说明重置成功。

5.3 Linux / macOS 环境操作步骤

第 1 步:停止 MySQL 服务。

sudo systemctl stop mysql

如果没有 systemd,则使用:

sudo service mysql stop

第 2 步:以跳过授权表模式手动启动 mysqld。建议使用 mysqld_safe 或直接启动 mysqld,并同时禁止网络连接:

sudo mysqld_safe --skip-grant-tables --skip-networking

也可以用:

sudo mysqld --skip-grant-tables --skip-networking

注意:macOS Homebrew 的安装路径可能不在 PATH 中,需要先确认 mysqld 位置,例如 /usr/local/opt/mysql/bin/mysqld/opt/homebrew/opt/mysql/bin/mysqld

启动后该命令会占用当前终端,可以另开一个终端进行后续操作。

第 3 步:无密码登录。

mysql -u root -p

密码提示直接回车。

第 4 步:修改密码,命令与 Windows 部分相同。

MySQL 5.7:

USE mysql;
UPDATE user SET authentication_string = PASSWORD('你的新密码') WHERE User = 'root' AND Host = 'localhost';
FLUSH PRIVILEGES;

MySQL 8.0:

FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';
FLUSH PRIVILEGES;

第 5 步:退出客户端并停止手动启动的 mysqld 进程。

可以在第一个启动窗口按 Ctrl + C 停止;如果进程在后台,可以用以下命令结束:

sudo pkill mysqld

必要时先确认进程:

ps aux | grep mysqld

请确保杀掉的是刚才手动启动的进程,而不是系统服务进程。由于刚才的服务已经停止,通常不会误杀。

第 6 步:正常启动服务。

sudo systemctl start mysql

第 7 步:验证新密码。

mysql -u root -p

5.4 skip-grant-tables 方法常见注意事项

  • 修改密码前最好确认 mysql.user 表中 root 账号有哪些 Host 记录,必要时对 localhost127.0.0.1 等多个条目分别处理;
  • 在 MySQL 8.0 跳过授权表模式下,先执行 FLUSH PRIVILEGES 再执行 ALTER USER 是最稳妥的顺序;
  • 操作完成后一定要恢复无需密码进入的状态,即去掉 --skip-grant-tables 参数;
  • 若旧版本使用 UPDATE user SET password = PASSWORD(...) 报错提示字段不存在,说明版本已经切换到 authentication_string 字段,按 5.7 方式处理即可;
  • 如果忘记了 root 具体 Host,也可以直接把条件写出多个常用主机的组合,避免只改到部分账号。

六、方法二:使用 --init-file 自动执行 SQL 重置密码(Linux / macOS 推荐)

如果你希望尽量减少手动交互,或者 MySQL 由脚本化管理、不方便长时间前台运行,可以使用 --init-file 参数让 MySQL 在启动时自动执行一段修改密码的 SQL。该方法特别适合 Linux 服务器、自动化运维脚本和不想逐个敲命令的场景。

6.1 制作 SQL 脚本文件

首先创建一个普通文本文件,例如 /tmp/mysql-init.sql,内容根据版本选择:

MySQL 8.0:

ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';
FLUSH PRIVILEGES;

MySQL 5.7:

USE mysql;
UPDATE user SET authentication_string = PASSWORD('你的新密码') WHERE User = 'root' AND Host = 'localhost';
FLUSH PRIVILEGES;

保存文件后,需要确保该文件能被 MySQL 进程读取,同时建议设置较严格权限:

sudo chmod 600 /tmp/mysql-init.sql
sudo chown mysql:mysql /tmp/mysql-init.sql

注意:有些系统的 AppArmor 或 SELinux 可能限制 MySQL 读取 /tmp 外的路径,如果启动报错「无法读取 init-file」,可以把文件放到 MySQL 数据目录下,例如 /var/lib/mysql/mysql-init.sql,并重新设置属主权限。

6.2 停止 MySQL 服务

sudo systemctl stop mysql

6.3 以 init-file 参数启动

sudo mysqld --user=mysql --init-file=/tmp/mysql-init.sql --skip-networking

启动后,MySQL 会自动执行该 SQL 文件中的语句。执行完毕后,--init-file 指定的文件会被忽略,但该启动进程仍会继续运行。此时可以先退出当前进程:

sudo pkill mysqld

6.4 恢复正常启动并验证

sudo systemctl start mysql
mysql -u root -p

该方法的优势:全程无需手动进入 MySQL 客户端,也无需在两种模式之间来回切换,非常适合写成标准恢复脚本。另外,因为脚本由 MySQL 启动时自动执行,可以避免 skip-grant-tables 模式下手动操作可能产生的断电或误操作风险。

七、方法三:如果你能登录但想改 root 密码

有时候并不是完全忘了密码,而是 root 密码过期、太薄弱想改、或者接手的账号可以登录但需要统一密码。这种「能进 MySQL」的场景重置起来简单得多。

7.1 登录后直接修改

ALTER USER 'root'@'localhost' IDENTIFIED BY '新的强密码';
FLUSH PRIVILEGES;

MySQL 5.7 也兼容上述 ALTER USER 写法。若旧版本不支持,可使用:

SET PASSWORD FOR 'root'@'localhost' = PASSWORD('新的强密码');
FLUSH PRIVILEGES;

7.2 修改 root 的所有 Host 记录

推荐一次性看清所有 root 账号,再逐个修改:

SELECT User, Host, plugin FROM mysql.user WHERE User = 'root';

根据查询结果,对所有 root 记录执行修改,例如常见的三个:

ALTER USER 'root'@'localhost' IDENTIFIED BY '新的强密码';
ALTER USER 'root'@'127.0.0.1' IDENTIFIED BY '新的强密码';
ALTER USER 'root'@'::1' IDENTIFIED BY '新的强密码';
ALTER USER 'root'@'%' IDENTIFIED BY '新的强密码';
FLUSH PRIVILEGES;

不要只改 localhost 而忽略 %,否则通过远程或容器网络登录时仍然使用旧密码,容易再次产生「密码不对」的困惑。

7.3 如果密码已过期无法执行其他语句

MySQL 可能提示 ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.,此时直接执行:

ALTER USER USER() IDENTIFIED BY '新的强密码';

执行后即可恢复完整操作权限。

八、方法四:Docker 容器中的 MySQL 密码重置

越来越多的开发环境通过 Docker 运行 MySQL,重置方法与传统裸机略有不同,但核心思想一致。下面是两种常见场景的处理方式。

8.1 容器能够正常停止和启动的场景

查看容器名称或 ID:

docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Image}}"

假设容器名为 mysql80,可以先停掉容器:

docker stop mysql80

然后用跳过授权表参数重新启动容器。这里有两种做法:

做法 A:直接覆盖容器启动命令。

docker run --rm -it \
  -v mysql80-data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=oldpassword \
  mysql:8.0 \
  mysqld --skip-grant-tables --skip-networking

随后另开终端进入容器客户端:

docker exec -it mysql80 mysql -u root -p

输入密码提示时直接回车,再执行 ALTER USER 修改。不过这种方式如果原容器使用命名卷或复杂网络配置,覆盖启动命令要格外小心卷的挂载路径。

做法 B:进入容器内部,直接操作 mysqld。如果你不熟悉容器启动参数覆盖,可以保留原容器配置,仅临时改变运行参数:

  1. 停止容器:docker stop mysql80
  2. 不删除容器,直接挂载或复制一个小脚本后重新以参数启动;
  3. 或者使用 docker run 基于同一数据卷启动一个临时容器执行重置。

对于大多数开发场景,更简单的做法是:如果该容器没有重要数据,直接删除容器和数据卷,重新 docker run 并使用新的 MYSQL_ROOT_PASSWORD。但这会丢失数据,只适合无数据的环境。

8.2 容器无法启动、连 exec 都进不去的场景

若容器因为权限或配置问题无法正常启动,可以尝试直接操作数据卷中的文件。先找到数据卷在宿主机上的实际路径:

docker volume inspect mysql80-data

Mountpoint 路径下能通过宿主机文件系统访问 MySQL 数据目录。此时可以参照 Linux 原生场景,使用宿主机上的 mysqld 或临时容器以 --init-file 方式启动并修改密码。不过这种方式对文件权限要求较高,建议仅在熟悉卷结构的前提下使用。

Docker 场景最稳妥的日常经验是:创建容器时就把 root 密码妥善保存到 docker-compose 的 .env 文件或密钥管理工具中,从源头避免遗忘。

九、MySQL 5.7 与 8.0 的差异详解(重点,务必看)

网上大量旧教程基于 MySQL 5.6 或 5.7 编写,直接套用到 8.0 上常常报错。下表集中对比两个主流大版本的区别:

对比项 MySQL 5.7 MySQL 8.0
密码存储字段 mysql.user.authentication_string mysql.user.authentication_string
默认认证插件 mysql_native_password caching_sha2_password
修改密码推荐语句 ALTER USERSET PASSWORD ALTER USER(推荐)
PASSWORD() 函数 可用 已移除,调用会报错
直接 UPDATE mysql.user 写哈希 可行但需注意格式 不推荐,容易写出错误哈希
跳过授权表下改密码 UPDATEFLUSH FLUSH PRIVILEGESALTER USER
密码策略相关插件 validate_password validate_password(组件形式)

下面重点解释最容易被坑的三点。

9.1 为什么 8.0 不能用 PASSWORD() 函数写入哈希

MySQL 8.0 移除了 PASSWORD() 函数,执行以下语句会直接报错:

UPDATE mysql.user SET authentication_string = PASSWORD('newpass') WHERE User = 'root';

报错类似 FUNCTION mysql.PASSWORD does not exist。在 8.0 中必须使用 ALTER USERSET PASSWORD,让服务器根据当前认证插件生成正确的密文。

9.2 为什么跳过授权表模式下 8.0 的 ALTER USER 会失败

skip-grant-tables 模式下,授权表处于关闭状态,ALTER USER 这类需要读取授权数据的操作可能无法正常工作。正确做法是先执行:

FLUSH PRIVILEGES;

该语句会重新加载授权表,让 ALTER USER 可以正常执行。完成密码修改后,再次执行 FLUSH PRIVILEGES 确保生效。

9.3 认证插件差异带来的客户端兼容问题

8.0 默认使用 caching_sha2_password,部分老旧的 MySQL 客户端、驱动或连接工具不支持该插件,登录时报错 Authentication plugin 'caching_sha2_password' cannot be loaded。此时可以在修改密码时显式指定旧插件:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的新密码';

这样可以在保持 8.0 版本的同时,兼容旧客户端。

十、修改密码的常用 SQL 语句详解

虽然重置场景中常用 ALTER USER,但了解不同语句的适用版本和边界,有助于在报错时快速定位问题。下面逐一说明。

10.1 ALTER USER 语句

ALTER USER 是 MySQL 5.6 后期引入、5.7 和 8.0 都支持的官方推荐语句。基本格式:

ALTER USER '用户名'@'主机' IDENTIFIED BY '密码';

如果同时要修改认证插件:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码';

如果想让密码永不过期:

ALTER USER 'root'@'localhost' IDENTIFIED BY '密码' PASSWORD EXPIRE NEVER;

10.2 SET PASSWORD 语句

SET PASSWORD 在现代版本中同样可用:

SET PASSWORD FOR 'root'@'localhost' = '新密码';

在 MySQL 8.0 中,上述语句会直接处理密码哈希。但若在 5.6 等老版本,可能需要 PASSWORD() 包裹:

SET PASSWORD FOR 'root'@'localhost' = PASSWORD('新密码');

为当前登录用户改密码时可简写为:

SET PASSWORD = '新密码';

10.3 直接 UPDATE mysql.user 的老方法

此方法在 5.6、5.7 中常见,但 8.0 中不推荐直接写入:

USE mysql;
UPDATE user SET authentication_string = PASSWORD('新密码') WHERE User = 'root';
FLUSH PRIVILEGES;

风险在于:如果版本与字段、插件不一致,可能生成错误的认证信息,导致改完后依旧无法登录。因此只要版本支持 ALTER USER,就优先用 ALTER USER

10.4 修改后立即生效的机制

使用 ALTER USERSET PASSWORD 修改密码后,授权信息会立即对后续新建连接生效。对于已经建立的旧连接,大多不受影响;若希望强制所有连接使用新密码,可以进一步限制或回收会话,但日常场景下无需处理。

如果执行的是 UPDATE mysql.user 这类直接改表操作,则必须执行 FLUSH PRIVILEGES 让服务器重新读取授权表。

十一、常见报错与排查思路

密码重置过程中,几乎每个人都会遇到几个经典报错。下面逐一解释原因和解决办法。

11.1 ERROR 1045 (28000): Access denied for user 'root'@'localhost'

这是最典型的「密码错误或账号不存在」提示。可能原因:

  • 确实输错密码;
  • 修改密码时只改了 root@localhost,而当前连接匹配的是 root@127.0.0.1 或其他 Host;
  • 客户端用了 socket 或 TCP 不同通道,匹配到不同账号;
  • 认证插件不一致,导致客户端无法完成握手。

排查建议:先确认修改时覆盖了所有 root Host 记录,再确认登录命令中的 -h 参数。例如 mysql -h 127.0.0.1 -u root -p 使用的是 TCP,而省略 -h 通常走本机 socket。

11.2 ERROR 1820 (HY000): You must reset your password

该错误表示当前账号的密码已过期或处于需强制修改状态。解决办法就是先执行一次密码修改:

ALTER USER USER() IDENTIFIED BY '新密码';

11.3 ERROR 1396 (HY000): Operation ALTER USER failed for 'root'@'...'

常见原因是目标账号不存在,即你写的 Host 和表里的 Host 不一致。先用以下语句确认实际存在哪些 root 账号:

SELECT User, Host FROM mysql.user WHERE User = 'root';

然后再对实际存在的 Host 执行修改。

11.4 ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

这是密码策略校验未通过。MySQL 的 validate_password 组件可能要求密码包含大小写字母、数字、特殊字符,且达到一定长度。解决办法有两个:

  • 改用符合安全策略的强密码;
  • 在开发环境临时降低策略或关闭校验(生产环境不建议)。

查看策略:

SHOW VARIABLES LIKE 'validate_password%';

8.0 中若使用组件形式:

SET GLOBAL validate_password.policy = LOW;
SET GLOBAL validate_password.length = 6;

修改后重试密码修改语句即可。

11.5 Authentication plugin 'caching_sha2_password' cannot be loaded

这是客户端或连接库太老,不支持 8.0 默认认证插件。可在服务端把 root 账号改为兼容插件:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';

11.6 启动报错:Can't open and lock privilege tables

大多数情况下是因为数据目录权限不对,或 MySQL 数据目录损坏。先检查数据目录属主是否被改成非 mysql 用户:

ls -ld /var/lib/mysql
sudo chown -R mysql:mysql /var/lib/mysql

若问题依旧,需要从备份恢复或通过日志进一步排查,通常已超出单纯密码重置范畴。

十二、重置后的安全加固建议

密码找回只是第一步,重置之后如果不做安全加固,可能会留下更大的隐患。以下建议按优先级排列。

12.1 删除或停用无用的匿名账号和远程 root

SELECT User, Host FROM mysql.user WHERE User = '' OR (User = 'root' AND Host = '%');

如果确认不需要远程 root,可以删除不必要的 Host 记录:

DROP USER 'root'@'%';

删除前务必确认不会影响正常业务连接。

12.2 设置强密码并启用密码校验

强密码建议至少 16 位,包含大小写字母、数字和特殊字符,避免使用生日、常见单词、连续字符等弱组合。对于生产环境,应保留 validate_password 组件并设置合理策略。

12.3 收紧远程访问

如果数据库只在本机使用,可将绑定地址限制为 127.0.0.1

# 在配置文件的 [mysqld] 段增加
bind-address = 127.0.0.1
skip-networking
# 根据实际需要二选一,skip-networking 会完全禁用 TCP

修改后重启 MySQL 生效。

12.4 建立密码管理规范

  • 把 root 密码存入加密的密码管理器;
  • 在服务器文档中记录账号与用途,但不要以明文随意粘贴到聊天或工单;
  • 为不同应用建立独立账号,避免所有程序都使用 root;
  • 定期轮换密码,并在轮换后同步更新配置文件中的连接串。

12.5 确认重置成功后清理中间文件

如果使用了 --init-file 方法,记得删除包含明文密码的 SQL 文件:

sudo rm -f /tmp/mysql-init.sql

同时检查是否有临时备份文件残留在数据目录或 /tmp 下,避免明文密码长期暴露。

十三、全流程速查清单与操作模板

为方便你在实际操作时快速对照,这里把最常用的两条路径整理成模板。模板中的服务名、路径、密码请替换为你的真实值。

13.1 Linux 8.0 快速重置模板(init-file 方式)

# 1. 写入重置脚本
cat > /tmp/mysql-init.sql <<'EOF'
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewStrongPass!2026';
FLUSH PRIVILEGES;
EOF
2. 设置权限
sudo chown mysql:mysql /tmp/mysql-init.sql
sudo chmod 600 /tmp/mysql-init.sql
3. 停止服务并以 init-file 启动
sudo systemctl stop mysql
sudo mysqld --user=mysql --init-file=/tmp/mysql-init.sql --skip-networking
4. 等待几秒后结束该进程
sleep 5
sudo pkill mysqld
5. 正常启动并验证
sudo systemctl start mysql
mysql -u root -p
6. 清理脚本
sudo rm -f /tmp/mysql-init.sql

注意上面的 <<'EOF'&> 等符号在 HTML 代码块中已做转义展示,实际终端命令以语义为准。

13.2 Windows 快速重置模板(skip-grant-tables 方式)

:: 1. 管理员 CMD 停止服务
net stop mysql80
:: 2. 进入 bin 目录
cd /d "C:\Program Files\MySQL\MySQL Server 8.0\bin"
:: 3. 跳过授权表启动,保持窗口
mysqld --console --skip-grant-tables --shared-memory
:: 4. 另开管理员窗口登录
mysql -u root -p
:: 5. 登录后执行
FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'NewStrongPass!2026';
FLUSH PRIVILEGES;
exit;
:: 6. 回到第 3 步窗口按 Ctrl+C 结束,再正常启动
net start mysql80

十四、总结:找回密码并不难,难的是养成良好习惯

回顾整个流程,MySQL root 密码遗忘的解决办法可以概括为:停止服务,临时以无授权或自动执行 SQL 的方式启动,修改认证信息,再恢复正常启动。无论 Windows、Linux、macOS 还是 Docker,万变不离其宗。真正的难点不在命令本身,而在于快速识别自己的 MySQL 版本和运行环境,从而选择正确的那组命令。

除了掌握重置技能,更值得投入的是日常管理习惯:把关键密码放进加密工具、为不同应用创建独立账号、限制 root 的远程访问、定期备份数据。这样即使再次遇到密码丢失,也能从容应对,不会因为一次小失误影响业务和数据安全。

希望这篇教程能帮你顺利找回 root 权限。如果在操作中遇到未覆盖到的报错,建议结合 MySQL 错误日志、官方文档和当前版本特性进一步排查。只要思路正确,绝大多数密码丢失问题都能在几分钟内解决。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐