必须先确认当前连接的是pdb而非cdb$root,否则create user会报ora-65096错误;需用alter session set container切换至目标pdb(如xepdb1),再创建用户、指定专用表空间及配额,并仅授予最小必要权限。

必须先确认当前连接的是 PDB,不是 CDB$ROOT
Oracle 21c 默认启用多租户架构,CREATE USER 命令在 CDB$ROOT 下执行会报错 ORA-65096:公共用户名必须以 C## 开头。但你想要的是应用账号,不是 DBA 管理账号,所以绝不能在根容器里操作。
常见错误现象:ORA-65096: invalid common user or role name —— 这说明你还在 CDB$ROOT,没切到 PDB。
- 先连上具有 DBA 权限的账户(如
sys/orcl@localhost:1521/XE as sysdba) - 运行
SHOW CON_NAME,如果返回CDB$ROOT,就立刻切换:ALTER SESSION SET CONTAINER = XEPDB1(XE 版本默认 PDB 名是XEPDB1;企业版请用SELECT NAME FROM V$PDBS查) - 再执行
SHOW CON_NAME确认输出是XEPDB1或你的目标 PDB 名
创建用户时指定表空间和配额,避免写入 SYSTEM
不显式指定 DEFAULT TABLESPACE,用户会落到 USERS 表空间;但更稳妥的做法是单独建一个应用表空间,并把配额限制死——既防误写大表,也避免挤占系统空间。
示例(在已切换的 PDB 内执行):
CREATE TABLESPACE app_ts DATAFILE '/opt/oracle/oradata/XE/XEPDB1/app01.dbf' SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE 500M; CREATE USER app_user IDENTIFIED BY "SecurePass123!" DEFAULT TABLESPACE app_ts QUOTA 100M ON app_ts;
注意点:
-
QUOTA 100M比UNLIMITED安全得多,应用出 Bug 循环插入也不会撑爆磁盘 - 路径
/opt/oracle/oradata/XE/XEPDB1/必须真实存在且 Oracle 用户有写权限;XE 版本该路径通常固定,非 XE 环境请先查SELECT NAME FROM V$DATAFILE - 别用
SYSTEM或SYSAUX表空间——那是 Oracle 自己用的,写业务数据属于严重违规
只授应用真正需要的权限,禁用“万能角色”
GRANT DBA TO app_user 或 GRANT RESOURCE TO app_user 是最常见也最危险的授权方式。RESOURCE 角色隐含 UNLIMITED TABLESPACE,等于废掉了前面设的配额;DBA 更是直接绕过所有隔离。
最小集权限组合(按需叠加):
-
CREATE SESSION:登录必需 -
CREATE TABLE、CREATE VIEW、CREATE SEQUENCE:仅当应用要建对象时才给 -
SELECT ANY DICTIONARY和LOGMINING:仅用于 CDC 工具(如 Debezium、FineDataLink),普通 CRUD 应用完全不需要 - 对具体表的权限:用
GRANT SELECT, INSERT, UPDATE ON schema.table TO app_user替代SELECT ANY TABLE
典型安全授权语句:
GRANT CREATE SESSION, CREATE TABLE, CREATE SEQUENCE, CREATE PROCEDURE TO app_user; GRANT SELECT, INSERT, UPDATE, DELETE ON app_user.emp TO app_user; GRANT SELECT ON app_user.dept TO app_user;
验证权限是否过度,用实际连接测试
别只信 SQL 执行成功,要模拟应用行为验证。用新账号登录后,立刻试几件关键但危险的事:
- 执行
SELECT COUNT(*) FROM dba_users—— 如果能查,说明误授了SELECT ANY DICTIONARY - 执行
CREATE TABLE test_in_system (x INT) TABLESPACE SYSTEM—— 如果成功,说明UNLIMITED TABLESPACE或配额失效 - 执行
SELECT * FROM v$logmnr_contents—— 如果能查,说明开了不必要的LOGMINING
真正干净的应用账号,应该只能访问自己 schema 下的对象,不能跨 schema 查系统视图,也不能在非默认表空间建表。一旦发现越权,立刻回收权限:REVOKE SELECT ANY DICTIONARY FROM app_user。
最后提醒:PDB 名、表空间路径、密码强度策略这些细节,在不同部署环境(XE / Standard / RAC)下差异很大,照搬示例前务必用 V$PDBS 和 V$DATAFILE 确认现场实际值。











