线上数据库的用户管理,是安全防线的最前沿。一个弱密码、一个被遗忘的测试账号、一条范围过大的授权语句,都可能让整个数据库暴露在风险中。本节聚焦用户管理的基础操作,不讲空泛的理论,只讲你上手就能用的命令和必须注意的细节。
23.1.1 创建用户
MySQL 的用户由 账号 和 允许连接的客户端主机 共同确定,即 'user'@'host' 是一个完整的用户标识。'app'@'192.168.1.%' 和 'app'@'%' 是两个完全不同的用户,各自拥有独立的权限。
创建用户的基本语法如下:
CREATE USER '用户名'@'主机' IDENTIFIED BY '密码';
注意主机部分的写法,它决定了这个账号能从哪里连接数据库:
'localhost':只能从本机通过 socket 连接,最安全,适合运维管理账号。'192.168.1.100':仅允许指定 IP 连接。'192.168.1.%':允许该网段内所有 IP 连接。'%':允许任何 IP 连接,虽然方便但对生产环境不够安全,应尽量避免,除非确有跨公网访问需求。
示例,创建一个只能从内网某网段连接的应用账号:
CREATE USER 'app_user'@'10.0.1.%' IDENTIFIED BY 'A_Strong_Passw0rd';
如果你希望用户连接后就被强制修改密码,可以在创建时加上 PASSWORD EXPIRE:
CREATE USER 'new_user'@'%' IDENTIFIED BY 'Temp_Passw0rd' PASSWORD EXPIRE;
另外,从 MySQL 8.0 开始,默认的身份验证插件从 mysql_native_password 变更为更安全的 caching_sha2_password。一些老旧的客户端(如较老的 mysql-connector 版本)可能不支持新的认证方式,如果连接报错,可以通过 IDENTIFIED WITH mysql_native_password BY '密码' 显式指定旧的认证插件,但这只是临时兼容方案,最佳实践是升级客户端。
创建用户后,该账号默认没有任何数据库的操作权限,需要单独授权(见 23.3 节)。注意,CREATE USER 执行时,MySQL 会自动把密码哈希后存入 mysql.user 表,密码不会被明文记录。
23.1.2 删除用户
清理不再使用的账号,是减少攻击面的基本操作。必须精确指定用户和主机:
DROP USER '用户名'@'主机';
例如删除测试账号:
DROP USER 'test_app'@'%';
这条命令不仅会移除用户,还会回收该用户所有的权限,并关闭该用户现有的所有连接(MySQL 5.7 之后)。在删除前,建议先用 SELECT 确认你要删的用户是不是还存在:
SELECT user, host FROM mysql.user WHERE user = 'test_app';
一个常见错误是:如果忘记了指定主机部分,比如只写 DROP USER 'test_app';,MySQL 会尝试删除 'test_app'@'%',如果该用户实际上定义的是 'test_app'@'localhost',则删除操作会失败,并提示用户不存在。所以务必保持“用户名@主机”的完整写法。
如果你的数据库是从 5.6 或更早版本升级上来的,可能存在 DROP USER 无法自动关闭已存在连接的情况,此时可以手动通过 SHOW PROCESSLIST 找到该用户的连接 ID,执行 KILL <id> 后再删除用户。
23.1.3 密码管理
密码管理主要包括修改密码、密码过期策略、密码强度检查三个方面。
修改密码
最常用的方式是通过 ALTER USER:
ALTER USER '用户名'@'主机' IDENTIFIED BY '新密码';
如果是让用户自己修改当前连接用户的密码,可以简写为:
ALTER USER USER() IDENTIFIED BY '新密码';
对于 MySQL 5.6 及更早版本,或者需要兼容的场景,也可以用 SET PASSWORD,但不推荐在新版本中使用。
另一个常见的需求是应急情况下通过命令行直接传递新密码修改 root 密码(例如忘记 root 密码后的重置流程,该流程通常需要先停止 MySQL,用 --skip-grant-tables 启动,然后手动更新 mysql.user 表,这里不深入展开)。
密码过期策略
你可以强制要求用户定期更换密码,通过 PASSWORD EXPIRE INTERVAL N DAY 设置,比如每 90 天过期:
ALTER USER 'app_user'@'10.0.1.%' PASSWORD EXPIRE INTERVAL 90 DAY;
设置为 PASSWORD EXPIRE NEVER 则取消过期,PASSWORD EXPIRE DEFAULT 则使用全局默认策略(通过 default_password_lifetime 系统变量控制)。
当密码过期后,用户下次登录时会强制要求修改密码(除非账号被锁定),这有助于满足安全审计要求。
密码强度检查
MySQL 8.0 内置了 validate_password 插件,用来强制密码复杂度,防止弱密码。你可以通过以下命令查看当前密码策略:
SHOW VARIABLES LIKE 'validate_password%';
关键参数包括:
validate_password.policy:强度级别(LOW/MEDIUM/STRONG),生产环境建议至少 MEDIUM。validate_password.length:最小长度,默认为 8。validate_password.mixed_case_count:至少包含的大小写字母数。validate_password.number_count:至少包含的数字个数。validate_password.special_char_count:至少包含的特殊字符个数。
如果你安装了该插件,设置密码时不符合复杂度要求会导致创建或修改密码失败,从而在数据库层面杜绝了诸如 123456、password 这种危险的弱密码。
其他实用操作
- 账号锁定/解锁:MySQL 8.0 支持
ACCOUNT LOCK/UNLOCK,当某个业务账号不再需要写访问但又不方便立即删除时,可以临时锁定:
ALTER USER 'readonly_user'@'%' ACCOUNT LOCK;
ALTER USER 'readonly_user'@'%' ACCOUNT UNLOCK;
- 查看用户信息:除了
SELECT user,host FROM mysql.user,还可以用SHOW CREATE USER '用户名'@'主机';得到创建该用户时所用的完整语句,方便审计和重建。
掌握以上操作,配合后续的权限管理,你就能搭建一个安全、可控的 MySQL 用户体系。记住两点最核心的原则:最小权限和最小暴露面——尽可能使用准对特定库、特定业务的账号,并且仅从内网必要机器开放连接。这些看似繁琐的步骤,最终保护的是你的数据资产。