角色就是「一组权限起了个名字」。
价值不在技术,在运维:20 个人要同一个权限组合,就授 1 次角色,不是 20 次。
三个预定义角色:CONNECT(能连)、RESOURCE(能开发)、DBA(几乎全能)。
DBA 不该给业务账号——它包含 SELECT ANY TABLE 这类权限。
12.3 讲「一个一个授权」。这一篇讲「打包授权」。 角色是权限管理的分水岭: 没有角色的库,权限表会变成一团乱麻;有角色的库,一眼能看出「谁能干什么」。 这一篇也会说角色的代价: 「谁到底有什么」变难查了,因为要顺着角色链算。 所以角色层级别超过两层。
一、角色是什么:权限的容器
CREATE ROLE r_read;
GRANT SELECT ON hr.emp TO r_read;
GRANT r_read TO scott;
三步:建角色、往角色里放权限、把角色授给人。
角色可以放系统权限,也可以放对象权限,还可以放另一个角色。
它就是个「权限的容器」,本身不是权限。
这一点带来一个副作用:
GRANT SELECT ON hr.emp TO r_read 里 r_read 是角色,但语法和「授给用户」一模一样——
所以看授权语句时,得先确认 TO 后面那个名字是用户还是角色。
查一下就知道:SELECT * FROM DBA_ROLES;。
二、为什么用角色:算一笔账
5 个人、3 个权限: 不用角色是 15 条授权记录;用角色是 3 条(角色里的权限)+ 5 条(成员关系)= 8 条。 但省记录数不是重点,重点是「改的时候」: 要加一个权限,不用角色得改 5 处,用角色只改 1 处。 要查「谁有这张表的权限」,不用角色要翻 15 条记录,用角色只看 1 条。 第三件事最值钱:员工离职或转岗。 用角色的话,收一个角色就完事;不用角色的话,得把他名下的权限一条条列出来再撤—— 而「列全」这件事本身就很难。
三、三个预定义角色
| 角色 | 包含什么 | 适合给谁 |
|---|---|---|
CONNECT |
11g 之后只剩 CREATE SESSION |
所有要连库的账号 |
RESOURCE |
建表、建序列、建过程、建触发器 | 开发账号 |
DBA |
几乎所有系统权限(含 ANY 系列) |
只给 DBA |
CONNECT 这个名字有历史包袱。
老版本(Oracle 7/8i)里它包含一堆建表建视图的权限,11g 之后被削得只剩 CREATE SESSION。
所以「照老书写 GRANT CONNECT 就能建表」是错的——
现在建表得靠 RESOURCE 或者单独授 CREATE TABLE。
DBA 角色要单独说一句:
它包含 SELECT ANY TABLE、DROP ANY TABLE、GRANT ANY PRIVILEGE。
一个账号有了 DBA,等于能删全库、能给任何人授权。
业务账号一律不给,开发账号按需给,且要定期复核。
四、启用与禁用:SET ROLE
SET ROLE ALL;(默认,全开)SET ROLE r_read;(只开这一个,
其余全关)SET ROLE NONE;(全关)
这个功能是给「一个人有多个身份」用的。
平时只有只读角色,要做维护时 SET ROLE 切到维护角色。
好处是「不切角色就删不了表」,误操作概率降低。
坏处也很明显:
应用不知道自己该在哪个角色下,连接池里的会话角色状态还可能互相干扰。
所以业务系统里很少用,基本是 DBA 自己在 SQL*Plus 里用。
还有一条:默认角色(DEFAULT ROLE)在登录时自动启用。
ALTER USER u DEFAULT ROLE r_read;
如果不设,所有角色都是默认的。
要做「最小权限」,就得显式设默认角色,把敏感角色排除在外。
五、动手 Demo:算一笔账:逐条授权 15 条,角色 8 条
这一篇的 Demo 是算账,不是命令。
因为角色的价值就体现在「记录数」和「改动处数」上,这两件事都能数出来。
沙箱里没有 CREATE ROLE,但「权限集合」和「成员关系」就是个两层字典,数一遍就能说明问题。
# 角色 vs 逐条授权:记录数差多少
users = ["u1", "u2", "u3", "u4", "u5"]
privs = ["CREATE SESSION", "SELECT ON hr.emp", "SELECT ON hr.dept"]
direct = 0
for u in users:
for p in privs:
direct += 1
print("不用角色:%d 条授权记录" % direct)
role_grants = len(privs)
members = len(users)
print("用角色:%d 条(角色里的权限) + %d 条(成员关系) = %d 条"
% (role_grants, members, role_grants + members))
print("省的是 %d 条,但更要紧的是「加一个权限」:" % (direct - role_grants - members))
print(" 不用角色要改 %d 处,用角色只改 1 处。" % len(users))
实跑输出:
--------------------------------------------------------------------
第五十六课:角色管理——权限的打包
--------------------------------------------------------------------
**角色(role)就是「一组权限起了个名字」。**
**它的价值不在技术,在运维:20 个人要同一个权限组合,就授 1 次角色,不是 20 次。**
一、不用角色:五个人 × 三个权限 = 十五次授权
--------------------------------------------------------------------
**五次授权操作,每次三个权限,一共 15 条授权记录。**
**问题不在「麻烦」,在「改的时候」:**
**哪天要加一个权限,得改 5 次;哪天要查「谁有这张表的权限」,得翻 15 条记录。**
二、用角色:三条授权 + 五次成员关系
--------------------------------------------------------------------
角色 角色里的权限
----------------------------------------------------------
r_read CREATE SESSION、SELECT ON hr.emp、SELECT ON hr.dept
已选择 1 行
用户 拥有角色
-------------
u1 r_read
u2 r_read
u3 r_read
u4 r_read
u5 r_read
已选择 5 行
**三条授权(给角色)加五次成员关系,一共八条记录。**
**以后加权限只改角色一处,五个用户自动生效。**
**角色还能套角色**——
**`GRANT r_read TO r_write;` 就是「读角色是写角色的子集」。**
**这一层嵌套能建出很清晰的权限层次,但也让「谁到底有什么」更难查。**
**两层的角色设计是常见做法,三层以上就该重新想了。**
三、三个预定义角色
--------------------------------------------------------------------
角色 能干什么 能不能给人
-------------------------------------------------------------------------
CONNECT 建会话、建视图等最基本的权限 能(11g 之后只剩 CREATE SESSION)
RESOURCE 建表、建序列、建过程等开发权限 能
DBA 几乎所有系统权限 能(极危险)
已选择 3 行
**`CONNECT` 和 `RESOURCE` 是「开发账号的标配」**,
**基本上一句 `GRANT CONNECT, RESOURCE TO 账号;` 就能开工。**
**但注意 11g 之后 `CONNECT` 被削得只剩 `CREATE SESSION`**——
**老书上写「`CONNECT` 能建表」已经不对了。**
**`DBA` 角色不建议给业务账号。** **它包含 `SELECT ANY TABLE`、`DROP ANY TABLE` 这类权限**,
**一个账号有了它,等于能删全库。**
四、角色的启用与禁用
--------------------------------------------------------------------
**`SET ROLE r_read;` 只启用这一个角色,其余全部关掉。**
**`SET ROLE ALL;` 全开(默认)。`SET ROLE NONE;` 全关。**
**这个功能是给「同一个人有多个身份」用的:**
**平时只有只读角色,要做维护时 `SET ROLE` 切到维护角色。** **好处是「误操作的概率降低」**——
**因为你不切角色就删不了表。** **坏处是「应用不知道自己该在哪个角色下」**,
**所以业务系统里很少用,多是 DBA 自己用。**
第一段:5 个人 × 3 个权限 = 15 条记录。 这是不用角色的代价。 第二段:用角色是 3 + 5 = 8 条。 省了 7 条,接近一半。 但真正的差距在第三段:加一个权限时,不用角色要改 5 处,用角色只改 1 处。 人越多、权限越复杂,这个差距越大——50 个人、10 个权限,就是 500 条对 60 条。 还有一个没体现在数字里的收益: 「查谁有这张表的权限」从「翻 15 条记录」变成「看 1 条角色定义」。 这在审计和事故排查时省的时间,比一开始省的操作多得多。
30 秒实验
- 把用户数从 5 改成 50,重跑。不用角色是 150 条,用角色是 13 条。
- 把权限数从 3 改成 10,重跑。 不用角色 50 条(5 人),用角色 15 条。注意角色那一边的增长是「权限数 + 人数」, 逐条授权是「权限数 × 人数」。
- 想想:如果两个人要的权限组合只是「差一个权限」,该建两个角色还是一个? 答案通常是两个,或者用一个角色加一个单独授权—— 角色嵌套能省事,但会让「谁有什么」更难查。
常见误区
- 「
CONNECT就能建表」。 11g 之后CONNECT只剩CREATE SESSION。 建表要靠RESOURCE或单独授CREATE TABLE。 - 「
DBA角色给开发方便调试」。 它包含ANY系列权限, 等于能删全库、能给任何人授权。 不该给业务或开发账号。 - 「角色可以无限嵌套」。 技术上可以,但层数越多,「谁到底有什么」越难算。 两层是常见做法,三层以上要重新设计。
- 「授了角色就等于授了权限」。 要看角色是不是「默认角色」、
以及用户有没有
SET ROLE NONE。 角色没启用的话,权限不生效。
自测三问(点开对答案)
1. 角色是什么? —— **一组权限的容器,本身不是权限。** **可以放系统权限、对象权限,也可以放另一个角色。** 2. 用角色省的是什么? —— **主要是「改动处数」和「查询难度」**,记录数只是顺带。 **加一个权限改 1 处 vs 改 N 处,这才是关键。** 3. `CONNECT` 角色在 11g 之后包含什么? —— **只剩 `CREATE SESSION`。** 建表要靠 `RESOURCE` 或单独授。 4. `SET ROLE NONE` 有什么用? —— **把所有角色关掉,回到「只有直接授的权限」状态。** **用于「临时确认某个权限是不是角色带来的」。**下一篇讲 PROFILE:管住密码策略和资源使用。
两个高频坑:PASSWORD_REUSE_MAX 要两个都设才生效;
资源限制默认不生效(RESOURCE_LIMIT 是 FALSE)。
- ☐ (本篇完,下一篇 12.5 资源配额 PROFILE)
相关笔记
- 用户权限管理
- 资源配额 PROFILE
- 创建与管理用户
-
- 🐬 MySQL必知必会/00-索引
- 🏺 Oracle从入门到精通 · 索引