查表空间使用率必须联查dba_data_files和dba_free_space,仅查其一结果不准;需外连接处理空表空间,nvl避免null,临时表空间另查v$temp_space_header,生产环境应监控趋势而非单次快照。

查表空间使用率必须用 dba_data_files 和 dba_free_space 两个视图联查
只查 dba_data_files 得到的是分配总量,只查 dba_free_space 得到的是当前空闲块总和,两者缺一不可。Oracle 不提供单表直接返回“已用率”的字段,硬要只查一个视图,结果一定不准——比如临时表空间、未格式化的空闲区、段头块占用等都会导致偏差。
最简可用的联查写法是:
SELECT a.tablespace_name, ROUND(a.bytes/1024/1024, 2) AS total_mb, ROUND((a.bytes - NVL(b.bytes, 0))/1024/1024, 2) AS used_mb, ROUND(NVL(b.bytes, 0)/1024/1024, 2) AS free_mb, ROUND((a.bytes - NVL(b.bytes, 0)) * 100 / a.bytes, 2) AS pct_used FROM (SELECT tablespace_name, SUM(bytes) bytes FROM dba_data_files GROUP BY tablespace_name) a, (SELECT tablespace_name, SUM(bytes) bytes FROM dba_free_space GROUP BY tablespace_name) b WHERE a.tablespace_name = b.tablespace_name(+) ORDER BY pct_used DESC;
-
dba_free_space可能不含某些表空间(比如刚创建还没分配任何段),所以要用(+)外连接,否则这些表空间会直接被过滤掉 -
NVL(b.bytes, 0)是必须的,否则空值参与计算会让整行结果变NULL - 如果想包含临时表空间,得额外
UNION ALL查v$temp_space_header,但注意它的单位和逻辑与永久表空间不同
查不到某个用户对应的表空间?先确认权限和对象归属
常见现象:执行上面 SQL 没报错,但查不到目标用户的表空间信息。不是 SQL 写错了,而是你当前登录用户没权限访问 dba_* 视图,或该用户根本没在对应表空间里建任何对象。
- 确保你用的是有
DBA角色的账号(如sys或system),普通用户默认看不到其他用户的dba_data_files - 查某用户实际用了哪些表空间,应优先看
dba_ts_quotas:SELECT tablespace_name, max_bytes, bytes FROM dba_ts_quotas WHERE username = 'YOUR_USER' - 如果该用户没显式配额,就走默认表空间——查
dba_users.default_tablespace,再拿这个表空间名去上一步的主查询里过滤
autoextensible = 'YES' 时,“剩余空间”不等于“还能用的空间”
很多人把 dba_free_space.bytes 当成“还能扩展多少”,这是错的。真正可扩展上限取决于数据文件的 maxbytes 和当前已用空间之差,不是空闲块总和。
- 查每个数据文件的扩展能力:
SELECT file_name, autoextensible, bytes/1024/1024 cur_mb, maxbytes/1024/1024 max_mb FROM dba_data_files WHERE tablespace_name = 'USERS' - 如果
max_mb接近cur_mb,即使free_mb还有几百 MB,也可能很快爆满——因为 Oracle 无法再自动扩展文件 - 临时表空间(
temp)不走dba_free_space,它用v$temp_space_header,且空闲空间是动态重用的,不能简单套用永久表空间逻辑
生产环境别依赖单次查询结果做容量决策
表空间使用率是瞬时快照,尤其对高并发 OLTP 系统,5 分钟前查是 85%,现在可能已到 99%。真正要防爆,得盯住趋势和增长速率。
- 单次查询只能告诉你“此刻状态”,不能代替监控。建议至少每小时采集一次
dba_tablespace_usage_metrics(11g+)或自己存档历史结果 - 注意
dba_free_space的统计粒度:它只反映“完全空闲”的 extent,已分配但未使用的 segment 空间(比如INITIAL分配后没填满)不算在内 - 如果发现某表空间长期 >90%,别急着加文件——先查是不是有大对象没清理(
dba_segments按bytes倒序)、有没有归档日志占了SYSAUX、或者审计日志膨胀











