MySQL 8.0中角色创建并授权后必须显式绑定并激活:先GRANT 'reader'@'%' TO 'alice'@'localhost'建立关联,再SET DEFAULT ROLE 'reader'@'%' TO 'alice'@'localhost'激活,且host必须完全匹配,否则CURRENT_ROLE()返回NULL。

角色创建了但没绑定到用户
CREATE ROLE 'reader'; 和 GRANT SELECT ON app.* TO 'reader'@'%'; 只是建了个空容器,权限不会自动落到任何用户身上。MySQL 不做隐式继承,必须显式执行 GRANT 'reader'@'%' TO 'alice'@'localhost' 才建立关联。
常见错误:
- 授角色时主机名不匹配:给
'alice'@'127.0.0.1'授了'reader'@'%',但登录用的是mysql -u alice -h localhost,实际匹配到的是'alice'@'localhost',而这条记录没被授角色 - 省略角色主机名:
GRANT 'reader' TO 'alice'@'localhost'等价于'reader'@'localhost',若角色创建时是'reader'@'%',则匹配失败 - 查绑定关系是否真实存在:
SELECT * FROM mysql.role_edges WHERE to_user = 'alice' AND to_host = 'localhost',结果为空就说明没绑上
绑定后没激活,默认角色未设置
执行 GRANT 'reader'@'%' TO 'alice'@'localhost' 后,CURRENT_ROLE() 仍返回 NULL —— 这不是 bug,是 MySQL 8.0 的默认行为:绑定 ≠ 激活。
必须补一步持久化设置:
-
SET DEFAULT ROLE 'reader'@'%' TO 'alice'@'localhost'(注意 host 必须和GRANT语句中完全一致) - 若报错
ERROR 3530 (HY000): Cannot set default role for user,先确认mysql.role_edges中有对应记录,再检查 host 是否精确匹配 - 设置后需退出重连才生效;已有连接不会自动更新角色状态
SHOW GRANTS 看不到角色权限,误判失败
SHOW GRANTS FOR 'alice'@'localhost' 默认只显示直接授予用户的权限,角色所含权限不会展开。这不是配置失败,是设计如此。
要验证角色权限是否真可用:
- 查角色本身:
SHOW GRANTS FOR 'reader'@'%' - 查用户通过该角色获得的权限:
SHOW GRANTS FOR 'alice'@'localhost' USING 'reader'(USING后必须是已绑定且 host 匹配的角色名) - 登录后实测:
SELECT CURRENT_ROLE();应返回'reader',再USE app; SELECT * FROM users;看是否报错
全局开关未启用或认证插件干扰
MySQL 8.0 默认关闭自动角色激活。即使设了默认角色,若 activate_all_roles_on_login 是 OFF,某些客户端(尤其是复用连接池的)可能在重连后仍不触发激活逻辑。
临时验证可运行:SET GLOBAL activate_all_roles_on_login = ON;,但生产环境必须写入配置文件:
[mysqld] activate_all_roles_on_login=ON
另外,如果用户 plugin 是 caching_sha2_password 而客户端不支持(如旧版 Navicat、PHP 7.4 mysqlnd),会出现“能连上但权限查不到”的假象。确认方式:SELECT User, Host, plugin FROM mysql.user WHERE User = 'alice';。不兼容时需改认证方式:ALTER USER 'alice'@'localhost' IDENTIFIED WITH mysql_native_password BY 'xxx';


















