DBA_FREE_SPACE统计的空闲空间不等于实际可用空间,因其仅记录已格式化、可分配块,忽略未格式化区、AUTOEXTEND上限、BIGFILE关联错误、字典对象占用及RAC缓存延迟等问题;永久表空间应联查DBA_DATA_FILES与DBA_SEGMENTS,TEMP和UNDO需分别用V$TEMP_SPACE_HEADER和GV$UNDOSTAT等专用视图。

dba_free_space 统计的“空闲空间”不等于你能写进去的空间。直接用它除以 dba_data_files 算出来的使用率,经常在关键时刻失真——比如 SYSTEM 显示 100% 却还能建索引,TEMP 突然飙到 99% 又秒降为 0。
dba_free_space 为什么不能直接算剩余空间
它只统计已格式化、可立即分配的块;新添加但未格式化的数据文件区(如刚执行
ALTER TABLESPACE ADD DATAFILE后)不计入,实际还能写,但视图里 free 是 0BIGFILE表空间下所有数据文件file_id = 1,若按file_id关联dba_free_space和dba_data_files,会错误聚合多个文件的空闲块它完全忽略
autoextensible = 'YES'的上限:如果maxbytes是 0(无上限),或maxbytes小于当前bytes(已达硬上限),这些都得动态纳入总容量基线不处理未格式化空闲块(unformatted blocks),这部分在 ASSM + LMT 下真实存在,但不在
dba_free_space中SYSTEM/SYSAUX中字典对象占用的空间不体现在dba_free_space的 free 计算中,但它们确实占用了物理空间
永久表空间要查 dba_data_files + dba_segments 而非 dba_free_space
真正反映“已用”的是段(segment)占用,不是 free 视图的补集:
dba_segments汇总所有永久段(表、索引、LOB、undo segment 等)的bytes,比dba_data_files - dba_free_space更可靠必须过滤掉
status != 'VALID'的 segment(如被标记为 dropped 但未 cleanup 的)对于
SYSTEM表空间,还需额外关联sys.ts$和obj$确认字典对象是否被重复计算-
推荐组合查询逻辑:
SELECT d.tablespace_name, ROUND(SUM(d.bytes)/1024/1024, 2) AS total_mb, ROUND(SUM(s.bytes)/1024/1024, 2) AS used_mb, ROUND((SUM(d.bytes)-SUM(s.bytes))/1024/1024, 2) AS free_mb, ROUND(SUM(s.bytes)/SUM(d.bytes)*100, 2) AS pct_used FROM dba_data_files d LEFT JOIN dba_segments s ON d.tablespace_name = s.tablespace_name WHERE d.status != 'OFFLINE' GROUP BY d.tablespace_name; 注意:此方式不包含临时段、undo 段的运行时内存占用,仅适用于永久表空间
TEMP 和 UNDO 表空间必须换视图,不能套用同一套逻辑
TEMP:真实压力看v$tempseg_usage(当前会话临时段)和v$temp_space_header(文件级空闲块),后者在 ASM 中有 3–30 秒缓存延迟;RAC 下必须用gv$并取各节点峰值UNDO:没有“剩余空间”概念;核心指标是undo_retention和gv$undostat.tuned_undoretention,空间是否紧张取决于活跃事务量和 retention 设置,而非 free 块数量-
查 TEMP 使用率示例(单实例):
SELECT tablespace_name, ROUND(SUM(bytes_used)/1024/1024, 2) AS used_mb, ROUND(SUM(bytes)/1024/1024, 2) AS total_mb, ROUND(SUM(bytes_used)/SUM(bytes)*100, 2) AS pct_used FROM v$temp_extent_pool GROUP BY tablespace_name; RAC 下查 TEMP 必须在每个节点执行
gv$tempseg_usage并人工比对最大值,不能简单 avg 或 sum
RAC 环境下 dba_free_space 的结果不可跨节点复用
dba_free_space是实例本地缓存视图,依赖 LRU 管理器刷新,高并发 DML 后可能滞后几秒某节点显示 95%,另一节点可能还是 82%,这不是数据错,是缓存不同步
紧急判断前建议先执行
ALTER SYSTEM CHECKPOINT强制刷脏页,再查-
正确做法:
- 在每个节点用
sqlplus / as sysdba连接后单独执行空间查询 - 若某节点报
ORA-01219: database not open,说明该实例未正常启动,需检查 CRS 状态:crsctl stat res -t - 不要用
GV$视图直接 joindba_free_space,因为后者根本不是全局视图
- 在每个节点用
真实剩余空间不是“能看见的 free 块”,而是“此刻能成功分配且不触发扩展/报错的连续空间”。这需要结合 autoextend 状态、ASM 分配单元(AU)粒度、段高水位、甚至 buffer cache 持有情况综合判断——尤其在 RAC 和 bigfile 场景下,漏掉任一维度都可能误判。


















