角色管理是可控、可复用、可回收的权限正解:需显式指定NOT IDENTIFIED或IDENTIFIED BY;多租户下角色不跨PDB继承;禁授DBA等高危角色;权限变更需重连生效。

直接给开发团队每人单独授一堆 SELECT、INSERT、UPDATE 权限,不出三天就会失控——权限混乱、删库误操作、审计查不到责任人。用角色(ROLE)统一管理,才是可控、可复用、可回收的正解。
创建角色时必须显式指定 NOT IDENTIFIED 或 PASSWORD
Oracle 角色默认是 NOT IDENTIFIED,也就是无口令角色,只能由 DBA 或具有 GRANT ANY ROLE 权限的用户授予/回收;如果想让应用或中间件自动激活(比如连接后自动生效),就得设密码:
CREATE ROLE dev_read_role NOT IDENTIFIED; CREATE ROLE dev_dml_role IDENTIFIED BY "dev123";
常见错误是漏写 IDENTIFIED BY 却指望应用连上就自动有权限——结果 SELECT 报 ORA-01031: insufficient privileges,因为角色没被激活。这时得手动执行 SET ROLE dev_dml_role IDENTIFIED BY "dev123";,但大多数 ORM 或连接池不支持这条命令。
角色不能跨 PDB 直接继承,多租户环境下要分别授权
Oracle 12c+ 启用多租户(CDB/PDB)后,角色只在创建它的容器内有效。你在 CDB$ROOT 创建的 dev_read_role,对所有 PDB 都不可见。
- 必须在每个目标 PDB 内连入后重新创建角色(推荐)
- 或使用公共角色(
CREATE ROLE dev_read_role CONTAINER=ALL),但仅限于 CDB 级权限(如SELECT_CATALOG_ROLE),不能包含对 PDB 内表的SELECT - 更稳妥的做法:在 PDB 中创建角色,并用脚本批量在各 PDB 执行授权
否则开发连的是 PDB A,却以为自己有 PDB B 的权限,查不到数据还怪 SQL 写错。
避免把 DBA、EXP_FULL_DATABASE 这类高危角色直接授给开发
这些预定义角色自带大量系统级权限,比如 DBA 包含 DROP ANY TABLE、ALTER SYSTEM,一个误操作就能让整个库不可用。
实操建议:
- 只授予最小必要权限:比如开发只需查
SCOTT.EMP和SCOTT.DEPT,就GRANT SELECT ON SCOTT.EMP TO dev_read_role;,别碰GRANT SELECT ANY TABLE - 用视图封装敏感字段:对含身份证、手机号的表,建只暴露脱敏字段的视图,再把视图查询权授给角色
- 禁用直接登录
SYS/SYSTEM:开发应统一用业务账号(如APP_USER),该账号只被授予自定义角色
角色权限变更后,已连接会话不会自动刷新
你刚执行了 GRANT INSERT ON ORDERS TO dev_dml_role;,但开发同学的 SQL*Plus 或 IDEA 数据库工具里还是报 ORA-01031。
原因:Oracle 不会主动推送权限变更。解决办法只有两个:
- 让开发断开重连(最简单)
- 在服务端执行
ALTER SYSTEM FLUSH SHARED_POOL;(不推荐,影响全库性能)
所以批量改权限前,最好提前通知团队“将在 XX 时间点重启连接”,否则排查起来容易误判为授权没生效。
真正难的不是建角色,而是厘清「谁在什么环境、访问哪些对象、做哪些操作」——这张权限映射表一旦模糊,后续加人、换库、切环境全是坑。











