
定期轮换数据库密码是经常会做的一件小事:在新同事入职后、交接服务器前,或刚怀疑凭据已泄露时。在 MySQL 和 MariaDB 中,这只是一条 SQL 语句,但正确的语法在不同大版本间有所变化,网上许多旧教程仍在展示早已不再生效的命令。
本指南介绍如何从 mysql shell 修改 MySQL 或 MariaDB 用户密码,采用在 MySQL 5.7.6+、MySQL 8.0 与 8.4、以及 MariaDB 10.2+ 上均有效的现代语法。
检查数据库版本
修改密码的命令取决于你运行的服务器。首先,可以用 mysql --version 查看已安装的客户端版本:
mysql --version
典型的 MySQL 输出:
mysql Ver 8.4.11-0ubuntu0.26.04.1 for Linux on x86_64 ((Ubuntu))
典型的 MariaDB 输出:
mysql from 11.8.6-MariaDB, client 15.2 for debian-linux-gnu (x86_64) using EditLine wrapper
在 MariaDB 上,客户端也可作为 mariadb 使用。客户端版本可能不同于服务器版本,尤其是在连接远程数据库时。登录后请按下方所示检查所连接服务器的版本。
在修改前查看现有账户列表,请参阅如何显示 MySQL 用户。
如何修改 MySQL 用户密码
按以下步骤修改 MySQL 或 MariaDB 用户账户的密码。
1. 以 root 身份登录 MySQL shell
以 root 用户身份打开 MySQL shell,并在提示时输入密码:
mysql -u root -p
如果尚未为 MySQL root 账户设置密码,或你的安装使用了 auth_socket 插件(近期 Ubuntu 软件包的默认设置),请用以下方式登录:
sudo mysql
连接后,在选择修改密码的语法前先检查服务器版本:
SELECT VERSION
()
;
结果会显示服务器版本。MariaDB 的版本字符串中会包含 MariaDB。
2. 修改用户密码
在 MySQL 5.7.6 及更高版本、MySQL 8.0 与 8.4、以及 MariaDB 10.2 及更高版本上,使用 ALTER USER:
ALTER USER
'user-name'
@
'localhost'
IDENTIFIED BY
'NEW_USER_PASSWORD'
;
将 user-name 替换为要更新的账户,将 NEW_USER_PASSWORD 替换为新密码。若该用户从远程主机连接,请将 localhost 替换为该账户定义的对应主机或 IP 地址。
也可以使用 SET PASSWORD。在 MySQL 上,将新密码作为普通字符串传入:
SET PASSWORD FOR
'user-name'
@
'localhost'
=
'NEW_USER_PASSWORD'
;
MariaDB 在 SET PASSWORD 中要求密码哈希。请将新密码用 PASSWORD() 函数包裹:
SET PASSWORD FOR
'user-name'
@
'localhost'
=
PASSWORD
(
'NEW_USER_PASSWORD'
)
;
在 MySQL 8.0 及更高版本上,PASSWORD() 函数已不存在,使用它会引发语法错误。在 MariaDB 上,普通字符串会失败并报 ERROR 1372。如果不确定运行的是哪类服务器,请使用 ALTER USER,它在两者上的行为一致。
若修改成功,服务器返回:
Query OK, 0 rows affected (0.00 sec)
在使用 ALTER USER 或 SET PASSWORD 之后,无需运行 FLUSH PRIVILEGES。只有在直接修改授权表、以及在使用 --skip-grant-tables 恢复访问前使用账户管理语句时才需要它。
退出 MySQL shell:
quit
;
3. 验证新密码
用刚刚更新的用户账户连接:
mysql -u user-name -h localhost -p
在提示符处输入新密码。如果凭据正确,MySQL shell 会打开;否则你会收到 ERROR 1045 (Access denied),需要重复第 2 步。
修改 MySQL root 密码
在 Ubuntu 和 Debian 上,数据库 root 账户默认不使用密码登录。MySQL 使用 auth_socket 插件,MariaDB 使用 unix_socket。两者都允许系统 root 用户通过 sudo mysql 免密码打开 shell。要设置 root 密码,你还需要改变 root 的登录方式。
MySQL 8.0 及更高版本
用 sudo mysql 登录,并将 root 切换为密码认证:
ALTER USER
'root'
@
'localhost'
IDENTIFIED WITH caching_sha2_password BY
'NEW_ROOT_PASSWORD'
;
IDENTIFIED WITH caching_sha2_password 部分是必需的。单纯的 ALTER USER ... IDENTIFIED BY 会返回 Query OK,但账户仍停留在 auth_socket,新密码永远不会被使用。
一旦 root 设置了密码,sudo mysql 将不再可用。今后请用以下方式登录:
mysql -u root -p
如果 root 已经使用密码认证,第 2 步的 ALTER USER 语句就足够了。在 MySQL 8.0 及更高版本上,将 root 从 socket 切换为密码认证时请使用 caching_sha2_password。MySQL 8.4 默认禁用 mysql_native_password,因此选择该插件会失败并报 ERROR 1524。
在 MySQL 5.7 上,服务器不支持 caching_sha2_password。要在该版本上将 socket 认证的 root 账户切换为密码认证,请改用 IDENTIFIED WITH mysql_native_password BY 'NEW_ROOT_PASSWORD'。
MariaDB
在 MariaDB 10.4 及更高版本上,root 既可以通过 Unix socket 登录,也可以使用密码登录。要在一条语句中同时保留两种方式并设置密码,请运行:
ALTER USER
'root'
@
'localhost'
IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD
(
'NEW_ROOT_PASSWORD'
)
;
此后,sudo mysql 仍然可用,而 mysql -u root -p 也接受新密码。
单纯的 ALTER USER 'root'@'localhost' IDENTIFIED BY '...' 也会设置密码,但会移除账户上的 unix_socket。之后 sudo mysql 会失败并报 ERROR 1045。
故障排查
ERROR 1064 (42000): You have an error in your SQL syntax 你很可能运行的是 MySQL 8.0 或更高版本,并传入了旧的 PASSWORD('...') 包裹。请移除包裹,并将密码作为普通引号字符串传入:ALTER USER 'user'@'localhost' IDENTIFIED BY 'secret';。在 MariaDB 上,MySQL 语法 IDENTIFIED WITH caching_sha2_password BY '...' 也会产生语法错误:MariaDB 在插件认证字符串上使用 USING 或 AS,而不是 BY。近期 MariaDB 版本包含了用于迁移的 caching_sha2_password 插件,但默认未安装。对于 root,请使用上面的 MariaDB 语句。
ERROR 1372 (HY000): Password hash should be a 41-digit hexadecimal number 你在 MariaDB 上对 SET PASSWORD 使用了普通字符串。MariaDB 此处要求哈希。请将密码用 PASSWORD('...') 包裹,或改用 ALTER USER ... IDENTIFIED BY。
ERROR 1524 (HY000): Plugin 'mysql_native_password' is not loaded MySQL 8.4 默认禁用 mysql_native_password 插件。请改用 IDENTIFIED WITH caching_sha2_password。自 MySQL 8.0 起它一直是默认认证插件。
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements validate_password 组件处于启用状态,且新密码过于简单。mysql_secure_installation 会在初始化时提供启用它的选项。用 SHOW VARIABLES LIKE 'validate_password%'; 查看当前规则,并选择包含大小写字母、数字和特殊字符的更长密码。
ERROR 1698 (28000): Access denied for user 'root'@'localhost' root 账户仍在使用 auth_socket。当你用单纯的 ALTER USER ... IDENTIFIED BY 在 MySQL 上设置 root 密码时会出现这种情况。请用 sudo mysql 登录,并使用适用于你 MySQL 版本的 root 密码语句。
ERROR 1045 (28000): Access denied for user 要么你输入的密码有误,要么该账户使用了不同的主机。用 SELECT user, host FROM mysql.user; 列出账户,并确认你要更新的是客户端尝试认证的精确 'user'@'host' 对。
ERROR 1396 (HY000): Operation ALTER USER failed for 'user'@'localhost' 该账户在对应主机上不存在。请仔细核对主机部分(例如 'user'@'%' 与 'user'@'localhost' 是不同的账户)。用 CREATE USER 创建账户,或使用正确的主机进行更新。
密码修改对远程客户端无效 该用户从与你更新时不同的主机连接。MySQL 将 'user'@'localhost' 和 'user'@'10.0.0.5' 视为独立账户,各自拥有自己的密码。请更新你关心的每个主机条目。
常见问题
如何修改 MySQL root 密码?在装有 MySQL 8.0 或更高版本的 Ubuntu 上,用 sudo mysql 登录并运行 ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'new_password';。MySQL 5.7 需要改用 mysql_native_password。在 MariaDB 10.4 及更高版本上,使用 IDENTIFIED VIA unix_socket OR mysql_native_password USING PASSWORD('new_password') 以保留 sudo mysql 可用。
使用 ALTER USER 后是否需要运行 FLUSH PRIVILEGES?不需要。账户管理语句如 ALTER USER、SET PASSWORD、CREATE USER、DROP USER 和 GRANT 无需它即可生效。只有在直接修改授权表后,或在使用 --skip-grant-tables 恢复访问前使用 ALTER USER 时才需要 FLUSH PRIVILEGES。
如何重置忘记的 MySQL root 密码?使用 --skip-grant-tables 恢复需要先运行 FLUSH PRIVILEGES; 再执行 ALTER USER,然后正常重启服务器。请遵循完整步骤(包括 systemd 部分),参见我们关于如何重置 MySQL root 密码的指南。
为什么 SET PASSWORD 使用 PASSWORD('...') 会失败?PASSWORD() 函数在 MySQL 5.7 中已弃用,并在 MySQL 8.0 中被移除。请使用普通字符串形式:SET PASSWORD FOR 'user'@'host' = 'new_password';。MariaDB 是例外,它在 SET PASSWORD 中仍要求 PASSWORD()。
结论
在现代 MySQL 和 MariaDB 服务器上,ALTER USER 是修改密码唯一需要记住的命令,且配合它无需运行 FLUSH PRIVILEGES。有关完整的账户与权限命令集,请参阅关于如何管理 MySQL 用户账户与数据库的指南。