分區表或分區索引的BLOCK_ID很大致使DATAFILE沒法RESIZE的解決方法

一 前言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操做隱藏着你可能不知道的祕密

相關文章
相關標籤/搜索