1. 故障现象与问题定位
上周五凌晨3点,监控系统突然发出Oracle数据库表空间使用率超过95%的告警。DBA团队立即介入检查,发现USERS表空间在短短10分钟内从200GB暴涨到500GB,但30分钟后又自动回落到210GB左右。这种异常现象引起了我们的高度警觉。
通过查询DBA_HIST_TBSPC_SPACE_USAGE历史视图,我们确认表空间使用量确实发生过瞬时激增。进一步检查发现,该表空间主要存储业务系统的交易流水表,正常情况下日均增长约2GB。这种异常波动显然不符合业务规律。
2. 关键排查步骤与发现
2.1 检查AWR报告异常时段
我们首先提取了故障时段的AWR报告,重点关注以下指标:
- 临时表空间使用情况
- 排序操作统计
- 并行查询执行情况
- undo表空间使用量
报告显示在异常时段存在大量临时段创建操作,且出现了异常的并行查询会话。这提示我们可能存在SQL执行计划异常导致的临时空间占用。
2.2 分析ASH实时会话历史
通过查询DBA_HIST_ACTIVE_SESS_HISTORY,我们锁定了几个关键会话:
sql复制SELECT sample_time, session_id, sql_id, event, program
FROM dba_hist_active_sess_history
WHERE sample_time BETWEEN
TO_DATE('2023-08-18 02:50:00','YYYY-MM-DD HH24:MI:SS')
AND TO_DATE('2023-08-18 03:30:00','YYYY-MM-DD HH24:MI:SS')
ORDER BY sample_time;
分析发现有一个ETL作业在异常时段执行了全表扫描操作,该作业平时使用索引扫描,执行计划发生了改变。
2.3 检查SQL执行计划变更
使用DBMS_XPLAN对比历史执行计划:
sql复制SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('g8s7d5k3n2m1'));
发现该SQL在异常时段使用了全表扫描+并行查询的执行计划,而非正常的索引扫描。这导致产生了大量临时段,占用了表空间。
3. 根因分析与验证
3.1 执行计划变更原因
进一步检查发现:
- 统计信息在故障前一天自动收集
- 关键列的直方图信息丢失
- 优化器评估全表扫描成本低于索引扫描
3.2 故障复现测试
我们在测试环境模拟了相同场景:
- 删除关键列直方图
sql复制EXEC DBMS_STATS.DELETE_COLUMN_STATS(
ownname=>'SCOTT',
tabname=>'TRANSACTIONS',
colname=>'TRX_DATE');
- 收集统计信息
sql复制EXEC DBMS_STATS.GATHER_TABLE_STATS(
ownname=>'SCOTT',
tabname=>'TRANSACTIONS');
- 执行相同ETL作业
确实复现了表空间异常增长现象。
4. 解决方案与优化措施
4.1 短期应急方案
- 固定问题SQL的执行计划:
sql复制EXEC DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(
sql_id=>'g8s7d5k3n2m1',
plan_hash_value=>123456789);
- 添加SQL提示强制使用索引:
sql复制SELECT /*+ INDEX(t TRANSACTIONS_IDX) */ *
FROM transactions t
WHERE trx_date > SYSDATE-30;
4.2 长期优化方案
- 调整统计信息收集策略:
sql复制BEGIN
DBMS_STATS.SET_TABLE_PREFS(
'SCOTT',
'TRANSACTIONS',
'ESTIMATE_PERCENT',
'DBMS_STATS.AUTO_SAMPLE_SIZE');
DBMS_STATS.SET_TABLE_PREFS(
'SCOTT',
'TRANSACTIONS',
'METHOD_OPT',
'FOR ALL COLUMNS SIZE AUTO');
END;
- 设置表空间自动扩展预警:
sql复制BEGIN
DBMS_SERVER_ALERT.SET_THRESHOLD(
metrics_id => DBMS_SERVER_ALERT.TABLESPACE_PCT_USED,
warning_operator => DBMS_SERVER_ALERT.OPERATOR_GE,
warning_value => '85',
critical_operator => DBMS_SERVER_ALERT.OPERATOR_GE,
critical_value => '95',
observation_period => 1,
consecutive_occurrences => 1,
instance_name => NULL,
object_type => DBMS_SERVER_ALERT.OBJECT_TYPE_TABLESPACE,
object_name => 'USERS');
END;
5. 经验总结与最佳实践
- 统计信息管理要点:
- 关键业务表避免使用自动采样
- 重要列必须保留直方图信息
- 大表统计信息收集安排在业务低峰期
- 执行计划稳定性建议:
- 对关键SQL实施执行计划基线
- 定期检查执行计划变更情况
- 使用SQL Performance Analyzer评估变更影响
- 表空间监控改进:
sql复制-- 创建表空间使用趋势监控视图
CREATE MATERIALIZED VIEW tbs_usage_trend
REFRESH COMPLETE EVERY 1 HOUR
AS
SELECT
tablespace_name,
ROUND(SUM(bytes)/1024/1024) size_mb,
SYSDATE snap_time
FROM dba_segments
GROUP BY tablespace_name;
- 自动化巡检脚本示例:
sql复制-- 检查异常表空间增长
SELECT
t.tablespace_name,
ROUND(t.used_space*t.block_size/1024/1024) current_mb,
ROUND((t.used_space*t.block_size/1024/1024 - h.used_mb)) growth_mb,
h.snap_time
FROM
dba_tablespace_usage_metrics t,
(SELECT
tablespace_name,
ROUND(SUM(bytes)/1024/1024) used_mb,
MAX(snap_time) snap_time
FROM tbs_usage_history
WHERE snap_time > SYSDATE-1/24
GROUP BY tablespace_name) h
WHERE
t.tablespace_name = h.tablespace_name
AND (t.used_space*t.block_size/1024/1024 - h.used_mb) > 1000;
通过这次故障处理,我们完善了表空间监控机制,优化了统计信息收集策略,并建立了SQL执行计划变更的评估流程。建议DBA团队定期检查关键SQL的执行计划稳定性,特别是在统计信息更新后。