一 前言web
最近发现磁盘空间有3T的性能机器出现了磁盘空间不足的现象,该机器主要部署ORACLE数据库,因此,猜想极可能是表空间数据文件变动致使的。接下来,就须要一步步的排查问题了,最终确认是ORACLE BLOCK_ID惹的祸。数据库
二 定位磁盘空间占用状况app
首先须要肯定是哪些文件占用空间,使用du -sh * ,果不其然,有个表空间增长了20个数据文件,并且每一个数据文件设置30G,Word天,谁这么狠,竟然找不到元凶,好吧,那我就职意处置了,不能影响后面的性能测试。ide
三 删除数据文件性能
既然发现这么多数据文件,固然想直接drop掉,因而,不觉得然的执行alter tablespace TEST drop datafile '/oradata/dat20.dbf';先把最后一个干掉,结果执行报错“ORA-03262: THE FILE IS NON-EMPTY”,呵,竟然有数据,直接删不掉。因而,就想查询这个表空间的表,把数据TRUNCATE掉,但又考虑到该表空间TABLE就有上千张,并且不能肯定哪张表可删,不能太鲁莽,事实证实,真和数据无关。测试
四 退而求其次-RESIZE 数据文件释放空间spa
既然不能drop 数据文件,那就resize它,就不信拿不回空间。因而,先查下能够释放多少空间出来,先执行以下命令:blog
select d.file_name,d.file_id,d.bytes/1024/1024 as d_byte,sum(f.bytes/1024/1024) as free_byte 索引
from dba_data_files d,dba_free_space f 部署
where d.file_id=f.file_id and d.file_id=67
group by d.file_name,d.file_id,d.bytes/1024/1024;
输出显示67号数据文件可用空间29.9G,看到这里,内心暗骂,是谁这么不靠谱,乱加乱设数据文件。不过,都是小问题,resize成1G就好了。因而,又兴冲冲的赶忙执行ALTER DATABASE DATAFILE '/oradata/hisdat20.dbf' RESIZE 1G; 竟然又报错了,
“ORA-03297:file contains used data beyond requested RESIZE value”,看到这个报错,开始意识到可能问题没有这么简单。
五 shrink space下降高水位
既然实际数据不多,resize却不能成功,就代表是某些数据块位于数据文件的末端,那就先降降HWM高水位,对表空间的表进行操做,主要命令以下:
alter table test_table enable row movement;
alter table test_table shrink space; ---下降高水位,释放空间
alter table test_table disable row movement;
固然,这样一个个的执行不显示,须要批量执行,命令以下:
SELECT DISTINCT 'alter table ' || segment_name || ' enable row movement;'||
'alter table ' || segment_name || ' shrink space;'||
'alter table ' || segment_name || ' disable row movement;'
FROM dba_extents
WHERE tablespace_name = 'TEST'
AND segment_type = 'TABLE'
下降HWM后,再次执行RESIZE操做,报错依旧,好吧,既然这样都没搞定,须要认真研究下了。
六 找到真凶和解决方法
经过上述尝试,发现数据文件可用空间充足,但对ORACLE而言,数据文件使用了30G,因此RESIZE到1G会报错失败,尽快进行了降高水位或TRUNCATE操做都无济于事。因而,排查和解决思路是这样的:
1)查询数据文件的最大BLOCK_ID
select max(block_id) from dba_extents where file_id=67;
2)肯定该BLOCK_ID与哪一个表或索引有关
SELECT OWNER, SEGMENT_NAME, SEGMENT_TYPE, TABLESPACE_NAME, A.PARTITION_NAME FROM DBA_EXTENTS A WHERE FILE_ID = 67 AND block_id = 3839929;
查询后,发现最大的BLOCK_ID都是与分区表或分区索引有关的。
3)针对最大BLOCK_ID出如今分区表的处理方法
对分区表出现最大BLOCK_ID的状况,采用先降分区表高水位,而后MOVE表空间,命令以下:
alter table TEST_TABLE MODIFY PARTITION P101101 shrink space;---注意下降高水位并不能下降数据文件中block_id大小
alter table TEST_TABLE move partition P101101 tablespace TEST;---move操做数据移动表空间最前面的空闲block,注意须要重建索引
4)针对最大BLOCK_ID出如今索引分区的处理方法
对索引分区出现最大BLOCK_ID的状况,重建分区索引便可,命令以下:
ALTER INDEX IDX_TEST_TABLE REBUILD PARTITION P201201
5)处理完后,再次执行RESIZE操做,数据文件大小修改为功。
最后,由于同个文件号上可能出现多个分区表,分区索引须要处理的状况,建议像第五步写成批量执行,提升效率。
关于shrink space下降高水位,能够参考博文Oracle delete操做隐藏着你可能不知道的秘密