创建用户需指定用户名和主机名,如'prodapp'@'10.209.112.%',禁止使用'%';授予权限时遵循最小必要原则,如grant select on reportdb.* to 'rpt_user'@'%';执行后必须flush privileges;并用show grants验证。

怎么创建用户并限定连接来源
MySQL 用户名和主机名共同构成唯一身份,比如 'appuser'@'192.168.1.%' 和 'appuser'@'localhost' 是两个完全独立的账号。不写主机名或写成 '%' 虽然方便,但会允许任意 IP 连接,线上环境必须避免。
- 开发测试可用:
CREATE USER 'devuser'@'%' IDENTIFIED BY 'StrongPass!2026'; - 生产环境推荐按网段限制:
CREATE USER 'prodapp'@'10.209.112.%' IDENTIFIED BY 'Zx9#kL2$mQv'; - 本地调试优先用
'localhost'(注意不是127.0.0.1,二者在 Unix socket 认证下行为不同) - 执行后务必
FLUSH PRIVILEGES;,否则权限表不会重载,新用户连不上
授什么权限?按最小必要原则配
给 ALL PRIVILEGES 是最常见也最危险的操作,尤其当用户能连上 mysql 系统库时,可能直接改掉其他用户的密码或删掉权限表。真实业务中 95% 的场景只需要数据库级操作权限。
- 只读报表账号:
GRANT SELECT ON reportdb.* TO 'rpt_user'@'%'; - 应用写入账号:
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app_rw'@'10.209.112.%'; - 需要建表/改结构?补上
CREATE, ALTER, DROP,但别给CREATE USER或SUPER - 若需跨库 JOIN,权限得分别授予涉及的每个库,MySQL 不支持“跨库通配”
为什么 SHOW GRANTS 看不到刚授的权?
常见现象:执行了 GRANT,再 SHOW GRANTS FOR 'user'@'host'; 却显示空或旧权限——大概率是忘了 FLUSH PRIVILEGES;,或者用了错误的 host 匹配形式。
-
SHOW GRANTS查的是内存中已加载的权限缓存,不是实时查mysql.user表 - 确认用户是否真被创建:
SELECT User, Host FROM mysql.user WHERE User = 'test'; - 检查 host 是否精确匹配,
'test'@'localhost'≠'test'@'127.0.0.1',哪怕你用mysql -utest -p从本机连,实际认证 host 可能是后者 - 权限生效前,用新账号登录测试比看命令输出更可靠
如何安全地批量管理权限(比如换环境、加白名单)
手动敲 GRANT 容易出错,尤其当要同步多个库、多个用户、多个 IP 段时。建议把权限逻辑封装成可复用的 SQL 模板,而不是靠记忆拼写。
- 用变量生成动态语句(在 MySQL 8.0+ 支持 PREPARE):
SET @sql = CONCAT('GRANT SELECT ON ', @dbname, '.* TO ''', @user, '''@''', @host, ''''); - IP 白名单建议统一用 CIDR 格式,如
'192.168.5.0/24',避免漏掉某台跳板机 - 密码必须走随机生成(至少 12 位含大小写+数字+符号),禁止明文硬编码在脚本里
- 所有权限变更操作,建议先在测试库跑通,再用相同 SQL 应用于生产,中间不要人工修改
权限配置真正难的不是语法,而是厘清“谁在什么网络环境下访问什么数据、做哪些操作”。很多线上事故都源于一个 @'%' 或一次忘记 FLUSH PRIVILEGES。越早把权限策略固化成脚本或配置模板,后期维护成本越低。










