Ora-03297 hatası datafile resize etmeye çalışırken alınan bir hata
mesajıdır. Hatanın nasıl çözülebileceğine geçmeden önce bu hatayı neden
alındığı üzerine biraz duralım.
Database içerisinde daha önceden oluşturulmuş ve kullanılmış olan bazı
tabloların drop veya truncate edilmesinden dolayı datafile’ in kullanılan alanı
küçülmüş olabilir. Dba’ ler için yer sıkıntısı sanıyorum en fazla
karşılaştıkları sorunlardan biridir desek yanlış olmaz. Hata tam bu esnada, kullanılmayan alanın fiziksel olarak operating sisteme
geri kazandırılmaya çalışdığı esnada alınıyor. Şimdi bir örnek üzerinden
gidelim.
select a.file_name, a.file_id,
(a.bytes/1024/1024) toplam_mb,
(a.bytes/1024/1024) - (sum(b.bytes)/1024/1024) used_mb,
sum(b.bytes)/1024/1024 free_mb
from dba_data_files a, dba_free_space b
where a.file_id = b.file_id
and a.file_id = 11
group by a.file_name, a.file_id, a.bytes
FILE_NAME FILE_ID TOPLAM_MB USED_MB FREE_MB
/oradata/SET/set01.dbf 11 30000 11630,6875 18369,3125
Yukarıdaki script ile 11 nolu datafile’ imizin toplam 30 gb yeri olduğunu
ancak bunun sadece 11,6 gb’ ını kullandığını görüyoruz. Yapmak istediğimiz şu,
bu datafile’ dan kullanılmayan 18 gb geri alıp daha efektif olarak başka
yerlerde kullanmak.
Geri almaya çalışıyoruz;
alter database datafile
'/oradata/SET/set01.dbf' resize 12000M ;
==> alter database datafile
'/oradata/SET/set01.dbf' resize 12000M
alter database datafile
'/oradata/SET/set01.dbf' resize 12000M
Error at line 1
Ve hatamızı alıyoruz. Datafile’ ı resize etmekdeki kural, datafile
içerisinde allocate edilmiş olan blocklardan dolu olan en son bloğa kadar
resize edilebilir kuralına burada takılıyor olmamızdan kaynaklanıyor. Yani 18
gb boş yerimiz olabilir ama son dolu olan blok datafile’ in allocate ettiği
blocklardan sonların da yer aldığı için buraya kadar (18gb kadar) geri
çekmemize izin vermiyor.
Burada yapılacak olan şu, son dolu olan bloğu bir şekilde aralardaki boş
olan blockları kullandırıp çekebildiğimiz kadar geriye çekmek olacaktır.
Sonrasında resize işlemini tekrar deneyebiliriz. Bunun için yapılacak çeşitli yöntemler bulunmaktadır.
Burda birkaçını açıklayacağım ;
1) exp – imp yöntemi ;
Bu en kesin ve en kolay yöntemlerden biridir. Exp – imp datafile
içerisindeki yapılandırmayı arada block atlamadan yapıtığından dolayı
kazanılabilecek maxiumum alanı bu şekilde kazanabiliriz.
2) table shrink ;
Shrink yöntemi tabloların datafile içerisinde farklı blocklar iiçerisinde
allocate etmiş oldukları kısımları aradaki boşlukları atarak
yeniden reorganize ettiğinden dolayı yer kazanmak için kullanılabilecek bir
yöntemdir. Ancak çok büyük size’ ı tablolarda çokda başarılı olduğunu kendi
testlerime dayanarak söyleyebilirim. Tablo üzerinde shrink
yapmadan önce o tablonun datalarının taşınabilmesi için row movement opsiyonunu
enable yapmamız gerekiyor.
alter table test.test_table enable row movement;
alter table test.test_table shrink space;
Database içerisindeki bir tablespace’ e bağlı tüm tablolar için yapmak
isterseniz ;
select 'alter table ' ||owner|| '.' ||table_name|| ' enable row movement;' from dba_tables where tablespace_name = 'TEST_TABLESPACE' ;
select 'alter table ' ||owner|| '.' ||table_name|| ' shrink space ;' from dba_tables
where tablespace_name = 'TEST_TABLESPACE' ;
Sonrasında tekran disable yapmak için ;
select 'alter table ' ||owner|| '.' ||table_name|| ' disable row movement;' from dba_tables where tablespace_name = 'TEST_TABLESPACE' ;
scriptlerini kullanabilirsiniz.
3) table-index move ;
Tablo ve indexleri başka bir tablespace’ e taşımakda yer kazanmak için bir
çözüm olacak yöntemlerden biridir. Tabloları ve indexleri yeni bir tablespace
altına move edilmeside blockların tablolar tarafından sırayla allocate edilmesi
ve arada kullanılmayan block olmamasını önleyeceğinden işimizi
görecektir. Burada unutulmaması gereken tabloların move komutu
taşınmasından sonra indexler invalid durumuna düşeceğinden işlem bittikden
sonra mutlaka rebuild edilmesi gerektiğidir.
Bunun için aşağıdaki scriptlerden faydalanabiliriz ;
Tabloları taşımak için ;
select 'alter table ' ||owner|| '.' ||table_name|| ' move tablespace ‘TEST_TABLESPACE2’ ;' from dba_tables where
tablespace_name = 'TEST_TABLESPACE' ;
Lob segmentler için aşağıdaki scripti kullanabilirsiniz ;
select 'alter table ' || t.owner || '.' || t.table_name || ' move lob
('||column_name||') store as lobsegment (tablespace TEST_TABLESPACE2);'
from all_lobs l, dba_tables t
where l.owner=t.owner
and l.table_name = t.table_name
and l.SEGMENT_NAME in (
select segment_name
from dba_segments
where segment_type like 'LOBSEGMENT'
and tablespace_name = 'TEST_TABLESPACE')
order by t.owner, t.table_name;
İndexleri taşımak için ;
select 'alter index '
||owner|| '.' ||index_name|| ' move tablespace
"TEST_INDEX_TABLESPACE";' from
dba_indexes where tablespace_name =
'TEST_TABLESPACE' ;
İndexleri rebuild etmek için ;
select 'alter index ' ||owner|| '.' ||index_name|| ' rebuild online
parallel 8 nologging ;' from dba_indexes where status <>
'VALID'
Yukarıdaki işlemlerden sonra database’ deki datafile’ lerin en son nereye
kadar resize edileceğini görmek için ise ;
select 'alter database datafile '''||file_name||''' resize ' ||
ceil( (nvl(hwm,1)*8192)/1024/1024 ) || 'm;' cmd
from dba_data_files a,
( select file_id, max(block_id+blocks-1) hwm
from dba_extents
group by file_id ) b
where a.file_id = b.file_id(+)
and ceil( blocks*8192/1024/1024) -
ceil( (nvl(hwm,1)*8192)/1024/1024 ) > 0 ;
scripti kullanılabilir.
son olarak recyclebin' i unutmamak gerek. Hangi yöntemi kullanıyorsak kullanalım, işlem öncesinde recyclebin' i purge etmemiz gerekir.
purge dba_recyclebin;
Sonrasında hata almadan resize işlemini yapabildiğinizi göreceksiniz.
Hiç yorum yok:
Yorum Gönder