29 Mayıs 2010 Cumartesi

Flashback Query!

Merhabalar,


Benim izlenimlerim arasında bir Oracle özelliği var ki; gerçekten şimdiye kadar geliştirilmiş en güzel Oracle veritabanı özelliği olduğunu düşünüyorum. Bir RAC ya da Data Guard gibi veya ASM gibi ileri düzey ve sistem seviyesinde de çalışmakta olan bir özellik değil ancak hayat kurtarabiliyor. Bu arkadaşımızın adı ise "Flashback". Bu konuyla ilgili daha önce de yazı yazmıştım ve "Flashback Database" komutu ile veritabanını bir yedekleme sistemi kullanmadan nasıl eski tarihe döndürebiliriz onu açıklamıştım.

Öncelikle birkaç örnek vermek istiyorum;

Bir kullanıcınız var ve aktif olarak sorgu çalıştırıyor, tablolara erişip veri siliyor, tablo yaratıyor, paket yaratıyor ya da değiştiriyor. Bunları yaparken de bir tabloda silmemesi gereken bir veriyi, bir arayüz ya da yazdığı sorgu aracılığı ile siliyor ve commit gönderiyor. Geçmiş olsun mu demek lazım ya da soğuk su mu ikram etmek lazım? Cevap, hiçbiri çünkü undo tablespace'in segment'lerinde bundan önceki tablonun şekli de tutuluyor! Bu noktada bir hatırlatma, Flashback bir 10g özelliğidir.

Kullanıcının yapması gereken veritabanı yöneticisi olan kişiye durumu acil bildirecek. İlk yapması gereken budur. Çünkü bu tablodan silinen kayıtların da undo'larda tutulduğu bir süre bulunuyor. Bu süreyi de undo_retention parametresi, saniye türünden belirliyor. Bu parametreyi ne kadar uzun tutarsanız o kadar geriye dönebilir ve görmek istediğiniz verileri görebilirsiniz. Yüksek tutarsanız alandan kaybedersiniz, düşük tutarsanız da geriye dönebildiğiniz zaman aralığı azalır. Bu noktada tercih merkezi veritabanı yöneticisidir.

Kullanım yöntemi ve şeklini ise birkaç örnekle göstermem gerekirse;

SQL> select * from tablo_adi as of timestamp sysdate-3/24; (3 saat önceki tablonuz).

SQL> select * from tablo_adi as of scn scn_sayisi (belirtilen scn'deki tablonuz).

Insert ya da update komutları ile de alt sorgu mahiyetinde de kullanabilirsiniz. Bu noktada PK ya da FK varsa dikkat edilmeli.

Flashback query undo segment'lerini kullanmaktayken rollback komutu ise system segment'lerini kullanıyor. Bu farkı da unutmamak gerekir.

İyi çalışmalar,

Ogan

27 Mayıs 2010 Perşembe

ORA-10631: SHRINK clause should not be specified for this object

Selamlar,

Başlıktan da anlaşılabileceği üzere ORA-10631 hatası üzerine çok kısa yorum yazacağım. 2005 yılında 9i ile tanıştığım zamandan bu yana bu hata ile karşılaşmamıştım. Halbuki çok fazla sayıda shrink komutu koşmuşluğum var.

Geçtiğimiz günlerde Oracle Forumlarını okurken bir okurun sorusuna shrink komutunun kullanması gerektiğini söylerek cevap vermiştim. Ancak başlıktaki hatayı aldığını söyledi ve çok ilginç bir neden çıktı arkasından...

Kullanıcı, tabloyu yaratırken FUNCTION BASED INDEX yaratmış. Function based index'in yapısından dolayı shrink space ya da shrink space compact komutları çalışmıyor ancak tablo üzerinde enable row movement komutu koşturulabiliyor! Bu durumda yapılabilecek en mantıklı çözüm yolu da indeksi kaldırıp yeniden yaratmak. Yeniden yaratmadan önce de High Water Mark'ı sıfırlayabilmek için shrink space komutunu göndermek. Bu noktada eklemem gerekiyor ki eğer tablodaki HWM sıfırlandıktan sonra tahsis ettiği alanları da boşaltmak isterseniz shrink space compact göndermeniz gerekiyor. Yalnız unutmamak gerekiyor ki compact ile birlikte tablo kilitlenecek, erişileyemecek ve clustering factor artacaktır. Aynı zamanda rowid üzerinde oluşturulmuş trigger'lar da geçersiz kılınacaktır.

Yukarıda sözü geçen sorguları aşağıda bulabilirsiniz;

alter table enable row movement;
alter table disable row movement;
alter table shrink space;
alter table shrink space compact;

24 Mayıs 2010 Pazartesi

Deallocate Edilemeyen Datafile

Merhaba,

Unix tabanlı işletim sistemlerinde karşılaşılabilecek bir ufak hata ile ilgili çözüm sunmak istiyorum.

Oracle veritabanınızda bir datafile'ın fiziksel olarak yerini değiştirmek istiyorsunuz ve yapmanız gerekenleri de biliyorsunuz ya da bilmiyorsunuz. Ben aşağıda bu listeyi tekrar hatırlatmak istiyorum;

İlk önce veritabanının fiziksel parçası olan datafile'ın bulunduğu tablespace'i buluyorsunuz;

SQL> select a.name tablespace, b.file#, b.name datafile
from v$tablespace a, v$datafile b
where a.ts#=b.ts#
and b.name = '/usr/db/data01.dbf';

Karşınızdaki listede yerini değiştirmek istediğiniz datafile'ın hangi tablespace'de olduğunu gördünüz. Şimdi ise önce tablespace'i offline konumuna getirerek, datafile'ın fiziksel olarak taşınması işlemine başlayabilirsiniz;

SQL> alter tablespace TS_1 offline normal;

Bu aşamada fiziksel olarak datafile'ın taşınmasını gerçekleştirebilirsiz (unix'te mv yerine cp komutunu koşmanız daha yararlı olacaktır;

# cp /usr/db/data01.dbf /usr/db_1/data01.dbf

Ardından datafile'ın adının değiştiğini Oracle'a iletmemiz gerekiyor;

SQL> alter datafile '/usr/db/data01.dbf' rename '/usr/db_1/data01.dbf';

Son olarak tablespace'i online durumuna getiriyoruz;

SQL> alter tablespace TS_1 online;

Bu aşamalardan geçtiğimiz zaman Oracle artık bu datafile'ın fiziksel olarak yerinin değiştiğini biliyor. Peki unix tarafındaki durum nedir?

Bir datafile'ı kullanmakta olan bir kullanıcı ya da bir background process'i varsa eğer bu datafile fiziksel olarak taşınsa bile kullandığı alanı unix bırakmayacaktır. Sizin cp ya da mv komutu ile taşıdığınız datafile aslında o datafile'ın inode girişi olacaktır. inode taşınmış olacak ve yeni yeri hem unix hem de oracle tarafından biliniyor olacak ancak eski işlemlerin üzerinde işlem yapıyor olmasından dolayı bu datafile'ın kapladığı alanın hala bırakılmadığını göreceksiniz. Bu duruma bir açıklık getirebilmek için kullanabileceğiniz unix programının adı "lsof", yani list of files.

Root kullanıcısı ile aşağıdaki komutu koşalım;

# lsof grep "/usr/db/data01.dbf"

lsof yazılımı bize bu datafile üzerinde hangi session'ın işlem gerçekleştirdiğini gösterecektir. Eğer bir ya da birden çok satır dönüyorsa, bu datafile'ın alanının bırakılmadığını farkedeceksiniz. Eğer hiçbir satır dönmüyorsa da datafile'ın hem fiziksel olarak taşınması gerçekleştirilmiş olacak hem de kullanmakta olduğu alan bilgisi güncellenmiş.

shutdown komutunu gönderirseniz eğer bütün bağlı kullanıcıların ve arkaplan görevlerinin çalışmaları durdurulacağından dolayı unix datafile'ın kapladığı alan bilgisini güncelleyebilecektir çünkü artık bu datafile için işlem sırasında olan ya da işlem yapan bir kullanıcı olmayacaktır.

İyi çalışmalar dilerim,

Ogan
Takip et: @oganozdogan