必须先显式授予角色且用户host、大小写完全匹配,再执行SET DEFAULT ROLE,否则报ERROR 3530;该设置仅对新连接生效,依赖账户未锁定、密码未过期、activate_all_roles_on_login=OFF等前提。

必须先显式授予角色,再执行 SET DEFAULT ROLE,否则一定报 ERROR 3530;该设置只对后续新连接生效,当前会话不会刷新。
为什么 SET DEFAULT ROLE 总是报 ERROR 3530
不是权限或语法问题,而是 mysql.role_edges 表里根本没对应记录。MySQL 检查时严格匹配 to_user 和 to_host 字段:
- 用户用
'app'@'localhost'登录,但角色只授给了'app'@'%'→ 查不到,报错 - 执行
GRANT 'r_ro' TO 'app'@'%'成功,不代表'app'@'localhost'就能设默认角色 - 角色名大小写敏感:若
lower_case_table_names=0,'R_RO'和'r_ro'是两个角色,GRANT和SET DEFAULT ROLE必须拼写完全一致
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 给用户,且 host 完全一致、大小写一致、账户未锁定、密码未过期、activate_all_roles_on_login=OFF——顺序反了、host 错了、大小写混了,都会让整套机制卡在第一步。


















