MySQL 8.0中GRANT不再支持创建用户,必须先CREATE USER再GRANT授权;角色需显式创建、授权、绑定并SET DEFAULT ROLE激活,权限为并集且须遵循最小权限原则。

MySQL 8.0中GRANT报错:老写法直接失效
不是语法错了,是MySQL 8.0强制拆分了「创建用户」和「授予权限」两个动作。像GRANT ALL ON *.* TO 'u'@'%' IDENTIFIED BY 'p'这种5.7惯用写法,在8.0里会明确报错:ERROR 1064 (42000): You have an error in your SQL syntax。
根本原因是认证逻辑和权限模型解耦了——用户身份(含密码、插件、过期策略)归CREATE USER管,权限归属GRANT管。强行合并会导致语义模糊,尤其在caching_sha2_password默认认证插件下更易出问题。
- 必须先执行
CREATE USER 'u'@'%' IDENTIFIED BY 'p',再执行GRANT SELECT ON db.* TO 'u'@'%' - 如果只想要权限不设密码(比如OS认证或代理用户),
CREATE USER可以不带IDENTIFIED BY,但GRANT不能补这个动作 - 旧脚本批量迁移时,建议用正则替换:
GRANT (.+) TO '(.+)'@'(.+)' IDENTIFIED BY '(.+)'→ 拆成两行
CREATE ROLE不是可选项,而是权限复用的刚需路径
当有3个以上开发人员都需要SELECT, INSERT on orders库,或DBA要轮换多个只读账号时,逐个GRANT就是技术债。角色把权限打包成可复用单元,改一次'dev_readonly',所有绑定该角色的用户立即生效。
注意角色名必须带主机名(哪怕只是'dev_readonly'@'%'),否则后续GRANT 'dev_readonly' TO 'u'@'h'会失败——MySQL 8.0把角色也当作带作用域的账户实体管理。
- 创建:
CREATE ROLE 'dev_readonly'@'%' - 授权:
GRANT SELECT ON sales.* TO 'dev_readonly'@'%' - 绑定用户:
GRANT 'dev_readonly'@'%' TO 'alice'@'10.%.%.%' - 激活(会话级):
SET ROLE 'dev_readonly'@'%',否则权限不生效
SET DEFAULT ROLE决定登录后权限是否自动就位
用户被授予角色后,默认不会自动激活——这是安全设计,避免误操作扩大权限范围。如果你发现SHOW GRANTS FOR 'u'@'h'能看到角色,但SELECT仍报Access denied,大概率是没设默认角色或没手动SET ROLE。
SET DEFAULT ROLE影响的是新连接的初始状态。它支持通配符和显式列表,但不能混用;且必须在用户已拥有该角色的前提下执行。
- 让所有已授角色都默认激活:
SET DEFAULT ROLE ALL TO 'u'@'h' - 只激活指定角色:
SET DEFAULT ROLE 'dba'@'localhost' TO 'admin'@'localhost' - 取消默认角色:
SET DEFAULT ROLE NONE TO 'u'@'h' - 验证当前默认设置:
SELECT default_role FROM mysql.role_edges WHERE to_host = 'h' AND to_user = 'u'
角色权限叠加与CURRENT_ROLE()调试陷阱
一个用户可被授予多个角色,权限是并集,但冲突时不会报错——比如角色A禁止DROP,角色B允许DROP,最终结果是允许。这种隐式叠加容易埋下越权隐患,尤其在交接维护或临时提权后忘记回收角色时。
CURRENT_ROLE()返回当前会话激活的角色,但它只显示字符串,不展开权限细节。真要确认某条SQL能否执行,别只查CURRENT_ROLE(),得用SHOW GRANTS配合实际连接测试。
- 查当前激活角色:
SELECT CURRENT_ROLE() - 查用户所有已授角色(含未激活):
SHOW GRANTS FOR 'u'@'h' - 查角色本身包含哪些权限:
SHOW GRANTS FOR 'role_name'@'%' - 最稳妥验证方式:用该用户连上后,直接执行
SELECT USER(), CURRENT_ROLE(), @@session.role三者比对
角色不是银弹。它解决的是“批量授权”和“权限模板化”问题,但无法替代最小权限原则——比如developer角色不该包含CREATE USER或SHUTDOWN这类高危权限,这些必须单独控制。真正容易被忽略的,是角色生命周期管理:没人定期清理长期不用的角色,也没人审计role_edges表里残留的绑定关系。


















