mysql 8.0.1+才支持角色功能;低于该版本执行create role必报error 1064,非语法错误而是功能不可用;必须完成创建→授权→绑定→激活四步,缺一权限不生效。

MySQL 8.0 的角色权限系统能显著提升运维效率,但前提是版本 ≥ 8.0.1、操作步骤不跳步、权限粒度不越界。低于这个版本或漏掉 SET DEFAULT ROLE,角色就等于没生效。
确认 MySQL 版本是否支持角色
执行 SELECT VERSION(); 是所有操作前的强制动作。输出为 5.7.42、8.0.0 或更低,CREATE ROLE 必报 ERROR 1064 (42000)——这不是语法错,是功能不可用。MySQL 8.0.1 才真正引入角色,8.0.0 是无效占位符。生产环境升级前,必须在测试库验证 CREATE ROLE 'test'@'localhost' 能否成功执行。
角色创建与授权必须分两步:先赋权、再绑人
常见错误是建完角色、授完权,就以为用户自动拥有了权限。实际权限链是:角色定义 → 授予用户 → 激活。缺任何一环,SHOW GRANTS FOR 'user'@'host' 都只显示 USAGE,查表直接报 Access denied。
- 给角色授权:
GRANT SELECT, INSERT ON app_db.* TO 'app_writer' - 把角色分给用户:
GRANT 'app_writer' TO 'dev_user'@'localhost' - 设为默认(否则登录后权限为空):
SET DEFAULT ROLE 'app_writer' TO 'dev_user'@'localhost'
批量分配可一次写多个用户:GRANT 'app_writer' TO 'u1'@'%', 'u2'@'%', 'u3'@'%',比在 5.7 里重复执行 10 次 GRANT 更可靠。
回收权限时 FROM 后的对象类型决定影响范围
REVOKE 语句的 FROM 后面跟的是角色名还是用户名,效果天差地别:
- 从角色撤权:
REVOKE INSERT ON app_db.* FROM 'app_writer'→ 所有被授予该角色的用户立刻失去INSERT权限 - 从用户撤角色:
REVOKE 'app_writer' FROM 'dev_user'@'localhost'→ 仅该用户失效,不影响角色定义和其他人 - 误写成
REVOKE INSERT ON app_db.* FROM 'dev_user'@'localhost'→ 只清除该用户的直授权限,对角色无感,容易误判“已回收”
生产环境执行前务必核对 FROM 后是 'role_name' 还是 'user'@'host',输错一个字符,要么收不干净,要么收过头。
SHOW GRANTS 看不到角色继承的权限,审计时极易误判
SHOW GRANTS FOR 'user'@'host' 只返回直接授予该用户的权限,完全不体现角色带来的权限。你看到的是“纸面权限”,不是“真实权限”。DBA 审计时如果只扫这个输出,可能放行一个其实拥有 ALL PRIVILEGES 的账号。
正确做法是组合使用:
- 查角色本身有哪些权限:
SHOW GRANTS FOR 'app_reader' - 查用户被授予了哪些角色:
SELECT * FROM mysql.role_edges WHERE TO_HOST = 'localhost' AND TO_USER = 'dev_user'; - 查当前会话激活了什么角色:
SELECT CURRENT_ROLE();
角色权限是动态叠加的,且不写入 mysql.user 表,只存于 mysql.role_edges 和 mysql.db/mysql.tables_priv 等权限表中——这点和传统用户权限存储方式不同,排查时容易忽略底层数据源。











