MySQL 角色管理

MySQL 角色管理

版本说明 :角色(Role)是 MySQL 8.0.0 引入 的特性,MySQL 5.7 及更早版本不支持 角色。角色在内部实现上是一个没有登录权限的特殊用户(account_locked=Ypassword_expired=Y)。以下命令仅适用于 MySQL 8.0+。


1. 创建角色

sql 复制代码
-- 创建单个角色
CREATE ROLE 'app_read';

-- 批量创建多个角色
CREATE ROLE 'app_write', 'app_admin';

查看已创建的角色

角色在 mysql.user 表中体现为 account_locked='Y'password_expired='Y' 的记录:

sql 复制代码
SELECT User, Host FROM mysql.user
WHERE account_locked = 'Y' AND password_expired = 'Y';

返回结果:

复制代码
+-----------+------+
| User      | Host |
+-----------+------+
| app_admin | %    |
| app_read  | %    |
| app_write | %    |
+-----------+------+
3 rows in set (0.00 sec)

2. 给角色授权

给角色授权与给用户授权的语法完全一致。下面是一个最常见的例子:

sql 复制代码
-- 创建角色
CREATE ROLE 'app_read';

-- 授予 db_test 库的只读权限
GRANT SELECT ON db_test.* TO 'app_read';

查看角色拥有的权限

sql 复制代码
-- 查看角色拥有的权限
SHOW GRANTS FOR 'app_read';

返回结果:

复制代码
+-----------------------------------------------+
| Grants for app_read@%                         |
+-----------------------------------------------+
| GRANT USAGE ON *.* TO `app_read`@`%`          |
| GRANT SELECT ON `db_test`.* TO `app_read`@`%` |
+-----------------------------------------------+
2 rows in set (0.00 sec)

3. 给用户分配角色

将角色授予用户使用 GRANT ... TO 语法:

sql 复制代码
-- 先创建用户
CREATE USER 'zhangsan'@'%' IDENTIFIED BY 'ZsPass123!';

-- 将角色分配给用户
GRANT 'app_read' TO 'zhangsan'@'%';

查看用户被授予了哪些角色

sql 复制代码
SHOW GRANTS FOR 'zhangsan'@'%';

返回结果:

复制代码
+----------------------------------------+
| Grants for zhangsan@%                  |
+----------------------------------------+
| GRANT USAGE ON *.* TO `zhangsan`@`%`   |
| GRANT `app_read`@`%` TO `zhangsan`@`%` |
+----------------------------------------+

注意 :角色分配给用户后,默认并不会自动生效 (即角色内的权限不会立即对用户生效),还需要激活


4. 激活角色

4.1 为什么需要"分配"和"激活"两个步骤

步骤 类比 说明
分配角色GRANT ... TO 给你一把钥匙 只是声明你拥有这个角色,但权限尚未生效
激活角色SET ROLE 用钥匙开门 真正让角色中的权限在当前会话中生效

这样设计的好处:

  • 最小权限原则:用户可以拥有多个角色,但只激活当前任务需要的角色。比如一个 DBA 平时只用只读角色,只有在需要修改时才激活写入角色。
  • 灵活切换 :无需重新分配角色,只需 SET ROLE 即可临时切换权限组合。
  • 安全隔离:高权限角色默认不激活,降低误操作风险。

4.2 激活前后的对比

sql 复制代码
-- ========== 激活前 ==========
-- 查看当前激活的角色,登录刚才分配角色的用户zhangsan
SELECT CURRENT_ROLE();

返回结果:

复制代码
+----------------+
| CURRENT_ROLE() |
+----------------+
| NONE           |
+----------------+

此时 zhangsan 虽然被分配了 app_read 角色,但角色未激活,不具备 app_read 中的 SELECT 权限。

sql 复制代码
-- ========== 激活后 ==========
-- 激活指定角色
SET ROLE 'app_read';

-- 再次查看当前激活的角色
SELECT CURRENT_ROLE();

返回结果:

复制代码
+----------------+
| CURRENT_ROLE() |
+----------------+
| `app_read`@`%` |
+----------------+
1 row in set (0.00 sec)

此时 zhangsan 真正拥有了 app_read 角色中的 SELECT ON db_test.* 权限。

4.3 激活的几种方式

方式一:手动激活(当前会话有效,重新登录后失效)
sql 复制代码
-- 激活指定角色
SET ROLE 'app_read';

-- 激活所有被授予的角色
SET ROLE ALL;

-- 停用所有角色(恢复到无角色状态)
SET ROLE NONE;

-- 恢复默认角色
SET ROLE DEFAULT;
方式二:设置默认角色(每次登录自动激活)
sql 复制代码
-- 为 zhangsan 设置默认角色,登录时自动激活
SET DEFAULT ROLE 'app_read' TO 'zhangsan'@'%';

-- 激活所有被授予的角色
SET DEFAULT ROLE ALL TO 'zhangsan'@'%';

-- 不设置默认角色(登录后需手动 SET ROLE)
SET DEFAULT ROLE NONE TO 'zhangsan'@'%';

查看默认角色设置

sql 复制代码
-- 查看默认角色设置,查询需要权限,在root用户查询
SELECT * FROM mysql.default_roles;

返回结果:

复制代码
+------+----------+-------------------+-------------------+
| HOST | USER     | DEFAULT_ROLE_HOST | DEFAULT_ROLE_USER |
+------+----------+-------------------+-------------------+
| %    | zhangsan | %                 | app_read          |
+------+----------+-------------------+-------------------+
1 row in set (0.00 sec)
方式三:全局强制激活(对所有用户生效)
sql 复制代码
-- 查看当前策略
SHOW VARIABLES LIKE 'activate_all_roles_on_login';

返回结果:

复制代码
+-----------------------------+-------+
| Variable_name               | Value |
+-----------------------------+-------+
| activate_all_roles_on_login | OFF   |
+-----------------------------+-------+
1 row in set, 1 warning (0.00 sec)

全局开启:所有用户的所有角色登录时自动激活

sql 复制代码
SET GLOBAL activate_all_roles_on_login = ON;

持久化 :写入配置文件 my.cnf / my.ini

ini 复制代码
[mysqld]
activate_all_roles_on_login = ON

注意 :开启此选项后,无需再为每个用户单独执行 SET DEFAULT ROLE


5. 角色与用户的关系

5.1 角色本质上是用户

在 MySQL 内部,角色就是一个 account_locked='Y'password_expired='Y' 的特殊用户:

sql 复制代码
-- 可以看到角色和用户都在同一张表中
SELECT User, Host, account_locked, password_expired
FROM mysql.user
WHERE User IN ('app_read', 'zhangsan');

返回结果:

复制代码
+----------+------+----------------+------------------+
| User     | Host | account_locked | password_expired |
+----------+------+----------------+------------------+
| app_read | %    | Y              | Y                |
| zhangsan | %    | N              | N                |
+----------+------+----------------+------------------+
2 rows in set (0.00 sec)

因此角色可以嵌套继承------一个角色可以授予给另一个角色:

sql 复制代码
-- 创建基础角色
CREATE ROLE 'base_read';
GRANT SELECT ON db_test.* TO 'base_read';

-- 创建高级角色,继承基础角色
CREATE ROLE 'senior_dev';
GRANT 'base_read' TO 'senior_dev';                       -- 角色授予角色
GRANT INSERT, UPDATE, DELETE ON db_test.* TO 'senior_dev';

-- 将 senior_dev 授予用户,用户将同时拥有 base_read 和 senior_dev 的权限
GRANT 'senior_dev' TO 'zhangsan'@'%';

5.2 用户能否像角色一样授予给其他用户?

可以。原因在于 MySQL 的实现中,角色和用户 没有本质区别 ------都是 mysql.user 表中的一行记录,区别仅在于 account_locked 标志位。而 GRANT ... TO ... 操作的是 mysql.user 表里的授权关系, MySQL 并不会校验被授予的对象是"角色"还是"用户" 。所以将一个普通用户授予另一个用户在语法上完全合法:

sql 复制代码
GRANT 'zhangsan'@'%' TO 'dba_user'@'%';

6. 回收角色

6.1 撤销用户的角色

sql 复制代码
-- 先查看用户当前拥有的角色
SHOW GRANTS FOR 'zhangsan'@'%';

返回结果:

复制代码
+---------------------------------------------------------+
| Grants for zhangsan@%                                   |
+---------------------------------------------------------+
| GRANT USAGE ON *.* TO `zhangsan`@`%`                    |
| GRANT `app_read`@`%`,`senior_dev`@`%` TO `zhangsan`@`%` |
+---------------------------------------------------------+
2 rows in set (0.00 sec)

撤销用户的某个角色

sql 复制代码
REVOKE 'app_read' FROM 'zhangsan'@'%';

6.2 撤销角色的权限

查看角色权限

sql 复制代码
SHOW GRANTS FOR 'app_write';

撤销角色中的某条权限

sql 复制代码
REVOKE DELETE ON db_test.* FROM 'app_write';

6.3 删除角色

删除角色会同时从所有拥有该角色的用户中移除

sql 复制代码
-- 删除单个角色
DROP ROLE 'app_read';

-- 批量删除
DROP ROLE 'app_write', 'app_admin';

6.4 管理角色需要的权限

条件 说明
CREATE USER 创建和删除角色需要此权限(角色本质是用户)
ROLE_ADMIN 执行 GRANT roleREVOKE role 需要此权限
WITH ADMIN OPTION 在授予角色时附加此选项,允许被授予者继续将该角色传递给其他用户
sql 复制代码
-- 示例:授予角色管理员所需的权限
GRANT CREATE USER, ROLE_ADMIN ON *.* TO 'role_admin_user'@'%'
WITH GRANT OPTION;

7. 完整示例流程

sql 复制代码
-- ============================================
-- 场景:为项目设置角色体系
-- ============================================

-- Step 1: 创建角色
CREATE ROLE 'role_read', 'role_write', 'role_dba';

-- Step 2: 给角色授权
GRANT SELECT ON db_app.* TO 'role_read';
GRANT SELECT, INSERT, UPDATE, DELETE ON db_app.* TO 'role_write';
GRANT ALL PRIVILEGES ON db_app.* TO 'role_dba';

-- Step 3: 创建用户
CREATE USER 'zhangsan'@'%' IDENTIFIED BY 'ZsPass123!';
CREATE USER 'lisi'@'%'     IDENTIFIED BY 'LsPass123!';
CREATE USER 'wangwu'@'%'   IDENTIFIED BY 'WwPass123!';

-- Step 4: 分配角色给用户
GRANT 'role_read'  TO 'zhangsan'@'%';
GRANT 'role_write' TO 'lisi'@'%';
GRANT 'role_dba'   TO 'wangwu'@'%';

-- Step 5: 设置默认角色(登录即自动激活)
SET DEFAULT ROLE 'role_read'  TO 'zhangsan'@'%';
SET DEFAULT ROLE 'role_write' TO 'lisi'@'%';
SET DEFAULT ROLE 'role_dba'   TO 'wangwu'@'%';

-- Step 6: 验证
SHOW GRANTS FOR 'zhangsan'@'%' USING 'role_read';
SHOW GRANTS FOR 'lisi'@'%'     USING 'role_write';
SHOW GRANTS FOR 'wangwu'@'%'   USING 'role_dba';

  1. 部分内容由AI生成
  2. 如有不对,欢迎指正!!!
相关推荐
每天都要进步哦6 分钟前
SQL单行函数详解:字符、数字、日期、转换与通用函数全解析
数据库·mysql
不剪发的Tony老师10 分钟前
VeloxDB:一款免费开源的轻量级数据库管理工具
数据库·sql
dotnet9015 分钟前
批量生成所有表的修改脚本
数据库·sql·oracle
@Mike@23 分钟前
06-数据库学习笔记(存储模型与数据压缩)
数据库·笔记·学习
南凉北往1 小时前
PandasAI连接LLM对MySQL数据库进行数据分析
数据库·mysql·数据分析
回眸不遇1 小时前
详谈 QT 布局 QLayout::SizeConstraint 和 QSizePolicy 对 QWidget 尺寸的影响
数据库·qt·系统架构
2601_965798471 小时前
MTDb Movie & TV Database Script Setup, Caching, and SEO Guide
linux·服务器·数据库·php
zdl6861 小时前
EasyMarkets:“机器人商业化仍待验证”
数据库·机器人
Freak嵌入式2 小时前
版本混乱 / 依赖缺失?uPyPi:MicroPython 版 PyPI,彻底解决库管理混乱
linux·服务器·数据库·单片机·嵌入式硬件·性能优化·依赖倒置原则
Elastic 中国社区官方博客2 小时前
Elastic 和 OpenAI 合作,将前沿智能引入非结构化企业数据
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai