必须在cdb$root中创建以c##开头的公共用户并授予pdb_db a角色才能管理所有pdb;在pdb中创建用户或授pdb_db a权限均会失败,因该角色仅在cdb$root有效且需container=all。
不能在pdb中创建“管理所有pdb”的用户——这类权限只存在于cdb$root,且必须用c##前缀创建公共用户。试图在某个pdb里建一个能跨pdb操作的账号,oracle会直接拒绝(如ora-65094或ora-65047)。真正可行的做法,是回到cdb$root,用公共用户+公共角色组合实现集中管控。
为什么CREATE USER u1 IDENTIFIED BY pwd在PDB里失败?
Oracle 12c强制区分用户类型:
- PDB内只能创建本地用户(local user),名字不能带
C##,但权限范围严格限制在当前PDB内 - 想管理多个PDB(比如启停、备份、查所有PDB状态),必须是公共用户(common user),名字必须以
C##或c##开头,且只能在CDB$ROOT中创建 - 直接在PDB里执行
CREATE USER admin IDENTIFIED BY p123会报ORA-65096: invalid common user or role name
如何在CDB$ROOT中创建可管理全部PDB的公共用户
切换到根容器后,按顺序执行以下操作:
- 确认当前容器:
SELECT SYS_CONTEXT('USERENV', 'CON_NAME') FROM DUAL,结果必须是CDB$ROOT - 创建公共用户:
CREATE USER C##pdb_admin IDENTIFIED BY secure_pwd CONTAINER=ALL(CONTAINER=ALL是关键,缺了就只是CDB$ROOT本地用户) - 授予CDB级管理权限:
GRANT SYSDBA, PDB_DBA TO C##pdb_admin CONTAINER=ALL(注意:不是DBA角色,PDB_DBA才是专为PDB管理设计的公共角色) - 可选但推荐:
GRANT SELECT_CATALOG_ROLE TO C##pdb_admin CONTAINER=ALL,以便查询CDB_*视图(如CDB_PDBS、CDB_USERS)
PDB_DBA和DBA角色到底差在哪?
这是最容易混淆也最危险的一点:
-
DBA是传统单机数据库的角色,包含大量CDB级系统权限(如ALTER DATABASE、DROP TABLESPACE),在CDB环境里授予它等于开放整个容器,不推荐给非SYS用户 -
PDB_DBA是12c新增的公共角色,权限聚焦在PDB生命周期操作:ALTER PLUGGABLE DATABASE ... OPEN、CREATE PLUGGABLE DATABASE、DROP PLUGGABLE DATABASE等,且自动适配CONTAINER=ALL语义 - 在PDB中执行
GRANT DBA TO u1会报ORA-01917: user or role 'DBA' does not exist,因为DBA角色在PDB上下文不可见
连接与使用这个CDB管理员用户的注意事项
即使用户建对了,连错地方依然白搭:
- 必须用
sqlplus C##pdb_admin/secure_pwd@cdb_service_name AS SYSDBA连接,不能指定PDB服务名(否则进的是PDB,看不到其他PDB) - 连接后默认仍在
CDB$ROOT,查SHOW CON_NAME确认;要操作某PDB,仍需ALTER SESSION SET CONTAINER=pdb_name,但此时你有权限 - 不要在PDB里尝试
GRANT PDB_DBA TO u1——该角色只在CDB$ROOT有效,PDB中执行会报ORA-01917 - 如果需要让某个PDB用户也能执行
ALTER PLUGGABLE DATABASE ... OPEN,必须由CDB管理员显式授予SET CONTAINER权限并授权PDB_DBA,且该用户本身也得是C##开头的公共用户
最关键的细节往往藏在容器边界上:一个CONTAINER=ALL漏写,一个ALTER SESSION少切,或者连错了服务名,都会让看似完整的授权链彻底失效。多租户不是加了个PDB开关,而是把权限模型从平面拉成了立体——CDB$ROOT是控制塔,每个PDB是独立舱室,钥匙(用户)和门禁卡(角色)必须严格匹配层级。











