配额是oracle中用户在表空间创建段的强制前提,未显式设置即等效于quota 0,即使有create table权限也会报ora-01536;dba_ts_quotas无记录即表示无配额,非遗漏而是默认禁止策略。

配额不是“可选功能”,而是生效前提
没设配额 = 不能建任何段,哪怕有 CREATE TABLE 权限也报 ORA-01536: space quota exceeded for tablespace 'USERS'。Oracle 不会默认给用户分配空间,DBA_TS_QUOTAS 里查不到记录,就等于配额为 0 —— 这不是遗漏,是强制策略。
常见误操作:GRANT UNLIMITED TABLESPACE 后以为万事大吉,结果发现对象还是落不进目标表空间。因为该权限只绕过配额检查,但不解决「用户在该表空间是否有显式配额」这个前提;且它太宽泛,违背最小权限原则。
- 必须先确保用户已存在、目标表空间(如
USERS)状态为ONLINE - 执行者需有
ALTER USER权限(通常是DBA角色) - 配额只对永久表空间有效,对
TEMP或UNDOTBS1执行会直接报ORA-02156
QUOTA 0 ON 和 QUOTA UNLIMITED ON 的真实含义
QUOTA 0 ON users 不是“限制为零”,而是彻底禁止在该表空间创建新段(表、索引、LOB 等)。已有对象不受影响,但后续 INSERT 若触发 extent 分配,仍可能报错。
QUOTA UNLIMITED ON users 是显式放开,不是“恢复默认”。它覆盖之前所有数值配额,且优先级高于 RESOURCE 角色隐含的配额行为。注意:如果用户同时拥有 UNLIMITED TABLESPACE 权限,那 QUOTA 设置会被忽略 —— 所以生产环境应先 REVOKE UNLIMITED TABLESPACE,再设 QUOTA。
- 设为
0后,CREATE TABLE t AS SELECT ...会失败,即使源表在别的表空间 -
QUOTA 100M ON users和QUOTA 102400K ON users等价,单位不敏感,但建议统一用M或G - 表空间名大小写敏感:若创建时用了双引号
"USERS",配额语句也必须用"USERS",否则报ORA-00959
怎么查配额是否生效、当前用了多少
别依赖 DBA_USERS.DEFAULT_TABLESPACE,它只告诉你默认往哪放,不反映实际可用空间。真正要看的是 DBA_TS_QUOTAS:
SELECT username, tablespace_name,
bytes/1024/1024 AS mb_used,
max_bytes/1024/1024 AS mb_quota
FROM dba_ts_quotas
WHERE username = 'SCOTT';
如果返回空行,说明没设过配额 → 等效于 0。若 mb_used > mb_quota,说明已超限(常见于 UNLIMITED TABLESPACE 未回收时)。
-
bytes是当前已用空间(含未释放的已删除对象),max_bytes是配额上限(-1 表示UNLIMITED) - 想确认对象实际落在哪:查
SELECT table_name, tablespace_name FROM user_tables,和配额设置无关,只反映物理位置 - 临时段、回滚段、物化视图日志等系统对象不计入用户配额,它们走各自专用机制
配额设多大才合理?看业务,不拍脑袋
没有通用值。OLTP 用户建几十张小表,100MB 够用;ETL 用户跑日结分区表,一天可能吃掉 5GB。关键看历史增长和对象生命周期:
- 查最近 7 天最大单日增长:
SELECT MAX(bytes_used) FROM dba_hist_tbspc_space_usage WHERE tablespace_id = (SELECT tablespace_id FROM dba_tablespaces WHERE tablespace_name = 'USERS'); - 若用户有长期归档表,配额得覆盖其全生命周期,不能只按当前占用设
- 避免设过小(如
1M)导致频繁 DDL 报错;也别设过大(如100G)浪费监控意义 - 上线前用模拟负载压测:建典型对象 + 批量插入,观察
DBA_TS_QUOTAS.bytes变化节奏
最易被忽略的一点:配额检查发生在 DML/DDL 执行时,不是定时刷新,也没有缓冲期。一旦超限,下一条 INSERT 就立刻失败 —— 它不像磁盘配额那样有 grace period。











