必须在目标pdb内执行用户操作,否则用户会创建在cdb$root中导致无法登录或权限错位;连接应指定pdb服务名或先用alter session set container切换容器,再创建local用户并授予create session等本地权限。
必须在目标pdb内执行用户操作,否则创建的用户会落在cdb$root中,导致无法登录该pdb或权限错位。
连接时必须指定PDB服务名或显式切换容器
直接用 sqlplus / as sysdba 登录,默认进入 CDB$ROOT,此时任何 CREATE USER 都会建在根容器。常见错误是连上就建用户,结果用户根本不在目标PDB里。
- 推荐方式:连接时直接指定服务名,如
sqlplus system/password@pdb_service_name,避免手动切容器出错 - 次选方式:若已连到CDB$ROOT,先运行
ALTER SESSION SET CONTAINER = pdb_name,再确认当前容器:SELECT SYS_CONTEXT('USERENV', 'CON_NAME') FROM DUAL - 切完容器后,
CREATE USER u1 IDENTIFIED BY pwd才会在该PDB中创建本地用户(COMMON='NO')
PDB内只能创建LOCAL用户,不能加CONTAINER=ALL
在PDB中执行 CREATE USER 时,Oracle默认按LOCAL处理。若强行写 CONTAINER=ALL,会立即报错 ORA-65094: invalid local user name —— 因为LOCAL用户天生不支持跨容器。
- Common用户必须以
C##或##开头,且只能在CDB$ROOT中创建 - PDB中创建的用户(如
scott、hr)自动为LOCAL,CON_ID字段显示对应PDB的ID,不会出现在其他PDB的CDB_USERS查询结果中 - 查用户归属:
SELECT USERNAME, COMMON, CON_ID FROM CDB_USERS WHERE USERNAME = 'U1',结果只有一行且CON_ID匹配目标PDB
授权必须在PDB内完成,且仅限本地权限
PDB层级的权限不具备跨容器传播能力。在PDB中执行 GRANT,只影响当前容器;试图用 CONTAINER=ALL 授权会触发 ORA-65047 错误。
- 可用权限:如
CREATE SESSION、CREATE TABLE、UNLIMITED TABLESPACE等本地系统权限 - 慎用预定义角色:
RESOURCE可授,但其包含的权限仅在本PDB生效;DBA角色不可用,会报ORA-01917: user or role 'DBA' does not exist - 查实际授予的权限:
SELECT * FROM DBA_SYS_PRIVS WHERE GRANTEE = 'U1'(注意是DBA_*视图,不是CDB_*)
删除用户前务必确认当前容器
在 CDB$ROOT 中执行 DROP USER u1 CASCADE 是高危操作:Oracle 12.2+ 默认会级联删除所有PDB中同名的LOCAL用户,多个业务库可能同时失联。
- 安全做法:先
ALTER SESSION SET CONTAINER = target_pdb,再执行DROP USER u1 CASCADE - 验证是否删对了:
SELECT COUNT(*) FROM CDB_USERS WHERE USERNAME = 'U1' AND CON_ID = (SELECT CON_ID FROM V$PDBS WHERE NAME = 'target_pdb') - 别依赖
SHOW CON_NAME,它不一定实时刷新,始终用SYS_CONTEXT函数确认
最易被忽略的一点:PDB用户看不到其他PDB的对象,也看不到CDB$ROOT里的表,哪怕被授予了 SELECT_CATALOG_ROLE —— 这不是权限没给够,而是数据字典视图本身做了容器隔离。查本PDB对象,永远用 DBA_* 视图,而不是想当然去查 CDB_USERS。











