开发、测试、生产三套环境必须用三套独立账号且权限不能跨环境继承,因开发/测试需建库删表等高危操作,复用生产账号易致误连误删;生产账号禁止通配符主机(%)及grant option、drop等高危权限,须精确绑定ip并定期审计。

直接结论:开发、测试、生产三套环境必须用三套独立账号,且权限不能跨环境继承;生产环境禁止任何通配符主机(%),更不能开放 GRANT OPTION 或 DROP 权限。
为什么开发/测试账号不能复用生产账号
开发和测试环境常需建库、删表、清空数据,但这些操作在生产环境是高危行为。如果用同一账号连多个环境,只要密码泄露或配置写错(比如测试脚本误连生产),DROP DATABASE 一条命令就能让整个业务停摆。MySQL 不会自动识别“你现在连的是测试还是生产”,它只认 'user'@'host' 这个组合——'dev_user'@'localhost' 和 'dev_user'@'192.168.10.%' 是两个完全不同的用户,权限互不影响。
常见错误现象:
- 开发人员本地执行
DROP TABLE users;,结果连上了生产库,因为连接串里 host 写成了192.168.10.5(生产 DB 地址) - 测试脚本用
'app_user'@'%'连接,该账号在生产库也存在,且被误授了ALTER权限,导致测试变更意外影响线上表结构
三套账号的最小权限分配模板
每套账号都应严格绑定 IP 范围,并禁用全局高危权限。以下为推荐写法(MySQL 8.0+):
开发环境(仅限本地):
CREATE USER 'dev_user'@'localhost' IDENTIFIED BY 'DevPass!2026'; GRANT CREATE, DROP, ALTER, SELECT, INSERT, UPDATE, DELETE ON dev_db.* TO 'dev_user'@'localhost';
测试环境(限定测试网段):
CREATE USER 'test_user'@'10.0.2.%' IDENTIFIED BY 'TestPass!2026'; GRANT SELECT, INSERT, UPDATE, DELETE ON test_db.* TO 'test_user'@'10.0.2.%'; -- 禁止 GRANT OPTION,避免测试账号给自己加权限
生产环境(精确到应用服务器 IP):
CREATE USER 'prod_app'@'172.16.31.42' IDENTIFIED BY 'ProdAppPass!2026'; GRANT SELECT, INSERT, UPDATE, DELETE ON prod_db.* TO 'prod_app'@'172.16.31.42'; -- 绝对不授 CREATE、DROP、ALTER、GRANT OPTION、FILE、SHUTDOWN
关键点:
- 生产账号的
host必须是具体 IP 或最小网段,不能用%;否则任意公网机器都能连 - 所有生产账号都不该有
GRANT OPTION—— 一旦开启,它就能给自己或别人授权,等于绕过权限管控 - 开发账号可授
ALL PRIVILEGES ON dev_db.*,但绝不能授ON *.*,防止误操作波及系统库
权限生效前必须做的两件事
MySQL 的权限不是创建完就立刻生效的。很多团队部署后发现“明明授了权,应用还是连不上”,问题就出在这两步漏了:
- 执行
FLUSH PRIVILEGES;—— 强制重载权限表(虽然多数情况下GRANT自动触发,但显式执行更稳妥) - 用
SHOW GRANTS FOR 'user'@'host';验证实际授予的权限,而不是只看自己写的 SQL
特别注意:SELECT CURRENT_USER(); 返回的是你实际登录所匹配的 'user'@'host',而 SELECT USER(); 返回的是客户端声明的用户名。两者不一致时,权限判断以 CURRENT_USER() 为准——这也是为什么有时“明明创建了 'app'@'192.168.1.%',但应用连不上”,很可能是因为客户端填的是 192.168.1.100,而 MySQL 匹配到了 'app'@'%' 这个权限更宽泛但没授过权的记录。
最容易被忽略的细节:认证插件与密码策略
MySQL 8.0 默认使用 caching_sha2_password 插件,但老版本客户端(如某些 Python MySQL 驱动旧版)可能不支持,报错 Authentication plugin 'caching_sha2_password' cannot be loaded。这时不能直接降级服务端,而应为特定账号指定兼容插件:
ALTER USER 'prod_app'@'172.16.31.42' IDENTIFIED WITH mysql_native_password BY 'ProdAppPass!2026';
另外,生产账号建议启用密码过期策略:
ALTER USER 'prod_app'@'172.16.31.42' PASSWORD EXPIRE INTERVAL 90 DAY;
真正难的不是写几条 GRANT,而是把每个账号的 host、plugin、PASSWORD EXPIRE、ACCOUNT LOCK 全部纳入运维清单定期审计——权限体系一旦松动,补救成本远高于初期设计成本。











