ORA-30036: unable to extend segment by 8 in undo tablespace

Zaman zaman database’ de tablolara yüklü miktarda insert işlemleri olur. Özellikle bahsettiğimiz bir raporlama database’  ise bu işlem kaçınılmaz olur ve yapılan işlemin boyutu undo tablespace’ inizin boyutundan fazla olduğunda (undo tbs autoextend olmadığını varsayarsak)   “ORA-30036: unable to extend segment by 8 in undo tablespace ‘UNDOTBS2’  hatasını almanız kaçınılmaz olacaktır.  Ora-30036 hatasının önüne geçmek için yapılan insert işlemini parçalamak ve daha ufak bölümlerde yapmak sizin için kaçınılmaz bir çözüm olacaktır. Bu işlemi de yaparken tablo içerisindeki bir alana göre bir den fazla where conditionı ile sorgu yazmak yerine tek sorgu ile ama belirli sayıda data üzerinde sırayla işlem yaparak undo’ ya fazla yüklenmeden tabiri caizse patlatmadan işleminizi gerçekleştirebilirsiniz. Örnek olması açısından şöyle bir bilgi verebilirim, raporlama database’ lerimizden birinde yer alan 54 gb bir datayı farklı bir schema altına aşağıdaki script ile yaklaşık 1 saat gibi bir sürede taşımıştım. (Aşağıda belirtmiş olduğum tuning yöntemlerinden hiçbirini kullanmadan) Tabi bu süreyi etkileyen diğer faktörleride göz önünde bulundurmak lazım. (işlemin yapıldığı andaki database deki yoğunluk, kullanılan server’ ın kapasitesi, taşınan tablespace’ lere ait dbf’ ler üzerindeki o anki i/o durumu vs.)

Aşağıdaki scripti çalıştırmadan önce hangi tabloyu taşıtacak iseniz o tablonun DDL’ ini taşıyacağınız ortamda öncelikle çalıştırıp tabloyu boş olarak oluşturuyorsunuz.  Sonrasında scriptin içerisindeki select ve insert kısımlarını bir sefere mahsus düzenlemeniz yeterli olacaktır.

DECLARE
   v_time   NUMBER;
BEGIN
   DBMS_OUTPUT.put_line (‘Started’);
   v_time := DBMS_UTILITY.get_time;
   FOR r IN (SELECT ROWNUM, mesaj_no, islem_kodu, atm_kodu, kart_no,
                    son_kul_tar, mesaj_date, mesaj_time, stan, responce,
                    responce_detay, mesaj, tarih, saat
               FROM atm_mesaj_log)
   LOOP
      INSERT INTO atm_mesaj_log_hist
                  (mesaj_no, islem_kodu, atm_kodu, kart_no,
                   son_kul_tar, mesaj_date, mesaj_time, stan,
                   responce, responce_detay, mesaj, tarih, saat
                  )
           VALUES (r.mesaj_no, r.islem_kodu, r.atm_kodu, r.kart_no,
                   r.son_kul_tar, r.mesaj_date, r.mesaj_time, r.stan,
                   r.responce, r.responce_detay, r.mesaj, r.tarih, r.saat
                  );
      IF (MOD (r.ROWNUM, 50000) = 0)
      THEN
         BEGIN
            COMMIT;
            DBMS_OUTPUT.put_line (‘commit executed’);
         END;
      END IF;
   END LOOP;
   DBMS_OUTPUT.put_line (   ‘time used: ‘
                         || (DBMS_UTILITY.get_time – v_time) / 100
                         || ‘ secs’
                        );
   DBMS_OUTPUT.put_line (‘Finished’);
   COMMIT;
END;
/

Scripte yer alan “IF (MOD (r.ROWNUM, 50000) = 0)”  bu kısım kaç satırda bir commit işlemini gerçektireceğini belirttiğiniz kısımdır. Bu sayede milyonlarca kaydı bir seferde insert etmek yerine parça parça hata almadan (ki unutmayın database üzerinde çalışan tek kişi siz değilsiniz J) işleminizi tamamlayabilirsiniz.

Son ve önemli bir not, yukarıdaki script ile işleminize hız katmak istiyorsanız, aşağıdaki ufak tuning bilgileri işleminizi  son derece kısaltacaktır.

–          tablo üzerinde varsa indexleri aktarım öncesinde yaratmayın, insert işleminiz bittiksen sonra create edebilirsiniz.

–          İnsert scriptine /*+ Append */ hintini mutlaka verin.

–          Database’ iniz archive modda ama force logging modda değilse  tablonun logging type’ ını işlem öncesinde NOLOGGING’ e alırsanız, işlem sırasında redoya hiçbir kayıt atmayacağından çok daha hızlı çalışacaktır. (işlem bittikden sonra tekrar logging moda alabilirsiniz.

Yukarıdaki scripti ve belirttiğim tuning metotlarını kullanarak benzer bir işlem yapan olursa deneyimlerini paylaşırsa bunuda burdan tüm arkadaşlara duyurmuş oluruz.  En azından gerçekçi bir takım veriler üzerinden konuşuyor oluruz.

Be Sociable, Share!

3 comments

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir


+ dört = 6