DBMS_SERVER_ALERT.SET_THRESHOLD无法为临时表空间设置使用率告警,因其仅支持永久表空间的TABLESPACE_PCT_FULL等指标,而临时表空间无对应监控数据源,需通过查询v$temp_space_header等视图并结合调度脚本实现自定义告警。
dbms_server_alert.set_threshold 不能直接为临时表空间设置使用率告警——它只支持永久表空间(object_type_tablespace)的 tablespace_pct_full 或 tablespace_utilization 指标,而临时表空间不在此监控范围内。
为什么对 TEMP 表空间调用 SET_THRESHOLD 总是失败
执行类似下面的语句不会报错,但也不会生效:
BEGIN
DBMS_SERVER_ALERT.SET_THRESHOLD(
metrics_id => DBMS_SERVER_ALERT.TABLESPACE_PCT_FULL,
object_type => DBMS_SERVER_ALERT.OBJECT_TYPE_TABLESPACE,
object_name => 'TEMP',
warning_value => '70',
critical_value => '90',
...
);
END;原因很明确:
-
TABLESPACE_PCT_FULL指标只适用于本地管理的永久表空间(LMT),Oracle 内部不采集临时表空间的「百分比已用」指标 -
v$metricname中查不到Temp Tablespace Space Usage或类似 metric_name -
DBA_THRESHOLDS视图里永远看不到object_name = 'TEMP'的记录 - 即使强行启用(
DBMS_SERVER_ALERT.ENABLE)也无效,因为底层没有对应的数据源
替代方案:用 SQL 查询 + 调度脚本模拟阈值告警
既然 DBMS_SERVER_ALERT 不支持,就得自己搭轮子。核心逻辑是定时查 v$temp_space_header 或 dba_temp_free_space,算出使用率,再触发通知。
关键点:
- 计算公式必须用
(used_bytes / (used_bytes + free_bytes)) * 100,不能只看dba_temp_free_space.bytes(它不含已分配但未释放的 sort segment) - 推荐查
v$temp_space_header:它反映当前实际分配的 temp 段总量,更贴近真实压力 - 示例检查语句:
SELECT tablespace_name, ROUND(100 * used_bytes / (used_bytes + NVL(free_bytes, 0)), 2) AS "USE_RATE(%)" FROM v$temp_space_header WHERE tablespace_name = 'TEMP';
把这个查询封装进 PL/SQL 脚本,搭配 UTL_MAIL.SEND 或外部 shell + sqlplus -S 发邮件,再用 DBMS_SCHEDULER 每 5–10 分钟跑一次即可。
容易被忽略的兼容性细节
临时表空间监控脚本在不同 Oracle 版本行为不一致:
- Oracle 11gR2+ 才有
v$temp_space_header;10g 只能靠sort_segment和v$sort_usage估算,不准 -
dba_temp_free_space的FREE_SPACE字段在某些版本中会包含未格式化的空间,导致计算偏低 - 如果启用了多个临时表空间(
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE ...),脚本必须遍历所有tablespace_name,不能只盯'TEMP' - RAC 环境下,
v$视图默认只返回当前实例数据,需用GV$并加inst_id过滤
真正起作用的告警从来不是靠一个包自动完成的,而是靠你清楚知道哪个视图返回真实数据、哪个字段代表“正在用”、以及什么时候该绕过官方接口自己动手。


















