ora-65096错误源于在cdb$root中创建非c##前缀用户,正确做法是先切容器至pdb再建本地用户,或在cdb层用c##前缀加container=all;业务用户必须建在pdb内,且需正确配置service_name才能连接。

在 Oracle 19c 多租户架构下,CDB 和 PDB 的用户体系是隔离的:CDB 层只能建 C## 开头的普通用户(common user),PDB 层才能建本地用户(local user);混用层级或忽略容器上下文,必然导致权限失效、对象不可见或 ORA-65096 错误。
create user 报 ORA-65096:没切对容器就执行
这是最常见报错,本质是当前 session 还在 CDB$ROOT,却试图创建不带 C## 前缀的用户。Oracle 强制要求:在 CDB$ROOT 中建用户,必须用 C## 前缀,且需显式指定 CONTAINER = ALL 或 CONTAINER = CURRENT。
-
ORA-65096: invalid common user or role name→ 当前在CDB$ROOT,但写了create user appuser identified by pwd; - 正确做法是:先确认容器:
show con_name;,再按需切换:alter session set container = pdb1; - 若真要在 CDB 层建跨 PDB 用户(如监控账号),必须写全:
create user c##monuser identified by pwd container = all; - 不指定
container子句时,默认值为CURRENT;但在CDB$ROOT下,CURRENT不允许创建非C##用户
在 PDB 内建业务用户:必须先切 container
PDB 是业务用户的唯一合法落脚点。所有业务表空间、角色、对象都应绑定在 PDB 内,不能“图省事”留在 CDB$ROOT。
通过 Google 服务账户在代码中读取或写入用户的 Google 表格、文档、云盘或日历——无头、无需 OAuth 浏览器流程。适用于已获得服务账户凭证的情况。
- 执行前务必验证:
select sys_context('USERENV','CON_NAME') from dual;返回值必须是目标 PDB 名(如PDB1) - 建用户语句示例:
create user appuser identified by app123 default tablespace users temporary tablespace temp; - 必须显式指定
default tablespace,否则会继承 PDB 的默认表空间(可能不是你期望的) - 授权要分两步:先授系统权限(如
create session,create table),再授角色(如connect,resource);注意resource角色在 19c 中已不包含unlimited tablespace,需单独授
common user 与 local user 的权限边界
普通用户(C##)和本地用户(无前缀)权限作用域完全不同,不能互相替代。
-
C##admin在CDB$ROOT创建后,可通过container=all授予跨所有 PDB 的权限(如select any dictionary),但无法直接访问 PDB 内业务表,除非显式grant select on appuser.t1 to c##admin; - 本地用户(如
appuser)只存在于单个 PDB,show pdbs切换到其他 PDB 后,该用户完全不可见 - 不要给本地用户授
sysdba—— 这是 CDB 级特权,本地用户拿不到;也不要在 PDB 内尝试grant sysdba to appuser;(会报ORA-65101) - 密码文件认证下,
C##用户可远程连接 CDB 并切换容器;本地用户只能连到对应 PDB 的 service_name,不能直连 CDB 实例名
用户创建后连不上:service_name 和监听配置漏了
建完用户只是第一步,连不上往往卡在客户端路由层。
- 检查监听是否识别该 PDB:
lsnrctl status输出中要有对应SERVICE_NAME,例如service_name = pdb1.example.com - tnsnames.ora 中 service_name 必须与 PDB 的
db_domain+db_name拼接一致,不能只写ORCLCDB(那是 CDB 实例名) - 确认 PDB 已 open:
select name, open_mode from v$pdbs where name = 'PDB1';,状态必须是READ WRITE - 测试连接命令:
sqlplus appuser/app123@//localhost:1521/pdb1.example.com,注意用//host:port/service_name格式,不是 SID
真正容易被忽略的是:PDB 的 service_name 默认由 db_name 和 db_domain 组成,而很多人改了 db_name 却忘了同步 db_domain,或者监听里硬编码了旧 service。这类问题不会报用户不存在,而是直接报 ORA-12514: TNS:listener does not currently know of service requested in connect descriptor —— 它根本没走到认证那步。










