4. 表空间与数据文件容量分析

容量规划的第一步不是“加空间”,而是把当前空间账算清楚。Oracle 的空间消耗分布在三类表空间上:永久表空间承载业务数据与索引,临时表空间承载排序、哈希连接、全局临时表等中间结果,UNDO 表空间保存回滚数据以支撑读一致性与事务回滚。三者的增长驱动因素、风险表现和处置手段完全不同,必须分开采集、分开判断,最后再合并成一张容量风险清单。

一、先建立统一的采集口径

分析前先固定口径,否则不同时间点的数据无法比较。建议统一使用 DBA_TABLESPACE_USAGE_METRICS 获取永久与 UNDO 表空间的使用率,用 DBA_TEMP_FREE_SPACE 获取临时表空间使用情况,用 DBA_DATA_FILES 与 DBA_TEMP_FILES 获取文件级容量与自动扩展配置。下面是一组可直接执行的采集语句:

-- 永久表空间与 UNDO:使用率、剩余可分配空间
SELECT tablespace_name,
       ROUND(used_space * 8192 / 1024 / 1024, 1)      AS used_mb,
       ROUND(tablespace_size * 8192 / 1024 / 1024, 1) AS total_mb,
       ROUND(used_percent, 2)                         AS used_pct
FROM   dba_tablespace_usage_metrics
ORDER  BY used_percent DESC;

-- 临时表空间:已用与空闲
SELECT tablespace_name,
       ROUND(allocated_space / 1024 / 1024, 1) AS alloc_mb,
       ROUND(free_space / 1024 / 1024, 1)      AS free_mb
FROM   dba_temp_free_space;

-- 文件级:自动扩展与上限
SELECT tablespace_name, file_name,
       ROUND(bytes / 1024 / 1024, 1)          AS cur_mb,
       autoextensible,
       ROUND(maxbytes / 1024 / 1024, 1)       AS max_mb,
       increment_by * 8192 / 1024 / 1024      AS next_mb
FROM   dba_data_files
UNION ALL
SELECT tablespace_name, file_name,
       ROUND(bytes / 1024 / 1024, 1),
       autoextensible,
       ROUND(maxbytes / 1024 / 1024, 1),
       increment_by * 8192 / 1024 / 1024
FROM   dba_temp_files;

注意 used_percent 的分母是“当前已分配并可用的空间”,不是文件上限。因此一个使用率 95% 但 autoextensible=YES 且 maxbytes 远大于当前 bytes 的表空间,风险等级要低于一个使用率 80% 但 autoextensible=NO 的表空间。这正是必须把使用率与自动扩展配置放在一起看的原因。

二、永久表空间:看增长斜率而非瞬时水位

永久表空间的风险来自“持续增长 + 无法扩展”。判断增长趋势的实用做法是每日定时采样并留存历史,例如建立一张监控表,每天凌晨插入一次快照,积累两周后即可计算日均增量:

CREATE TABLE tbs_hist (
  snap_date   DATE,
  tbs_name    VARCHAR2(30),
  used_mb     NUMBER,
  total_mb    NUMBER,
  max_mb      NUMBER
);

INSERT INTO tbs_hist
SELECT TRUNC(SYSDATE), m.tablespace_name,
       m.used_space * 8192 / 1024 / 1024,
       m.tablespace_size * 8192 / 1024 / 1024,
       (SELECT SUM(maxbytes) / 1024 / 1024
        FROM   dba_data_files d
        WHERE  d.tablespace_name = m.tablespace_name)
FROM   dba_tablespace_usage_metrics m;
COMMIT;

积累数据后,用线性回归或简单差值估算“剩余可用天数”。假设某业务表空间当前已用 620 GB,文件上限合计 800 GB,近 14 天日均增长 3.2 GB,则剩余可增长空间为 180 GB,预计约 56 天触顶。若该表空间 autoextensible=NO,则剩余空间就是 800 GB 减去当前 bytes,触顶后直接报 ORA-01653,业务写入立即失败,属于高优先级风险。

还要区分“表空间整体水位”和“单文件水位”。一个表空间有 4 个数据文件,其中 3 个已满、1 个还有余量,整体使用率可能只有 70%,但新增段只能落在未满文件上,实际可用空间被严重高估。因此文件级检查不可省略,尤其要关注 maxbytes 是否被设成了 32 GB 这类偏小的值。

三、临时表空间:关注峰值而非均值

临时表空间的使用具有强烈的时段性,白天报表、夜间批处理、月末结算的峰值差异可能达到数倍。用均值判断会严重低估风险。正确做法是采集峰值:

SELECT tablespace_name,
       ROUND(allocated_space / 1024 / 1024, 1) AS alloc_mb,
       ROUND(free_space / 1024 / 1024, 1)      AS free_mb,
       ROUND((allocated_space - free_space) / 1024 / 1024, 1) AS used_mb
FROM   dba_temp_free_space;

更可靠的方式是结合 AWR 的临时段统计,查看 TEMP 表空间的历史峰值分配。若某实例临时表空间总容量 200 GB,日常使用 30 GB,但月末批处理峰值达到 190 GB,则风险不在“平均水位”,而在“峰值窗口”。此时应优先考虑:把大排序 SQL 的 PGA 参数调优、拆分批处理、或为临时表空间增加文件并设置合理的 maxbytes,而不是简单扩容了事。

临时表空间还有一个易被忽略的点:临时文件通常 autoextensible=YES,但 maxbytes 若等于当前 bytes,实际等同于不可扩展。检查时必须同时看这两个字段。

四、UNDO 表空间:看保留时间与峰值事务

UNDO 的容量需求由三个因素决定:UNDO_RETENTION 保留时间、峰值并发事务的生成速率、以及查询所需的读一致性时间。UNDO 表空间过小会导致 ORA-01555 快照过旧,过大则浪费存储。可用如下查询观察 UNDO 使用与最长查询时间的关系:

SELECT begin_time, end_time,
       undoblks, maxquerylen, tuned_undoretention
FROM   v$undostat
ORDER  BY begin_time DESC
FETCH FIRST 12 ROWS ONLY;

若 maxquerylen 经常接近或超过 tuned_undoretention,说明 UNDO 保留时间不足以支撑最长查询,ORA-01555 风险上升。此时应评估是提高 UNDO_RETENTION,还是优化长查询。UNDO 表空间同样要检查 autoextensible 与 maxbytes,并确认没有其他表空间误用了 UNDO 类型的段。

五、把三类表空间合并成风险清单

采集完成后,按“使用率、剩余可增长空间、自动扩展上限、预计触顶天数、峰值余量”五个维度打分,形成可执行的风险清单。下面是一份示例判断表(数据为教学假设值):

表空间类型已用/上限自动扩展预计触顶风险等级
APP_DATA永久620G / 800GYES,max 800G约 56 天高
APP_IDX永久180G / 200GNO约 12 天紧急
TEMP临时峰值 190G / 200GYES,max 200G峰值窗口内高
UNDOTBS1UNDO42G / 60GYES,max 60G约 90 天中

这张表的价值在于把“使用率”翻译成“还有多少天可用”,并明确每个风险的处置方向:APP_IDX 需要立即扩容或开启自动扩展;TEMP 需要优化峰值 SQL 或扩容;APP_DATA 需要纳入月度扩容计划;UNDOTBS1 保持观察并核对 UNDO_RETENTION。

表空间容量风险分析视图 采集口径 DBA_TABLESPACE_USAGE_METRICS DBA_TEMP_FREE_SPACE DBA_DATA_FILES / TEMP_FILES V$UNDOSTAT / AWR 峰值 永久表空间 关注:日均增长斜率 剩余可增长 = maxbytes - bytes 触顶后果:ORA-01653 单文件水位不可忽略 临时表空间 关注:峰值而非均值 峰值窗口:批处理 / 月末 触顶后果:ORA-01652 maxbytes = bytes 即不可扩 UNDO 表空间 关注:保留时间 vs 最长查询 maxquerylen 接近 retention 触顶后果:ORA-01555 核对 UNDO_RETENTION 风险判断五维度 使用率 | 剩余可增长空间 | 自动扩展上限 | 预计触顶天数 | 峰值余量 输出:容量风险清单 紧急(APP_IDX)→ 立即扩容 | 高(APP_DATA、TEMP)→ 计划扩容 + SQL 优化 | 中(UNDOTBS1)→ 持续观察

最后强调一点:容量分析不是一次性动作。建议把上述采集脚本做成每日定时任务,保留至少 30 天历史,并设置两级告警——使用率超过 80% 或预计触顶天数小于 30 天时触发预警,使用率超过 90% 或预计触顶小于 7 天时触发紧急告警。这样容量风险才能从“事后救火”转为“事前可见”。