Tablespace İçerisindeki Objelerin Taşınması

Tablespace içerisinden büyük objelerin silinmesi durumunda disk üzerinde alan kazanımı olmadığı için tablespace’i recreate etme yoluna gidebiliriz. Bu durumda diskten alan kazanmanın yanında tablespace içerisinde bulunan objeler defragmente olup db üzerinde performans artışlarını beraberinde getirecektir. Tablespaceyi recreate etmenin aşamaları şu şekildedir:

  1. Yeni tablespace create etmek (bundan sonra TS_DATA_NEW olarak adlandırılacaktır)
  2. default_tablespace’i TS_DATA olan schemaların alter edilmesi ve gerekli quota ayarlarının yapılması.
  3. Varolan tablespace (TS_DATA olarak adlandırılacaktır) içerisindeki tüm objelerin move edilmesi.
    1. Tablo partition ve subpartitionların taşınması
    2. Lobların taşınması
    3. Lob partitionların taşınması
    4. İndexlerin taşınması
    5. Partitionlu indexlerin taşınması
  4. TS_DATA’yı offline konumuna almak
  5. Gerekli olması durumunda modify default attributes yapmak
  6. TS_DATA’yı drop etmek
  7. TS_DATA_NEW’i rename edip TS_DATA olarak değiştirmek.
  8. İndexlerin kontrolü

1. Create Tablespace

Yeni oluşturulacak TS_DATA_NEW tablespace için örnek komut aşağıdaki gibidir. Tabiki varolan tablespace üzerinde tanımlanan kota, yetki v.s gibi yetkilerin de varolan tablespace den alınıp yeni oluşturulan tablespaceye tanımlanması gerekmektedir. Aksi halde objeler taşındıktan sonra yetki problemleri nedeniyle başka sorunlara sebebiyet verebiliriz.

CREATE TABLESPACE TS_DATA_NEW 
DATAFILE '+DATA'
SIZE 31G;

2. Default Tablespace Değiştirmek

Default tablespacesi TS_DATA olarak ayarlanmış kullanıcıların yeni tablespace tanımını ayarlamak için aşağıdaki komutu kullanabilirsiniz.

SELECT username,default_tablespace,'alter user '||username||' default tablespace TS_DATA_NEW;
alter user '||username||' quota unlimited on TS_DATA_NEW;'
FROM dba_users
WHERE default_tablespace='TS_DATA';

3. Objelerin Taşınması

Varolan tablespace (TS_DATA) içerisindeki tüm objeler yeni tablespace içerisine taşınacaktır.

3.1. Tablo Partitionların Taşınması

Tablo partition ve sub partitionların taşınması için örnek komutaşağıdaki şekildedir. Burada klasik yöntem ile taşınacaktır. Sistemin kesintiye uğramaması için redef gibi taşıma yöntemlerini de tercih edebilirsiniz.

select 'ALTER TABLE '||table_owner||'.'||table_name||'  MOVE PARTITION '||partition_name||' TABLESPACE TS_DATA_NEW parallel 8;'
from dba_tab_partitions
where tablespace_name = 'TS_DATA';

Subpartitionların taşınması aşağıdaki şekilde gerçekleştirilebilir.

select 'ALTER TABLE '||table_owner||'.'||table_name||'  MOVE SUBPARTITION '||subpartition_name||' TABLESPACE TS_DATA_NEW parallel 8;' 
from dba_tab_subpartitions
where tablespace_name = 'TS_DATA';

3.2. Lob ve Lobparitionların Taşınması

Loblar aşağıdaki şekilde taşınabilir.

SELECT owner,table_name,COLUMN_NAME,SEGMENT_NAME,TABLESPACE_NAME, 'alter table '||owner||'.'||table_name||' move lob ('||COLUMN_NAME||') store as '||SEGMENT_NAME||' (tablespace TS_DATA_NEW);'
from dba_lobs
where tablespace_name ='TS_DATA';

Lob partitionlar aşağıdaki şekilde taşınabilir.

SELECT 'alter table ' || TABLE_OWNER || '.' || TABLE_NAME || ' move partition ' || partition_name || ' lob (' || COLUMN_NAME || ') store as  (tablespace TS_DATA_NEW);' 
FROM DBA_LOB_PARTITIONS
WHERE TABLESPACE_NAME = 'TS_DATA' ;

3.3. İndexlerin Taşınması

İndexler aşağıdaki şekilde taşınabilir.

select distinct 'ALTER INDEX '||owner||'.'||index_name||' REBUILD ONLINE TABLESPACE TS_DATA_NEW PARALLEL 16; ALTER INDEX '||owner||'.'||index_name||' NOPARALLEL;' 
from dba_indexes
where tablespace_name = 'TS_DATA';

İndex partitionlar aşağıdaki şekilde taşınabilir.

select 'ALTER INDEX '||index_owner||'.'||index_name||' REBUILD PARTITION '||partition_name||' TABLESPACE TS_DATA_NEW
ONLINE PARALLEL 16; ALTER INDEX '||index_owner||'.'||index_name||' NOPARALLEL;'
from dba_ind_partitions
where tablespace_name = 'TS_DATA';

3.4. Objeleri Otomatik Taşımak için Script

Yukarıdaki taşıma adımlarını teker teker yapmak yerine aşağıdaki komutu kullanıp tablespace içerisindeki tüm objeleri sırası ile taşıyabilirsiniz. Bu komut size taşınacak objelerin scriptini öncelik sırasına göre verecektir.

SELECT *
     FROM (SELECT 0 sira,
                  owner,
                  table_name,
                     'alter table ' || owner || '.' || table_name || ' modify default attributes tablespace  TBS_EXISTING ;'    move_sql
             FROM dba_part_tables
            WHERE DEF_TABLESPACE_NAME = '&&tbsname'
           UNION ALL
           SELECT 1 sira,
                  owner,
                  table_name,
                     'alter index ' || owner || '.' || index_name || ' modify default attributes tablespace  TBS_EXISTING ;'    move_sql
             FROM dba_part_indexes
            WHERE DEF_TABLESPACE_NAME = '&&tbsname'
           UNION ALL
           SELECT 2 sira,
                  owner,
                  table_name,
                     'ALTER TABLE ' || owner || '.' || table_name || '  MOVE TABLESPACE  TBS_EXISTING parallel 8;'    move_sql
             FROM dba_tables
            WHERE tablespace_name = '&&tbsname'
           UNION ALL
           SELECT 3 sira,
                  table_owner                                   owner,
                  table_name,
                     'ALTER TABLE ' || table_owner || '.' || table_name || '  MOVE PARTITION ' || partition_name || ' TABLESPACE  TBS_EXISTING parallel 8;'    move_sql
             FROM dba_tab_partitions
            WHERE tablespace_name = '&&tbsname'
           UNION ALL
           SELECT 4 sira,
                  owner,
                  table_name,
                     'alter table ' || owner || '.' || table_name || ' move lob (' || COLUMN_NAME || ') store as ' || SEGMENT_NAME || ' (tablespace  TBS_EXISTING );'    move_sql
             FROM dba_lobs
            WHERE tablespace_name = '&&tbsname'
           UNION ALL
           SELECT 5 sira,
                  owner,
                  table_name,
                     'ALTER INDEX ' || owner || '.' || index_name || ' REBUILD TABLESPACE  TBS_EXISTING PARALLEL 16;
  ALTER INDEX ' || owner  || '.' || index_name || ' NOPARALLEL;'    move_sql
             FROM dba_indexes
            WHERE tablespace_name = '&&tbsname'
           UNION ALL
           SELECT 6 sira,
                  i.owner,
                  i.table_name,
                     'ALTER INDEX ' || p.index_owner || '.' || p.index_name || ' REBUILD PARTITION ' || p.partition_name || ' TABLESPACE  TBS_EXISTING PARALLEL 16;
  ALTER INDEX ' || p.index_owner || '.' || p.index_name || ' NOPARALLEL;'
             FROM dba_ind_partitions p, dba_indexes i
            WHERE     p.tablespace_name = '&&tbsname'
                  AND p.index_owner = i.OWNER
                  AND p.index_name = i.index_name) aa
 ORDER BY 2, 3, 1;

4. Tablespace’nin Offline Duruma Getirilmesi

Aşağıdaki şekilde TS_DATA’yı offline konuma getirebiliriz. Burada normal şeçeneğini kullanmak mantıklı olabilir. Çünkü tablespace içerisinde unutulan bir obje olduğu durumlarda uyarı verecektir.

ALTER TABLESPACE TS_DATA OFFLINE NORMAL/IMMEDIATE;

5. Modify Default Attribute

Varolan TS_DATA tablespace’i drop ettikten sonra dba_part_tables ve dba_part_indexes viewlerinden taşınan objelerin ownerleri altında bulunan objelerin kontrolünün yapılması gerekmektedir. Tablespace drop edildikten sonra bu viewlerin içerisinde bulunan DEF_TABLESPACE_NAME kolonunda bulunan değerlerin bazınlar veya bir çoğu “_$deleted$25$3” gibi bir değere dönebilir.

Bunun bu şekilde değişmesinin nedeni partitionlu tablo ve indexlerin move edilmesi sonucunda metadata diyebileceğimiz adresin değişmemesinden kaynaklanmaktadır. Buradan bu kayıtları bulup aşağıdaki şekilde alter edilmesi gerekmektedir. Aksi halde insert gibi transactionlarda “ORA-00959: tablespace ‘_$deleted$25$3’ does not exist” gibi hatalar alabilirsiniz.

alter index SCHEMA.INDEX_NAME modify default attributes tablespace TBS_EXISTING;

alter table SCHEMA.TABLE_NAME modify default attributes tablespace TBS_EXISTING;

6. Drop Tablespace

Varolan tablespace aşağıdaki şekilde drop edilebilir.

DROP TABLESPACE TS_DATA INCLUDING CONTENTS AND DATAFILES;

7. Rename Tablespace

Varolan tablespace aşağıdaki şekilde rename edilebilir. Oracle’nin rename tablespace komutunu 11g ve üzeri sürümlerde desteklediğini unutmamak gerekir.

ALTER TABLESPACE TS_DATA_NEW RENAME TO TS_DATA;

Bunun çalıştırılmasının ardından 2. aşamada değiştirdiğimiz default tablespace değeri de otomatik değişecektir. Yine de her ihtimale karşı dba_users view’inden kontrol edilmesi daha sağlıklı olacaktır.

8. İndexlerin Kontrolü

Son olarak indexlerin kontrolünü yapmak gerekiyor. Aşağıdaki şekilde yapılabilir.

select  * from dba_indexes where tablespace_name = 'TS_DATA' and status <> 'USABLE'; 

select * from dba_ind_partitions where tablespace_name = 'TS_DATA' and status <> 'USABLE';