Common User权限必须在每个PDB中单独授予;创建后需在目标PDB执行GRANT CREATE SESSION、CREATE TABLE及ALTER USER QUOTA UNLIMITED ON users,否则报ORA-01031或ORA-01950。

Common User默认权限只在CDB$ROOT生效
你用 CREATE USER c##app IDENTIFIED BY pwd CONTAINER=ALL 创建的用户,名字虽跨PDB存在,但权限不会自动同步。刚建完时,c##app 在任意 PDB 中执行 CREATE TABLE 都会报 ORA-01031: insufficient privileges——不是语法错,是压根没权限。
根本原因:Oracle 12c 的权限作用域严格绑定容器。你在 CDB$ROOT 执行的 GRANT,哪怕加了 CONTAINER=ALL,也只影响 CDB$ROOT 和 PDB$SEED,**所有业务 PDB 都不继承**。
- 查当前会话权限:
SELECT * FROM session_privs返回空,就说明权限没落进当前 PDB -
SELECT SYS_CONTEXT('USERENV', 'CON_NAME') FROM DUAL必须确认已切到目标 PDB,否则后续所有授权都无效 - 不要依赖
GRANT RESOURCE TO c##app CONTAINER=ALL—— 它在 PDB 中根本不会生效,且可能报ORA-65047
必须在每个目标PDB中单独授本地权限
想让 c##app 能在 PDB1 建表,就得在 PDB1 里显式给它授权限。这不是“额外步骤”,而是唯一合法路径。
- 先切换容器:
ALTER SESSION SET CONTAINER = PDB1 - 授基本权限:
GRANT CREATE SESSION, CREATE TABLE TO c##app - 配表空间配额(关键!):
ALTER USER c##app QUOTA UNLIMITED ON users,否则建表仍报ORA-01950 - 如果要用角色,也在本 PDB 执行:
GRANT CONNECT, RESOURCE TO c##app(注意:RESOURCE此时只映射当前 PDB 的权限集合)
无法限制Common User“只能访问某PDB”
Common User 的本质就是跨容器存在,你不能通过权限控制让它“看不见其他 PDB”。它始终能在所有 PDB 中登录(只要被授予 CREATE SESSION),只是在未授权的 PDB 中没有任何操作能力。
真正能隔离访问范围的是 **本地用户**:CREATE USER app_user IDENTIFIED BY pwd(不加 C##,且在 PDB 中执行)。这种用户只存在于当前 PDB,连 CDB$ROOT 都查不到它。
- 若业务只需要单 PDB 访问,优先建本地用户,而非折腾
c##用户的权限边界 -
c##用户适合监控、备份等需跨 PDB 操作的场景,但必须接受它天然可见所有 PDB 的事实 - 别试图用
REVOKE在某个 PDB 中“禁用”c##用户——它在其他 PDB 的权限不受影响,且撤销操作本身无意义
常见权限失效的隐蔽原因
即使按步骤在 PDB 中授了权,仍可能失败。最常被忽略的是表空间配额和连接方式。
- 没配配额:
ALTER USER c##app QUOTA 0 ON users或完全没执行配额语句 →ORA-01950 - 用错服务名连接:
sqlplus c##app/pwd@orcl连的是 CDB service,实际进的是 CDB$ROOT;必须用 PDB 对应的服务名,如sqlplus c##app/pwd@pdb1 - 误以为
SET CONTAINER权限能让c##app自由切换:该权限只允许用户执行ALTER SESSION SET CONTAINER,不赋予任何对象操作权 - 删除用户必须回 CDB$ROOT:
DROP USER c##app CASCADE,在 PDB 中执行会报ORA-01918: user does not exist
权限模型的容器绑定是硬性规则,不是配置开关。你没法“限制”一个 c## 用户只在某 PDB 有权限,只能选择“在哪几个 PDB 显式给它权限”。而真正需要隔离的场景,应该用本地用户。


















