MySQL 8.0+ 禁止 GRANT 隐式创建用户,必须先 CREATE USER 再 GRANT,否则报 ERROR 1410;strict 模式下该语法直接被拒绝,权限不生效。

直接用 GRANT 隐式创建用户在 MySQL 8.0+ 已被弃用,且 strict 模式下会报 ERROR 1410 (42000): You are not allowed to create a user with GRANT;必须先 CREATE USER,再 GRANT,否则权限根本不会生效。
CREATE USER 必须显式执行,不能省略
MySQL 5.7+ 默认启用 sql_mode=STRICT_TRANS_TABLES,此时如果跳过 CREATE USER、只写 GRANT ... TO 'app'@'10.20.30.%',MySQL 会尝试隐式建户——但 strict 模式禁止该行为,直接拒绝执行。
- 正确做法:先运行
CREATE USER 'app_rw'@'10.20.30.%' IDENTIFIED BY 'xxx' PASSWORD EXPIRE ACCOUNT LOCK;(PASSWORD EXPIRE和ACCOUNT LOCK是安全加固项,程序账号无需登录) - host 写
'localhost'≠ 所有本地连接都匹配:它只响应 Unix socket 连接;应用若用127.0.0.1或内网 IP 走 TCP,则必须用'10.20.30.%'或具体 CIDR(如'10.100.0.0/255.255.0.0') - 密码不要硬编码,应从密钥服务注入;生产环境禁用空密码、弱密码、明文配置
GRANT 必须精确到表,禁用 *.* 和 mydb.*
给 mydb.* 授权等于把日志表、审计表、临时配置表全放开,违背最小权限原则。真实业务极少需要操作整个库的所有表。
- 先确认应用实际访问哪些表:开启
general_log,跑典型链路,再查mysql.general_log中的SELECT/UPDATE语句,提取真实表名 - 按需授权,例如只读订单页:
GRANT SELECT ON mydb.orders TO 'reporter'@'10.20.30.%'; - 写账号也别贪全:
GRANT INSERT, UPDATE ON mydb.orders TO 'order_writer'@'10.20.30.%';,不涉及删除就别加DELETE - 绝对禁用:
GRANT ALL PRIVILEGES ON *.*、GRANT ... WITH GRANT OPTION、对mysql系统库授予权限
MySQL 8.0+ 必须用角色封装权限
直接给用户授予权限难维护,尤其当多个服务共用一类权限时。角色不是可选项,是批量管控的基础设施。
- 建角色:
CREATE ROLE 'app_reader', 'app_writer'; - 授角色权限:
GRANT SELECT ON mydb.orders TO 'app_reader';,GRANT INSERT, UPDATE ON mydb.orders TO 'app_writer'; - 绑定并设默认角色:
GRANT 'app_reader' TO 'webapp'@'10.20.30.%'; SET DEFAULT ROLE 'app_reader' TO 'webapp'@'10.20.30.%'; -
SHOW GRANTS FOR 'webapp'@'10.20.30.%'看不到角色权限,得用SHOW GRANTS FOR 'webapp'@'10.20.30.%' USING 'app_reader';或登录后查CURRENT_ROLE()
FLUSH PRIVILEGES 不是必需步骤
用 CREATE USER、GRANT、DROP USER 这类 DCL 语句修改权限时,MySQL 自动重载权限缓存;只有直接更新 mysql.user 等系统表才需要手动 FLUSH PRIVILEGES。
- 误加
FLUSH PRIVILEGES不报错,但属于冗余操作,还可能误导人以为“不刷就不生效” - 验证权限是否生效,最可靠方式是用新账号直连测试:
mysql -u app_rw -p -h 10.20.30.5 -e "SELECT * FROM mydb.orders LIMIT 1;" - 连接失败时优先检查 host 匹配(
SELECT User, Host FROM mysql.user WHERE User = 'app_rw';)、SSL 是否强制(REQUIRE SSL)、密码是否过期
最容易被忽略的是 host 匹配逻辑和角色权限的可见性——SHOW GRANTS 不显示角色权限,'localhost' 不等于所有本地连接,这两点在排查“明明授权了却没权限”时几乎必踩。


















