MySQL 角色管理
版本说明 :角色(Role)是 MySQL 8.0.0 引入 的特性,MySQL 5.7 及更早版本不支持 角色。角色在内部实现上是一个没有登录权限的特殊用户(
account_locked=Y且password_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 role 和 REVOKE 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';
- 部分内容由AI生成
- 如有不对,欢迎指正!!!