Veritabanı Yedekleme Stratejileri - 3 (RESTORE)
Bir önceki makalemde örneklerle yedekleme işlemlerini detaylandırmıştım. Bu makalemde ise bir önceki makaleme benzer bir şekilde örneklerle veritabanı yedek dönme yani restore işlemlerinden bahsedeceğim.
Yedekten dönme işlemi “RESTORE” komutu temelinde gerçekleşir. Restore komutunun en temel kullanım notasyonu aşağıdaki gibidir.
--BOŞLUKLARI DOLDURMAK İÇİN CTRL+SHIFT+M TUŞ KOMBİNASYONUNA BASINIZ
RESTORE DATABASE <VERİTABANI ADI,VARCHAR,> FROM DISK='<YEDEK DOSYASININ BELİRTİNİZ,VARCHAR,>'
Yukarıdaki komutun çalışması durumunda belirtilen veritabanı , belirtilen lokasyondaki yedek dosyasından dönülür. Bu komutun çalışması sonrasında veritabanı yedek dosyasının başlık bilgisinde belirtilen lokasyona yüklenerek kullanılabilir hale gelir.
Öncelikle örneklerime başlamadan önce bilgi amaçlı kullanılan “RESTORE” komutunun argümanlarına değinmek istiyorum. Bunlardan birincisi ve en çok ihtiyaç duyacağımız komut “RESTORE HEADERONLY”. Bu komut sayesinde bir yedek dosyasının içerisinde kaç adet veritabanı yedeği olduğunu, yedeklerin tiplerini, yedeği alan kullanıcı bilgisini, yedeğin alındığı sunucu bilgisini, bu yedeklerin nekadarlık bir yer kapladığını, yedeğin alınmaya başladığı ve bittiği tarihi, LSN numaralarını ve yedeklenen veritabanının özelliklerini öğrenebiliriz. Şimdi bir yedek dosyasının header bilgisini okuyalım.
Kullanacağımız komut aşağıdaki gibi.
RESTORE HEADERONLY FROM DISK='C:\DBBACKUPS\RESTORETESTDB_FULL1.BAK'
Bir başka “RESTORE” argümanı ise “RESTORE FILELISTONLY” . Adından da anlaşılacağı gibi bu argüman yedek dosyasında dönülecek veritabanı dosylarının bilgilerini döner. Yedekten dönme esnasında varsayılan olarak bu argümandan dönen sonuçlar kullanılır. Örneğin yedek alınan sunucuda veritabanı dosyaları X:\DATA klasöründe bulunuyor ise yedek dönülecek sunucuda da X:\DATA klasörü bulunması gerekir. Aksi durumda yedekten dönüş esnasında böyle bir klasör bulunmadığına dair işletim sistemi hatası alınır. Bu sorun ilerde anlatacağım MOVE TO komutu ile aşılabilir.
RESTORE FILELISTONLY FROM DISK='C:\DBBACKUPS\RESTORETESTDB_FULL1.BAK'
Bir başka “RESTORE” argümanı ise “RESTORE VERIFYONLY” . Bu argüman ile yedek dosyasının dönülebilir durumda olup olmadığı kontrol edilebilir. Burda kontrol edilen yedek dosyası içerisindeki veritabanı yedeğinin okunabilir durumda olup olmamasıdır. Bu argüman ile yedek dosyasının içerisindeki veritabanı verilerinin bütünlük kontrolünü sağlamaz.
RESTORE VERIFYONLY FROM DISK='C:\DBBACKUPS\RESTORETESTDB_FULL1.BAK'
Son anlatmak istediğim argüman ise “RESTORE LABELONLY”. Bu argüman yedek medyasının veya başka bir tabirle yedek dosyasının bilgilerini kontrol eder. Örneğin aynalanarak veya bölünerek formatlanan yedek dosyalarının bilgileri bu komut sayesinde elde edilir.
RESTORE LABELONLY FROM DISK='C:\DBBACKUPS\RESTORETESTDB_FULL1.BAK'
“RESTORE” argümanlarımıza değindikten sonra şimdi örneklere başlayabiliriz. İlk olarak elimdeki veritabanı yedeğini dönüp bu günkü örneklerim için gerekli veritabanımı oluşturmak istiyorum. Bunun için aşağıdaki komutu kullanacağım.
RESTORE DATABASE RESTORETESTDB
FROM DISK='C:\DBBACKUPS\RESTORETESTDB_FULL1.BAK'
Bu komut sonucunda RESTORETESTDB adında bir veritabanımız oluştu ve kullanıma hazır hale geldi.
İleride yapacağımız örnekler için veritabanı recovery durumununu kontrol edip eğer full modda değil ise full moda almak için aşağıdaki kodu çalıştıracağım
IF DATABASEPROPERTYEX('RESTORETESTDB','RECOVERY')!='FULL'
ALTER DATABASE RESTORETESTDB SET RECOVERY FULL
Daha önceki makalemde differential(fark) ve log yedeklerinin nasıl alındığı görmüştük. Şimdi bu yedeklerin nasıl dönüldüğüne bir bakalım. Bu tip yedekler tek başına dönülebilecek yedekler olmadıklarından dolayı herhangi bir yedek dönüldükten sonra veritabanının “NORECOVERY” veya “STANDBY” durumda olmaları anında dönülebilirler. Bu anlattıklarımı örneğe dökebilmek için bir full ve differential(fark) veritabanı yedeği alacağım.
BACKUP DATABASE RESTORETESTDB
TO DISK='C:\DBBACKUPS\RESTORETESTDB_FULL2.BAK'
BACKUP DATABASE RESTORETESTDB
TO DISK='C:\DBBACKUPS\RESTORETESTDB_DIFF1.BAK' WITH DIFFERENTIAL
Veritabanının restore sonrası hangi duruma geleceği gözelliği için “RESTORE” komut setinin üç farklı parametresi vardır. Bunlar; “RECOVERY”, “NORECOVERY” ve “STANDBY” dır. Bu parametrenin varsayılan değeri “RECOVERY” dir ve veritabanın dönüldükten sonra kullanıma hazır hale gelmesini sağlar. Bu parametre kullanıldığı takirde geri dönüş işleminden sonra hiç bir yedek dönülemez. “NORECOVERY” parametresi ile restore yapıldığında veritabanı geri dönüldükten sonra başka bir yedek dosyasının geri dönülmesini bekler ve bu aşamada veritabanına erişim sağlanamaz. “STANDBY” parametresi ile restore yapıldığında veritabanı geri dönüldükten sonra başka salt okunur olarak kullanıma açılır ve aynı zamanda başka bir veritabanı dosyasını da geri dönebiliriz. “STANDBY” parametresi ile yapılan restore işleminden sonra veritabanı okunabilir durumdadır fakat “NORECOVERY” parametresi ile yapılan restore işlemi daha az maliyete sahiptir bunun nedeni “STANDBY” parametresi ile yapılan restore işleminde standby dosyasının oluşturulmasıdır.
Şimdi örneğimizde full yedeğimizi “NORECOVERY” özelliği ile döndükten sonra differential(fark) yedeğimizi dönelim.
RESTORE DATABASE RESTORETESTDB
FROM DISK='C:\DBBACKUPS\RESTORETESTDB_FULL2.BAK'
WITH REPLACE,NORECOVERY
Processed 1288 pages for database 'RESTORETESTDB', file 'RESTORETESTDB' on file 1.
Processed 2 pages for database 'RESTORETESTDB', file 'RESTORETESTDB_log' on file 1.
RESTORE DATABASE successfully processed 1290 pages in 1.052 seconds (9.573 MB/sec).
Döndüğümüz veritabanı varolan bir veritabanı olduğu için “REPLACE” ve yeni bir yedek dönüşünü beklemesi içinde “NORECOVERY” parametrelerini kullandım. Restore bittimi ile beraber veritabanı yeni bir yedek dönmem için beni bekliyor
SELECT state_desc FROM sys.databases
WHERE name='RESTORETESTDB'
Sonuç:
state_desc
------------------------------------------------------------
RESTORING
Şimdi differential(fark) yedeğimi dönüp veritabanı veritabanımı kullanılır hale getireceğim. Bunun için yedeğimi “RECOVERY” parametresi ile döneceğim
RESTORE DATABASE RESTORETESTDB
FROM DISK='C:\DBBACKUPS\RESTORETESTDB_DIFF1.BAK'
WITH RECOVERY
Processed 32 pages for database 'RESTORETESTDB', file 'RESTORETESTDB' on file 1.
Processed 1 pages for database 'RESTORETESTDB', file 'RESTORETESTDB_log' on file 1.
RESTORE DATABASE successfully processed 33 pages in 0.088 seconds (2.852 MB/sec).
Şimdi veritabanı durumunu kontrol edersem kullanıma hazır olduğunu görebilirim.
SELECT state_desc FROM sys.databases
WHERE name='RESTORETESTDB'
Sonuç:
state_desc
------------------------------------------------------------
ONLINE
Anlaşılacağı gibi yedekten dönme işleminde birden fazla yedek dönülecekse son yedekten önceki tüm yedekler “NORECOVERY” parametresi ile dönülmelidir. Temel yedek dönme örneklerimizle log yedeği dönerek son verelim ve yedekten dönme işlemini diğer özelliklerini inceleyerek ayrıntılandıralım.
Öncelikle log kaydı yaratacak işlemler yapıp log yedeği alalım.
USE RESTORETESTDB
GO
--ÖRNEK TABLO TANIMLANIYOR
CREATE TABLE TESTTABLE1
(
ID INT IDENTITY(1,1),
ISIM VARCHAR(20),
SOYISIM VARCHAR(20),
TARIH DATETIME
)
GO
-- 1000 KAYIT GİRİLİYOR
INSERT INTO TESTTABLE1 (ISIM,SOYISIM,TARIH)
VALUES('TEST','TEST',GETDATE())
GO 1000
--LOG YEDEĞİ ALINIYOR
BACKUP LOG RESTORETESTDB
TO DISK='C:\DBBACKUPS\RESTORETESTDB_LOG1.TRN'
Alınan bu log yedeğini dönmek için öncelikle full ve differential(fark) yedeklerini dönüp sonrasında log yedeği dönmem gerekiyor
USE master
go
--FULL YEDEK DÖNÜLÜYOR
RESTORE DATABASE RESTORETESTDB
FROM DISK='C:\DBBACKUPS\RESTORETESTDB_FULL2.BAK'
WITH REPLACE,NORECOVERY
--DIFFERENTIAL YEDEK DÖNÜLÜYOR
RESTORE DATABASE RESTORETESTDB
FROM DISK='C:\DBBACKUPS\RESTORETESTDB_DIFF1.BAK'
WITH NORECOVERY
--LOG YEDEK DÖNÜLÜYOR
RESTORE LOG RESTORETESTDB
FROM DISK='C:\DBBACKUPS\RESTORETESTDB_LOG1.TRN'
WITH RECOVERY
Şimdiki örneğimizde “STOPAT” özelliği ile istenilen bir tarihe nasıl yedek dönülebileceğinden bahsedeceğim. Öncelikle full yedek alıp yedekleme zincirinin yeniden başlamasını sağlayalım ve sonrasında tablomuza zaman bazlı kayıtlar girelim.
--VERİTABANI YEDEĞİ ALINIYOR
BACKUP DATABASE RESTORETESTDB
TO DISK='C:\DBBACKUPS\RESTORETESTDB_FULL3.BAK'
GO
--ZAMAN BAZLI KAYITLAR ATILIYOR, HER 5 SANİYEDE BİR 10 ADET KAYIT ATILIYOR
USE RESTORETESTDB
GO
TRUNCATE TABLE TESTTABLE1
DECLARE @I INT=0
WHILE @I<10
BEGIN
WAITFOR DELAY '00:00:05'
INSERT INTO TESTTABLE1(ISIM,SOYISIM,TARIH)
VALUES('KADİR'+CONVERT(VARCHAR,@I),'EVCİLER'+CONVERT(VARCHAR,@I),GETDATE())
SET @I+=1
END
GO
--LOG YEDEĞİ ALINIYOR
BACKUP LOG RESTORETESTDB
TO DISK='C:\DBBACKUPS\RESTORETESTDB_LOG2.TRN'
Şimdi tablonun içine bakalım ve kendimize dönülecek bir zaman belirleyelim.

Belirlediğim kayda dönmek için “STOPAT” komutunu aşağıdaki gibi kullanabiliriz.
USE master
go
--FULL YEDEK DÖNÜLÜYOR
RESTORE DATABASE RESTORETESTDB
FROM DISK='C:\DBBACKUPS\RESTORETESTDB_FULL3.BAK'
WITH REPLACE,NORECOVERY
--LOG YEDEK DONULUYOR VE STOPAT KOMUTU İLE İSTENİLEN TARİHE GELİNİYOR
/*
OTURUMUN TARİHİNİ AŞAĞIDA VERDİĞİMİZ TARİH FORMATI
İLE AYNI SET ETMEK FAYDALI OLACAKTIR. AKSİ TAKTİRDE
OTURUM TARİH FORMATI İLE VERDİĞİMİZ TARİH FORMATI TUTMAYABİLİR
*/
SET DATEFORMAT YMD
RESTORE LOG RESTORETESTDB
FROM DISK='C:\DBBACKUPS\RESTORETESTDB_LOG2.TRN'
WITH RECOVERY,
STOPAT='2011-09-07 18:06:33.220'
Döndükten sonra tabloyu sorgulamamız durumunda belirttiğim tarihe kadarki tüm kayıtların geldiğini görebiliriz.

Kendi sistemlerimiz üzerinde çok kritik veri değişiklikleri yapmadan önce işlemi işaretlenmiş işlem (marked transaction) şeklinde yaparsak gerekli durumda dönmemiz gereken yeri rahatlıkla bulabiliriz.
Makalemin son kısmında SQL Server 2008 ile beraber gelen “PAGE RESTORE” özelliğinden bahsetmek istiyorum. Bazen veritabanı sayfalarımızın bozulması ile beraber veritabanları ulaşılamaz hale gelebilirler. Bu gibi durumlarda biz veritabanı yöneticileri ilk olarak DBCC CHECKDB komutunu çalıştırarak hasarın nerde olduğunu anlamaya çalışırız. Elimizde yedeğin olmaması durumuda bozulan sayfalardaki verileri kaybetmek zorunda kalabiliriz ki bu durum bazı iş kritik uygulamaların çalıştığı veritabanlarında kabul edilemeyecek kadar büyük bir sorundur. Böyle bir senaryoda “PAGE RESTORE” özelliği sadece bozulan sayfaların dönülmesini sağlayarak en kısa zamanda sorunu çözüme kavuşturmak için kullanılabilir.