SQL Server Database Snapshot

Merhabalar ,

Database Snapshot özellikleri SQL 2005 'den itibaren bizlerin kullanımına sunulan çok sevdiğim özelliklerden birisi.
Kısaca DataBase Snapshot , Veri tabanın o anda bir resmini çekmeye benzer. Veri tabanın Snapshot oluşturduğu andan itibaren elimizde read-only bir kopyasını elde etmiş oluruz.
Temel amacı ise Asıl veri tabanımızda ,snapshot oluşturulduğu andan sonra, değiştirilmiş kayıtların orjinal hallerini saklayıp gerektiğinde düzeltmektir.

İsterseniz örnek bir senaryo ile daha iyi anlıyalım, daha sonra da olumlu ve olumsuz yanlarından bahsedelim.

CREATE DATABASE CUSTOMER_SS_CASE1 ON (
NAME = CUSTOMER,
FILENAME = 'C:\SQLDATA\CUSTOMER_SS_CASE1.SS')
AS SNAPSHOT OF CUSTOMER;

Senaryomuz'da Customer veritabanın da önemli değişiklik planlıyoruz. 3 farklı case den oluşan değişikliğin ilk adımında belirtilen dosya altına Veritabanımızın o andaki snapshot'nı aldık.
Şu andan itibaren yapılan tüm update,delete,insert işlemleri öncesinde ,orjinal halleri snapshot database yazılır.
Değişiklikleri başlattık , bazı değişiklikleri devreye aldık ve case1 adımını tamamladık ve bu arada 2. snapshot'ı aldık. fakat istenmeyen bir şey oldu! Ve önemli bazı kayıtları Customer database'den sildik..Bu durumda değişiklikleri başlatmadan önceki case dönmemiz gerekiyor.(case1 sorunsuz geçildiğinden, case2 adımına dönmemiz gerekiyor.)

RESTORE DATABASE CUSTOMER
FROM DATABASE_SNAPSHOT = 'C:\SQLDATA\CUSTOMER_SS_CASE2.SS'

Gördünüz gibi çok daha az zamanda değişiklik öncesine dönmüş olduk.Eğer elimizde snapshot olmasaydı backup'dan en başa dönmemiz gerekiyordu!. Fakat biz case2 adımına dönebildik.

Burada göz ardı edemiyecemiz özellik ,full backup'dan dönmek çok daha uzun sürecekti hemde backup size ile snapshot dosyasının size arasındaki fark olucaktı.

Bu şekilde yapıldan senaryolar'da , belirli periyotlarda alınan Database snapshot'lar oldukça kullanışlı olabilir. Snapshot sadece değişiklik oldunda orjinal veritabanı ile konuştundan, oldukça hızlıdır. Aynı zamanda sparse dosyasına sadece oluşan değişiklikleri yazdığından ,değişikliğe uğrayan veri alanı kadar diskde yer kaplıyacaktır. Backup-Restore işlemine göre daha az masraflıdır.

Olumsuz yanlarına bakarsak, Orjinal Veritabanı ile konuştundan sanpshotdan çekilebilcek data için performans kaybı olucaktır. Sebebi ise değişmemiş datayı gidip okumasıdır. orjinal veri tabanı offlie moda geçtinde snapshot database de aynı şekilde offlie moda geçer.

Şimdilik bu kadar Pusulanı Ayarlamayı unutma :)

ORA-14099 all rows in table do not qualify for specified partition

Mevcut hata partiton switch işlemi sırasında alınmıştır. 
Yapılması gereken switch yapılacak tabloyu kontrol etmek olmalı.
PUSULA_ARCHIVE tablosunun satırlarının geçerli olduğundan emin olmalısınız. Tablosunun kolonlarının invalid, eksik yada tablonun boş olduğunu kontrol etmelisiniz. Yada tabloyu VALIDATE etmek için, ANALYSE edebilirsiniz.

Alter table pusula exchange partition part_01 with table pusula_archive;

ORA-14099: all rows in table do not qualify for specified partition

Oracle Var olan Tabloyu PartitionYapmak (Partitioning an Existing Table)

Selamlar bu yazımızda ORACLE Veri tabanında dolu bir tabloyu nasıl partition şekle getirebiliriz bunu inceleyelim.
Örneğin fazla büyümekte olan bir tablomuz var.Bu taployu arşivlemek hatta aylık yada yıllık partitionlara bölerek performans artışı sağlamak isteyebiliriz.Oracle de içinde kayıt olan tablolar için bunu yapmak, oldukça zahmetli ve risk içeren bir işlemdir.
Şimdi bunu örnek ile nasıl yapabileceğimizi tartışalım.
Yeni bir tablo yaratıp Index yaratalım ve bu tabloya yeni kayıtlar girelim.

CREATE TABLE PUSULA (
id            NUMBER(10),
created_date  NUMBER(10), 
named         VARCHAR2(50)
)TABLESPACE DATA_LARGE_TBS_01;
--Indexler
CREATE INDEX IX_PUSULA_01 ON PUSULA (ID) TABLESPACE DATA_LARGE_TBS_01;
CREATE INDEX IX_PUSULA_02 ON PUSULA (CREATED_DATE)TABLESPACE DATA_LARGE_TBS_01;
--Kayıtlar
INSERT INTO PUSULA VALUES (1, 20111001, 'ilker');
INSERT INTO PUSULA VALUES (2, 20111101, 'ilkerusta');
INSERT INTO PUSULA VALUES (3, 20111201, 'ustailker');
COMMIT;

Tablomuza bir göz atıyoruz
select * from PUSULA;

Tabi herzaman kayıtlarımız bu kadar az olmıyacak :) şimdi partition yapıda yeni bir tablo yaratalım.
Burada dikkat edilmesi gereken partition başlangıç zamanı, hangi alanın kullanılacağı ve hangi table space üzerinde create edileceği.
CREATE TABLE PUSULA2 (
id            NUMBER(10),
created_date  NUMBER(10),
named         VARCHAR2(50)
)
TABLESPACE DATA_LARGE_TBS_01
PARTITION BY RANGE (created_date)
INTERVAL(100) STORE IN (DATA_LARGE_TBS_01)
(PARTITION p0 VALUES LESS THAN (20111200) TABLESPACE DATA_LARGE_TBS_01);

ALTER TABLE PUSULA2 SET STORE IN (DATA_LARGE_TBS_01);

ALTER TABLE PUSULA2 enable row movement;

NOT: Ben 20111200 tarihininden başlattım.  LESS THAN opsiyonu ile bu tarih öncesini P0 partition içine alacak.

ENABLE ROW MOVEMENT Enable ediliyor. Çünkü partitionlar yer değiştiriyor. Ne kadar sevilen bir hareket olmasada J (i/o vs. gibi sorunlar için bu tamamen ayrı bir konu) partition key update olabilmesi için yapıyoruz.

Indexler yaratılsın. Tavsiyem isimleri rename edilecek tablo ile farklı olması. Tabiki bu Indexleri kullanan sql hint cümlecikleri yok ise.
CREATE INDEX IX_PUSULA2_01 on PUSULA2 (ID) local;
CREATE INDEX IX_PUSULA2_02 on PUSULA2 (CREATED_DATE) local;

Not: Indexler Local yaratılıyor bu da demek olur ki her partition için local bir index olacak ve exchange esnasında Unusable olmasınlar.

SELECT partitioned
FROM dba_indexes
WHERE table_name = 'PUSULA2'

Yapımızı hazırladık. Şimdi tablomuzu yeni yapıya geçirelim. Bunun için mevcut tablo içerisindeki kayıtları yeni yaratılan tablomuzun ilk partitiona exchange edip daha sonra rename işlemini yapalım.

Not: Öncesinde bu tablolara depent eden tüm objelerin tespit edilip exchange ve rename sonrası compile edilmesi gerekiyor.

--Exchange işlemi
ALTER TABLE PUSULA2 EXCHANGE PARTITION p0 WITH TABLE PUSULA WITHOUT VALIDATION;
--Yeni tablo ile rename işlemi
ALTER TABLE PUSULA RENAME TO PUSULA_OLD;
ALTER TABLE PUSULA2 RENAME TO PUSULA;
--Indexler rebuild ediliyor.
ALTER INDEX IX_PUSULA2_01 rebuild partition p0 online;
ALTER INDEX IX_PUSULA2_02 rebuild partition p0 online;

Tablomuz rename edildi ve exchange yapıldı. Kontrol edelim
select * from PUSULA;

Güzel !! Şimdi tablomuz partition oldu ve eski kayıtlarımız hala, aynı isimdeki yeni yapıdaki tablomuzda.

Son olarak yeni yapıdaki partition tabloya yeni tarihli kayıtların geldiğinin ve partition dağılımı nasıl olucak bunların testini yapalım.
insert into PUSULA values (4,20111201,'ilker');
insert into PUSULA values (5,20120101,'ilkerusta');
insert into PUSULA values (6,20120201,'ustailker');
commit;

Dağılımı görmek için.
SELECT table_name, partition_name, tablespace_name
FROM dba_tab_partitions
WHERE table_name = 'PUSULA';

Şimdilik kolay gelsin :)

ORA-14039: partitioning columns must form a subset of key columns of a UNIQUE index

Mevcut hata partition bir tabloya local / partition bir index yaratılmak istenirken alınan hatadır.

create unique index USTA.MUHASEBE_IX01 on USTA.TABLE_MUHASEBE (log_guid)
  tablespace LARGE_TBS_01 local;


ORA-14039: partitioning columns must form a subset of key columns of a UNIQUE index

Partition index non-Unique olmak zorundadır. Doğru şekli:

create index USTA.MUHASEBE_IX01 on USTA.TABLE_MUHASEBE (log_guid)
  tablespace LARGE_TBS_01 local;


 

Ara