SET DEFAULT ROLE 必须在角色已显式授予用户后执行,否则报 ERROR 3530;且仅对后续新连接生效,当前会话不刷新,也不受 activate_all_roles_on_login=ON 干扰。

直接说结论:SET DEFAULT ROLE 必须在角色已显式授予用户之后执行,否则一定报 ERROR 3530;且该设置只对**后续新连接**生效,当前会话不刷新,也不受 activate_all_roles_on_login=ON 干扰。
为什么 SET DEFAULT ROLE 总是报 ERROR 3530?
根本不是权限或语法问题,而是 mysql.role_edges 表里压根没这条记录。MySQL 检查默认角色时,会严格匹配 to_user 和 to_host 字段——哪怕你 GRANT 'r_ro' TO 'app'@'%' 成功了,但用户实际登录用的是 'app'@'localhost',那就查不到。
- 先确认角色是否真授给了目标用户:
SELECT * FROM mysql.role_edges WHERE to_user = 'app' AND to_host = '%';,无结果就得重做GRANT - host 必须完全一致:用户是
'app'@'127.0.0.1',就不能用'app'@'%'去设默认角色 - 角色名大小写敏感:若
lower_case_table_names=0,'R_RO'和'r_ro'是两个角色,GRANT和SET DEFAULT ROLE必须用同一拼写 -
FLUSH PRIVILEGES在 8.0+ 通常不需要,别靠它“碰运气”
SET DEFAULT ROLE 生效的前提条件
它不是“设完就立刻起作用”的命令,而是一条持久化配置,但依赖多个运行时状态:
- 用户账户不能被锁定:
SELECT account_locked FROM mysql.user WHERE user = 'app' AND host = '%';返回必须是N - 密码不能过期:
SELECT password_expired FROM mysql.user WHERE user = 'app' AND host = '%';同样得是N -
activate_all_roles_on_login必须为OFF(即SELECT @@activate_all_roles_on_login;返回0),否则所有已授角色全激活,DEFAULT ROLE彻底失效 - 如果配置了
mandatory_roles,它会静默覆盖DEFAULT ROLE,此时设了也白设
怎么验证默认角色真生效了?
别在当前连接里查 CURRENT_ROLE(),那只是旧会话状态。必须新开一个连接,再执行:
-
SELECT CURRENT_ROLE();—— 应返回你设的角色名,如'r_ro',不是NULL或空字符串 -
SHOW GRANTS FOR 'app'@'%';只显示“被授予了哪些角色”,不反映激活状态;要确认权限可用,得实操:SELECT 1 FROM some_protected_table; - 设多个默认角色:
SET DEFAULT ROLE 'r1', 'r2' TO 'app'@'%';,权限叠加,但只要其中一个被REVOKE,它就自动从默认列表剔除 - 想清空默认角色:
SET DEFAULT ROLE NONE TO 'app'@'%';
最容易被忽略的一点:角色必须先 GRANT 给用户,再 SET DEFAULT ROLE;顺序反了、host 错了、大小写混了,都会让整套机制卡在第一步。别指望 MySQL 自动推导或容错。


















