mysql8角色权限怎么使用_mysql新特性说明

来源:这里教程网 时间:2026-02-28 20:47:27 作者:

MySQL 8.0 的角色(

ROLE
)不是“锦上添花”,而是解决权限管理混乱的刚需工具——只要你有 3 个以上需要同类权限的用户,或频繁调整权限,就该用
ROLE
,否则迟早会
GRANT
错、
REVOKE
漏、审计时抓瞎。

创建和授权角色:别跳过主机名,否则登录就失效

角色名其实是个“伪用户”,格式是

'role_name'@'host'
,省略
@'host'
默认为
@'%'
。但问题来了:如果你创建的是
CREATE ROLE 'dev';
(即
@'%'
),而用户是
'alice'@'localhost'
,后续
GRANT 'dev' TO 'alice'@'localhost';
虽然语法通过,但激活时可能因上下文 host 匹配逻辑出问题(尤其在 strict SQL mode 下)。

推荐显式声明 host,保持一致性:比如开发角色统一用
@'%' 
,DBA 角色用
@'localhost'
给角色授予权限,和给用户一样,但对象是角色名:
GRANT SELECT, INSERT ON app_db.* TO 'dev_role'@'%';
注意:角色本身不能登录,所以不需要
IDENTIFIED BY
,也不支持密码策略

分配角色给用户后,为什么还是没权限?

这是最常踩的坑:角色授给了用户,

SHOW GRANTS FOR 'user'@'host';
也显示成功,但一执行
SELECT
就报
ERROR 1045 (28000): Access denied
——根本原因是角色默认不激活。

必须显式激活才能生效,方式有两种:
– 当前会话临时激活:
SET ROLE 'dev_role'@'%';

– 设为登录默认激活(推荐生产环境):
SET DEFAULT ROLE 'dev_role'@'%' TO 'alice'@'localhost';
如果想让所有已分配角色自动激活,启用系统变量:
SET PERSIST activate_all_roles_on_login = ON;
(需
SYSTEM_VARIABLES_ADMIN
权限)
检查当前生效角色:
SELECT CURRENT_ROLE();
返回
NULL
就说明没激活

强制角色(
mandatory_roles
):方便但不可逆,慎用

设为强制的角色,所有用户(包括未来新建的)都会隐式拥有它,连

REVOKE
都删不掉权限——这不是“快捷方式”,而是“全局锁”。

配置方式(需
ROLE_ADMIN
SUPER
权限):
SET PERSIST mandatory_roles = "'dba_role'@'localhost','read_only'@'%';"
一旦写入,该角色的权限无法被单个用户撤销,也不能
DROP ROLE
,除非先清空
mandatory_roles
典型适用场景只有两个:全库只读兜底(如灾备从库)、审计日志角色(确保所有连接都带 trace 权限) 误配后恢复麻烦:必须用
SET PERSIST mandatory_roles = '';
再重启服务(或动态重载,取决于版本)

查看与调试:别只信
SHOW GRANTS

SHOW GRANTS FOR 'user'@'host'
只告诉你“这个用户被授予了哪些角色”,但不告诉你“这些角色具体有哪些权限”。你看到
GRANT 'dev_role'@'%' TO 'alice'@'localhost'
,却不知道
dev_role
到底有没有
DELETE
权限。

查角色本身权限:
SHOW GRANTS FOR 'dev_role'@'%';
查用户实际生效权限(含角色继承):
SHOW GRANTS FOR 'alice'@'localhost' USING 'dev_role'@'%';
查当前会话权限快照(含动态激活状态):
SELECT * FROM INFORMATION_SCHEMA.ROLE_TABLE_GRANTS WHERE ROLE_NAME = 'dev_role';

真正难的不是语法,而是权限叠加逻辑:多个角色 + 强制角色 + 显式用户权限,最终生效的是并集,但拒绝权限(

REVOKE
)只作用于直接授予项,不会穿透角色——这点在排查越权或失权时最容易误判。

相关推荐