外观
Oracle 空间不足故障
空间不足的症状
1. 错误信息
表空间不足:
ORA-01653: unable to extend table OWNER.TABLE by 128 in tablespace TABLESPACE_NAME临时表空间不足:
ORA-01652: unable to extend temp segment by 128 in tablespace TEMPUNDO 表空间不足:
ORA-30036: unable to extend segment by 8 in undo tablespace 'UNDOTBS1'归档日志空间不足:
ORA-00257: archiver error. Connect internal only, until freed.
2. 数据库性能下降
- 查询执行时间变长
- 事务提交时间变长
- 数据库响应变慢
3. 监控指标异常
- 表空间使用率接近或达到 100%
- 数据文件自动扩展频繁
- 临时表空间使用率持续高位
空间不足的诊断方法
1. 检查表空间使用情况
查看表空间使用率:
sqlSELECT tablespace_name, ROUND((total_space - free_space) / total_space * 100, 2) AS used_percent, total_space, free_space FROM ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS total_space FROM dba_data_files GROUP BY tablespace_name ) t1, ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS free_space FROM dba_free_space GROUP BY tablespace_name ) t2 WHERE t1.tablespace_name = t2.tablespace_name ORDER BY used_percent DESC;查看临时表空间使用情况:
sqlSELECT tablespace_name, ROUND((total_space - free_space) / total_space * 100, 2) AS used_percent, total_space, free_space FROM ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS total_space FROM dba_temp_files GROUP BY tablespace_name ) t1, ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS free_space FROM dba_free_space WHERE tablespace_name IN (SELECT tablespace_name FROM dba_temp_files) GROUP BY tablespace_name ) t2 WHERE t1.tablespace_name = t2.tablespace_name ORDER BY used_percent DESC;查看 UNDO 表空间使用情况:
sqlSELECT tablespace_name, ROUND((total_space - free_space) / total_space * 100, 2) AS used_percent, total_space, free_space FROM ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS total_space FROM dba_data_files WHERE tablespace_name IN (SELECT tablespace_name FROM dba_tablespaces WHERE contents = 'UNDO') GROUP BY tablespace_name ) t1, ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS free_space FROM dba_free_space WHERE tablespace_name IN (SELECT tablespace_name FROM dba_tablespaces WHERE contents = 'UNDO') GROUP BY tablespace_name ) t2 WHERE t1.tablespace_name = t2.tablespace_name ORDER BY used_percent DESC;
2. 检查数据文件情况
查看数据文件大小和自动扩展设置:
sqlSELECT file_name, tablespace_name, ROUND(bytes / 1024 / 1024, 2) AS size_mb, ROUND(maxbytes / 1024 / 1024, 2) AS max_size_mb, autoextensible FROM dba_data_files ORDER BY tablespace_name, file_name;查看数据文件增长历史:
sqlSELECT file_name, tablespace_name, increment_by * 8 / 1024 AS increment_mb FROM dba_data_files WHERE autoextensible = 'YES' ORDER BY tablespace_name, file_name;
3. 检查归档日志空间
查看归档日志目标位置:
sqlSHOW PARAMETER log_archive_dest;检查归档日志空间使用情况:
bashdf -h <归档日志目录>
4. 检查大对象和大表
查看大表:
sqlSELECT owner, table_name, ROUND(bytes / 1024 / 1024, 2) AS size_mb FROM dba_segments WHERE segment_type = 'TABLE' ORDER BY bytes DESC FETCH FIRST 10 ROWS ONLY;查看大索引:
sqlSELECT owner, segment_name, ROUND(bytes / 1024 / 1024, 2) AS size_mb FROM dba_segments WHERE segment_type = 'INDEX' ORDER BY bytes DESC FETCH FIRST 10 ROWS ONLY;查看大分区:
sqlSELECT owner, segment_name, partition_name, ROUND(bytes / 1024 / 1024, 2) AS size_mb FROM dba_segments WHERE segment_type LIKE '%PARTITION' ORDER BY bytes DESC FETCH FIRST 10 ROWS ONLY;
空间不足的解决方案
1. 表空间不足的解决方案
方法 1:扩展数据文件
手动扩展数据文件:
sqlALTER DATABASE DATAFILE '/u01/app/oracle/oradata/ORCL/users01.dbf' RESIZE 1000M;启用自动扩展:
sqlALTER DATABASE DATAFILE '/u01/app/oracle/oradata/ORCL/users01.dbf' AUTOEXTEND ON NEXT 100M MAXSIZE 2048M;
方法 2:添加数据文件
- 添加数据文件:sql
ALTER TABLESPACE users ADD DATAFILE '/u01/app/oracle/oradata/ORCL/users02.dbf' SIZE 500M AUTOEXTEND ON NEXT 100M MAXSIZE 2048M;
方法 3:清理表空间
删除不需要的表:
sqlDROP TABLE owner.table_name;清理表数据:
sqlDELETE FROM owner.table_name WHERE condition; COMMIT;重建表释放空间:
sqlALTER TABLE owner.table_name MOVE; ALTER INDEX owner.index_name REBUILD;使用分区表:
sqlALTER TABLE owner.table_name DROP PARTITION partition_name;
2. 临时表空间不足的解决方案
方法 1:扩展临时文件
手动扩展临时文件:
sqlALTER DATABASE TEMPFILE '/u01/app/oracle/oradata/ORCL/temp01.dbf' RESIZE 1000M;启用自动扩展:
sqlALTER DATABASE TEMPFILE '/u01/app/oracle/oradata/ORCL/temp01.dbf' AUTOEXTEND ON NEXT 100M MAXSIZE 2048M;
方法 2:添加临时文件
- 添加临时文件:sql
ALTER TABLESPACE temp ADD TEMPFILE '/u01/app/oracle/oradata/ORCL/temp02.dbf' SIZE 500M AUTOEXTEND ON NEXT 100M MAXSIZE 2048M;
方法 3:创建新的临时表空间
创建新的临时表空间:
sqlCREATE TEMPORARY TABLESPACE temp_new TEMPFILE '/u01/app/oracle/oradata/ORCL/temp_new01.dbf' SIZE 1000M AUTOEXTEND ON NEXT 100M MAXSIZE 2048M;设置为默认临时表空间:
sqlALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp_new;删除旧的临时表空间:
sqlDROP TABLESPACE temp INCLUDING CONTENTS AND DATAFILES;
3. UNDO 表空间不足的解决方案
方法 1:扩展 UNDO 数据文件
手动扩展 UNDO 数据文件:
sqlALTER DATABASE DATAFILE '/u01/app/oracle/oradata/ORCL/undotbs01.dbf' RESIZE 1000M;启用自动扩展:
sqlALTER DATABASE DATAFILE '/u01/app/oracle/oradata/ORCL/undotbs01.dbf' AUTOEXTEND ON NEXT 100M MAXSIZE 2048M;
方法 2:添加 UNDO 数据文件
- 添加 UNDO 数据文件:sql
ALTER TABLESPACE undotbs1 ADD DATAFILE '/u01/app/oracle/oradata/ORCL/undotbs02.dbf' SIZE 500M AUTOEXTEND ON NEXT 100M MAXSIZE 2048M;
方法 3:创建新的 UNDO 表空间
创建新的 UNDO 表空间:
sqlCREATE UNDO TABLESPACE undotbs2 DATAFILE '/u01/app/oracle/oradata/ORCL/undotbs201.dbf' SIZE 1000M AUTOEXTEND ON NEXT 100M MAXSIZE 2048M;切换到新的 UNDO 表空间:
sqlALTER SYSTEM SET undo_tablespace = 'undotbs2' SCOPE=BOTH;删除旧的 UNDO 表空间:
sqlDROP TABLESPACE undotbs1 INCLUDING CONTENTS AND DATAFILES;
4. 归档日志空间不足的解决方案
方法 1:清理归档日志
使用 RMAN 清理归档日志:
sqlRMAN> DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-7';手动清理归档日志:
bashrm /archivelog/*.arc
方法 2:增加归档日志空间
添加新的归档日志目标:
sqlALTER SYSTEM SET log_archive_dest_2 = 'LOCATION=/new_archivelog' SCOPE=BOTH;扩展归档日志所在的文件系统:
- 使用 LVM 扩展文件系统
- 添加新的磁盘并挂载到归档日志目录
方法 3:调整归档日志保留策略
设置归档日志保留策略:
sqlCONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;启用归档日志自动删除:
sqlCONFIGURE ARCHIVELOG DELETION POLICY TO BACKED UP 1 TIMES TO 'DISK';
空间不足的预防措施
1. 监控空间使用情况
使用 Oracle Enterprise Manager:设置空间使用告警
使用自动监控脚本:
sql-- 检查表空间使用率 SELECT tablespace_name, ROUND((total_space - free_space) / total_space * 100, 2) AS used_percent FROM ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS total_space FROM dba_data_files GROUP BY tablespace_name ) t1, ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS free_space FROM dba_free_space GROUP BY tablespace_name ) t2 WHERE t1.tablespace_name = t2.tablespace_name AND (total_space - free_space) / total_space * 100 > 80;
2. 合理规划表空间
- 初始大小:设置合理的初始大小
- 自动扩展:启用自动扩展,但设置最大大小
- 多个数据文件:为大型表空间创建多个数据文件
- 数据文件分布:将数据文件分布在不同的磁盘上
3. 数据管理策略
- 分区表:使用分区表管理大型表
- 表压缩:启用表压缩减少存储空间
- 定期清理:定期清理不需要的数据
- 归档策略:建立数据归档策略
4. 空间使用审计
- 定期审计:定期审计表空间使用情况
- 识别增长趋势:分析数据增长趋势
- 预测空间需求:根据增长趋势预测未来空间需求
- 调整策略:根据审计结果调整空间管理策略
常见问题(FAQ)
Q1: 如何快速识别空间不足的表空间?
A1: 快速识别空间不足的表空间的方法:
使用 SQL 查询:
sqlSELECT tablespace_name, ROUND((total_space - free_space) / total_space * 100, 2) AS used_percent FROM ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS total_space FROM dba_data_files GROUP BY tablespace_name ) t1, ( SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS free_space FROM dba_free_space GROUP BY tablespace_name ) t2 WHERE t1.tablespace_name = t2.tablespace_name ORDER BY used_percent DESC FETCH FIRST 5 ROWS ONLY;使用 Oracle Enterprise Manager:查看表空间使用率仪表盘
Q2: 如何防止临时表空间不足?
A2: 防止临时表空间不足的方法:
- 合理设置临时表空间大小:根据查询需求设置合适的大小
- 多个临时文件:创建多个临时文件,分布在不同的磁盘上
- 监控临时表空间使用:设置临时表空间使用率告警
- 优化查询:减少需要大量临时空间的查询
- 使用适当的排序参数:调整 PGA 大小,减少临时表空间使用
Q3: 如何处理大量小表占用表空间的情况?
A3: 处理大量小表占用表空间的情况的方法:
- 使用分区表:将相关的小表合并为分区表
- 表压缩:启用表压缩减少存储空间
- 定期清理:清理不需要的小表
- 使用本地管理表空间:使用本地管理表空间减少字典管理开销
- 调整区大小:为小表设置合适的区大小
Q4: 如何预测未来的空间需求?
A4: 预测未来空间需求的方法:
分析历史增长趋势:
sql-- 分析表空间增长趋势 SELECT tablespace_name, AVG(growth_mb) AS avg_growth_mb_per_day FROM ( SELECT tablespace_name, (current_bytes - previous_bytes) / 1024 / 1024 AS growth_mb FROM ( SELECT tablespace_name, SUM(bytes) AS current_bytes, LAG(SUM(bytes)) OVER (PARTITION BY tablespace_name ORDER BY snap_id) AS previous_bytes FROM dba_hist_tbspc_space_usage GROUP BY tablespace_name, snap_id ) WHERE previous_bytes IS NOT NULL ) GROUP BY tablespace_name;使用 AWR 报告:分析表空间增长历史
建立预测模型:基于历史数据建立空间增长预测模型
Q5: 如何处理 LOB 段占用大量空间的情况?
A5: 处理 LOB 段占用大量空间的情况的方法:
使用 LOB 压缩:
sqlALTER TABLE owner.table_name MODIFY LOB (lob_column) (COMPRESS);重建 LOB 段:
sqlALTER TABLE owner.table_name MOVE LOB (lob_column) STORE AS (TABLESPACE lob_tablespace);清理不需要的 LOB 数据:
sqlDELETE FROM owner.table_name WHERE lob_column IS NULL; COMMIT;使用 SecureFiles:对于 Oracle 11g 及以上版本,使用 SecureFiles 存储 LOB 数据
Q6: 如何在不影响数据库运行的情况下清理表空间?
A6: 在不影响数据库运行的情况下清理表空间的方法:
使用分区表:删除旧的分区
在线重建表:
sqlALTER TABLE owner.table_name MOVE ONLINE;使用 DBMS_REDEFINITION:在线重定义表
分批清理:分批删除数据,避免长时间锁定
低峰期操作:在数据库低峰期进行清理操作
