縮小表空間文件,節省磁盤

分類:IT技術 時間:2016-10-07

在我管的系統中,數據庫磁盤經常只剩下20G左右,以前是刪除數據庫服務器中的日誌,日誌做了定時清理之後,發現表空間經常出現表空間不足的情況,每次都是通過擴充表空間來解決問題,但是加了幾次之後,服務器的磁盤不夠用了,就開始清理數據庫中的數據。清理了數據之後,發現表空間實際占用率很小,用不到那麽多的磁盤,於是想到把用到的磁盤釋放出來。

    在處理的過程中,發現truncate表只能夠減小表空間占用率,並不能釋放磁盤通過請教別人,了解到有下面方法可以釋放磁盤。

方法一:

查看表空間對應的數據文件大小

select FILE_NAME,FILE_ID,TABLESPACE_NAME,BYTES/1024/1024 mb,BLOCKS from dba_data_files where 


TABLESPACE_NAME='TFR_DATA';

查看數據文件中數據處在最大位置

select max(block_id) from dba_extents where file_id=9;

計算表空間實際需要多大空間

select 1354880*8/1024 from dual;

設置表空間大小為該值

ALTER database DATAFILE '/u01/oradata/FOSSDB/datafile/o1_mf_tfr_data_9ymk9p5n_.dbf' RESIZE 10600M;

這種方法在我之前的文章中寫到過。這種方法也是有缺陷的,表空間中實際沒有很多數據,例如只有100M數據,但是這種方法resize的時候,發現只能夠resize到10G左右,並沒有釋放出很大的空間。

方法二:

縮小數據文件尺寸報ORA-03297的處理辦法 

ORA-03297: 文件包含在請求的 RESIZE 值以外使用的數據

 

最近歷史數據庫磁盤空間不足,而有一個表空間有50個G容量,但是實際只占100m的空間,

使用ALTER TABLE table SHRINK SPACE CASCAD後大部分數據文件可以調整,當試圖調整其中一個數據文件尺寸的時候報

RA-03297: file contains used data beyond requested RESIZE value

說明這個文件不能通過降低hwm來釋放空間了。******************************************

數據庫版本:Oracle 10.2.1

--找到數據文件對應的文件號*********

SQL>select file#,name from v$datafile where name like '%BASEINFO.dbf';

5                  /data/eucpdb/eucpdb/BASEINFO.dbf

找到文件中最大的塊號

SQL>select max(block_id) from dba_extents where file_id=5 ;************************

1213833

--查看數據庫塊大小

SQL>show parameter db_block_size

db_block_size integer 8192

計算一下文件中最大使用塊占用的位置

SQL>select 1213833*8/1024 from dual;

9483.0703125 M

--為了驗證上面做法的準確性,下面做一個試驗                      

--調整前數據文件大小為10000M

--現在調整數據庫文件為9500M

SQL>ALTER DATABASE DATAFILE '/data/eucpdb/eucpdb/BASEINFO.dbf' RESIZE 9500M

  2  /

數據庫已更改

--調整文件為 9400m

SQL>ALTER DATABASE DATAFILE '/data/eucpdb/eucpdb/BASEINFO.dbf' RESIZE 9400M

  2  /

SQL> ALTER DATABASE DATAFILE '/data/eucpdb/eucpdb/BASEINFO.dbf' RESIZE 9400M;

ALTER DATABASE DATAFILE '/data/eucpdb/eucpdb/BASEINFO.dbf' RESIZE 9400M

*

第 1 行出現錯誤:

ORA-03297: 文件包含在請求的 RESIZE 值以外使用的數據

--看來了上面的計算是準確的

解決方法

查看表空間中有哪些對象

select * from DBA_SEGMENTS where WHERE TABLESPACE_NAME='BASEINFO';

select * from DBA_tables;

select FILE_NAME,FILE_ID,TABLESPACE_NAME,BYTES/1024/1024 mb,BLOCKS from dba_data_files where 


TABLESPACE_NAME='TFR_DATA';

查看FILE_ID

  

SQL> select segment_name,segment_type,tablespace_name,extent_id,bytes,blocks from dba_extents where file_id=5 and   block_id='1213833';

SEGMENT_NAME                   SEGMENT_TYPE       TABLESPACE_NAME                 EXTENT_ID      BYTES     BLOCKS

------------------------------ ------------------ ------------------------------ ---------- ---------- ----------

REGISTRYINFO                   TABLE              BASEINFO                               25     524288         64

SQL>

SQL>  ALTER TABLE eucpmanager.REGISTRYINFO SHRINK SPACE CASCADE;

表已更改。

創建一個新的表空間,把block_id比較高的幾個表移出表空間

SQL> CREATE SMALLFILE TABLESPACE "BASEINFO_BAK" DATAFILE '/data/eucpdb/eucpdb/baseinfo_bak.dbf' SIZE 100M LOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO

  2  /

表空間已創建。

SQL> alter user eucpmanager quota unlimited on BASEINFO_BAK;

用戶已更改。使得數據庫中表的所屬用戶能夠操作新建的表空間。否則不能把表移到新的表空間中

把block_id比較高的幾個表移動到新的表空間

SELECT DISTINCT SEGMENT_NAME FROM DBA_EXTENTS WHERE TABLESPACE_NAME='BASEINFO' AND FILE_ID=5  and segment_type='TABLE' ;

SQL> SELECT distinct  'alter table '|| SEGMENT_NAME||' move tablespace baseinfo_bak; ' FROM DBA_EXTENTS WHERE TABLESPACE_NAME='BASEINFO' AND FILE_ID=5  and segment_type='TABLE' ;

'ALTERTABLE'||SEGMENT_NAME||'MOVETABLESPACEBASEINFO_BAK;'

----------------------------------------------------------------------------------------------------------------------------

alter table ENTERPRISESERVICEINFO move tablespace baseinfo_bak;

alter table REGISTRYFEEDETAILEX move tablespace baseinfo_bak;

alter table ENTERPRISEROUTE move tablespace baseinfo_bak;

alter table REGISTRYAUTHINFO move tablespace baseinfo_bak;

alter table ENTERPRISEBASEINFO move tablespace baseinfo_bak;

SQL> alter table ENTERPRISESERVICEINFO move tablespace baseinfo_bak;

alter table REGISTRYFEEDETAILEX move tablespace baseinfo_bak;

alter table ENTERPRISEROUTE move tablespace baseinfo_bak;

alter table REGISTRYAUTHINFO move tablespace baseinfo_bak;

alter table ENTERPRISEBASEINFO move tablespace baseinfo_bak;

表已更改。

SQL>

表已更改。

SQL>

表已更改。

SQL>

表已更改。

告警日誌中會出現下面的內容,索引需要重建

Thu Apr 24 14:20:21 2008

Some indexes or index [sub]partitions of table EUCPMANAGER.ENTERPRISEBASEINFO have been marked unusable

把下面的執行結果的語句執行所有重建

 SELECT distinct  'alter INDEX '|| SEGMENT_NAME||' REBUILD TABLESPACE BASEINFO_BAK; ' FROM DBA_EXTENTS WHERE TABLESPACE_NAME='BASEINFO' AND FILE_ID=5  and segment_type='INDEX' ;

 

 

 alter INDEX PK_ENTERPRISEBASEINFO REBUILD TABLESPACE BASEINFO_BAK;

alter INDEX PK_REGISTRYINFO REBUILD TABLESPACE BASEINFO_BAK;

alter INDEX PK_REGISTRYFEEDETAILEX REBUILD TABLESPACE BASEINFO_BAK;

alter INDEX UNI_REGISTRYAUTHINFO REBUILD TABLESPACE BASEINFO_BAK;

alter INDEX UNI_REGISTRYAUTHINFO REBUILD TABLESPACE BASEINFO_BAK;

alter INDEX UNI_REGISTRYAUTHINFO REBUILD TABLESPACE BASEINFO_BAK;

alter INDEX UNI_REGISTRYAUTHINFO REBUILD TABLESPACE BASEINFO_BAK;

alter INDEX UNI_REGISTRYAUTHINFO REBUILD TABLESPACE BASEINFO_BAK;

再次修改數據文件大小

SQL>  select max(block_id) from dba_extents where file_id=5 ;

MAX(BLOCK_ID)

-------------

         3209

SQL> ALTER DATABASE DATAFILE '/data/eucpdb/eucpdb/BASEINFO.dbf' RESIZE 1000m;

數據庫已更改。

數據庫文件的空間已經調整成功了

SQL>

--把挪走的表在挪回來

SQL> alter table ENTERPRISESERVICEINFO move tablespace baseinfo;

alter table REGISTRYFEEDETAILEX move tablespace baseinfo;

alter table ENTERPRISEROUTE move tablespace baseinfo;

alter table REGISTRYAUTHINFO move tablespace baseinfo;

alter table ENTERPRISEBASEINFO move tablespace baseinfo;

alter table registryinfo move tablespace baseinfo;

表已更改。

SQL>

表已更改。

--重建索引

SQL>

SQL>

SQL> ALTER INDEX PK_REGISTRYINFO REBUILD TABLESPACE BASEINFO;

ALTER INDEX AK_REGISTRYCODE_REGISTRYINFO REBUILD TABLESPACE BASEINFO;

ALTER INDEX PK_ENTERPRISEBASEINFO REBUILD TABLESPACE BASEINFO;

ALTER INDEX PK_ENTERPRISESERVICEINFO REBUILD TABLESPACE BASEINFO;

ALTER INDEX UNI_REGISTRYAUTHINFO REBUILD TABLESPACE BASEINFO;

ALTER INDEX PK_REGISTRYFEEDETAILEX REBUILD TABLESPACE BASEINFO;

索引已更改。

SQL> SELECT COUNT(*) FROM DBA_SEGMENTS WHERE TABLESPACE_NAME='BASEINFO_BAK' ;

  COUNT(*)

----------

         0

已經沒有對象在新建的這個表空間了。現在刪除掉

SQL> drop tablespace baseinfo_bak;

表空間已刪除。

到此調整已經結束了。

其實調整方法有很多,如用imp/exp等


Tags:

文章來源:


ads
ads

相關文章
ads

相關文章

ad