SQL Server’da LSN Nedir & Copy Only Backup

Merhabalar,

Günümüzde verinin çeşitliliği ve hacmi gün geçtikçe doğrusal olmayan bir hızda artmaktadır. Özellikle son 10 yıllık periyoda baktığımızda verinin 40 kata yakın bir artış gösterdiği ve bununla birlikte günümüz verilerinin yüzde 90’a yakınının ise son 5 yılda oluştuğu bilinmektedir. Böyle büyük bir veri hacmiyle birlikte önümüzdeki 10 yıl içinde verinin boyutunun artık GB ile değil, TB ile ifade edileceği bir dünyada dijital güç olarak veriyi saklamak şirketler için oldukça önemlidir. Bu özellikleriyle geleceğin madeni olan veri, bir yandan üretilmeye devam ederken bir yandan da bu verilerin korunması, saklanması ve felaket anında tekrardan kullanıma dahil edilmesi gibi durumlar bir veritabanı yöneticisinin en önemli görevlerindendir.

Bu veriler satış verisi olabileceği gibi operasyonel süreçlerde karar alma, ürün listesi ya da E-Ticaret firmasında bir ürünün kargosunun yapılıp yapılmadığının bilgisi süreç açısından oldukça önem arz etmektedir. Bu verilerin herhangi bir felaket anında yaşanan kesinti sebebiyle ya da başka bir sebeple zarar görmemesi için yedekleme planı çıkarılarak buna uygun şekilde yedeklenmelidir. Bu yedekleme planı belirlenirken şirketin iş ihtiyaçları, gereksinimleri ve belirlemiş olduğu RPO ve RTO değerleri de göz önünde bulundurulmalıdır.

Özetle bu iki kavramdan bahsedecek olursak;

RTO ( Recovery Time Objective ) : Olası felaket anında, süreç ve hizmetlerin eski haline döndürülmesi için geçen kabul edilebilir süre diyebiliriz.

RPO ( Recovery Point Objective ) : Felaket sonrası kabul edilebilir veri kaybının ne düzeyde olabileceği şeklinde tanımlayabiliriz.

Elbette ki tüm bu süreçler için alınan yedekler tek başına yeterli olmayıp belirli senaryolar ve periyotlar çerçevesinde restore edilerek alınan yedeklerin doğrulaması da yapılmalıdır.

Bugün bu yazımızın konusu ise, bu verileri yedeklerken SQL Server’ın bu yedekleri nasıl tuttuğu ve ilişkilendirdiğini açıklamamıza yardımcı olacak LSN yani Log Sequence Number kavramı olacak.

Öncelikle LSN tanımı ile başlayalım.

OLTP sistemlerde en iyimser haliyle bir günde binlerce transaction işlemi gerçekleşmektedir. Gerçekleşen her transaction işleminin birbirinden ayrılabilmesi kolay olmadığı için de bir etiketlendirme yapılarak kayıt altına alınır. Bu etiketler ise Unique olarak işaretlenen LSN ile yapılmaktadır. Gerçekleşen işlem sayısı arttıkça LSN number da artarak bir sonraki kayıt numarası bir önceki kayıt numarasından büyük olacak şekilde süreç devam etmektedir.

Bu şekilde birbirini takip eden transactionlar ve verilmiş olan LSN Number ile felaket anında veri kaybı sebebiyle yaşanan zararımızı en aza indirgeyebiliyoruz. Tabi ki bu kayıtların düzenli olarak yedeklerinin alınması ve bu yedeklerde herhangi bir bozulma vs. olmaması şartıyla.

SQL Server üzerinde yapılan değişikliklerin Transaction Log dosyasına yazıldığından bahsetmiştik. Bu log dosyası işlem sayısı arttıkça yüksek boyutlara ulaşmaya başlar. Bu noktaya gelmemesi amacıyla da bu Transaction Log dosyalarının yedeklerinin alınması gerekir. Peki ama yedek alınca Transaction Log dosyasının büyümesi neden duruyor ?

Bu sorunun cevabı veritabanı özelliklerinde yer alan Recovery Model ile ilişkilidir. Çünkü belirlemiş olduğumuz recovery model aslında log dosyasının boyutunu dolaylı yoldan belirleyen bir faktördür.

Full recovery modelde her işlem detayı transaction log dosyasına yazıldığından dolayı data kaybı yaşanması pek mümkün değildir. Bazı avantajlar sağlasa da Log dosyası hızlı bir büyüme ivmesi göstereceği için kaynak tüketimini artıracaktır. Büyük boyutlara ulaşma potansiyeli olduğundan log yönetimi de nispeten zordur. Fakat data kaybı yaşanmaması gereken durumlarda tercih edilir.

Tam tersi olarak veritabanımızın recovery modeli Simple ise, kayıt altına alınan transaction loglar her checkpoint işlemi gerçekleştikten sonra silinir. Transaction loglar silindiği için de Log backup alınamaz. Bu sebeple data kaybı durumu yüksek olasılığa sahiptir. Test ortamlarındaki veritabanları için daha uygun bir tercih olacaktır.

Bulk-Logged Recovery Modelde ise, bulk insert ya da data import işlemleri gibi toplu data işlemleri dışındaki tüm işlemler loglanır.

Bu recovery modellerinin LSN number ile ilgisi nedir ?

Yazımızın başında da bahsetmiş olduğumuz gibi veri kaybı yaşamamak adına belirlenen backup stratejisi dahilinde yedekler almaktayız. Örneğin dakikalık hatta saniyelik bazda veriler önem arz ediyorsa transaction log backup ağırlıklı bir yedekleme planı, birkaç saat ya da günlük bazda verilerimiz değişiyorsa differential ve full backup ağırlıklı bir backup stratejisine yönelmeliyiz. Yedekleme stratejileri ve backup türlerinin özellikleri bu yazımızın konusu olmadığı için çok fazla değinmeyeceğim.

Fakat verimizin önemine bağlı olarak her ne kadar backup stratejimiz değişiyor olsa da değişmeyecek bir kural vardır. O da restore ederken elimizde bir full backup olması.

Peki bu kural neden geçerli ?

SQL Server’da bir Log backup almak için Recovery Modelin Full olarak işaretlenmesi gerekir. Bu recovery modelde her işlem kayıt altında tutulduğu için log backupları kullanarak istediğimiz saniyeye kadar dönebilmekteyiz. Bunu yaparken bir Full backup seçip daha sonra dönmek istediğimiz zamanı da kapsayacak şekilde alınmış log backupları da seçerek işlemi gerçekleştirebiliriz.

Aynı şekilde bir Diff backup alabilmek için Full backup alınmış olması gerekir. Ve restore ederken de bu Diff backuptan önce Full backup restore edilmelidir.

Log ve Diff backupların restore edilirken Full backup zorunlu olmasının sebebi ise bu her iki backup için de LSN numberlarının, daha önceden alınmış olan Full yedeği referans almasıdır. Böylece bir bütün halinde Full-Diff-Log yedekleri ile sıralanmış bir backup zinciri oluşur.

Bu backup zincirindeki sıralama ise LSN number ile sağlanmaktadır. Her backup için bir ilk LSN değeri, son LSN değeri ve referans aldığı LSN değeri bulunmaktadır.

Gerçekleşen her işlemin Unique olarak etiketlendiğini düşündüğümüzde, eğer istediğimiz veri bu başlangıç ve bitiş LSN değeri arasındaysa verimizi o yedeği kullanarak kurtarabiliriz. Tabi ki biz restore ederken hangi işlemin hangi LSN değerleri arasında olduğunu göz önüne alarak değil, tahmini geri döneceğimiz zamanı belirleyerek verilerimizi kurtarıyoruz. Her yedeğin bir işlemler bütününden oluşan paketler olduğunu, Diff ve Log backupların da birer fark backupları olduğunu düşündüğümüzde (Diff backup, son alınan Full backup ile Diff backup alınacak zaman arasındaki veri farkı ve Log backup ise bir önceki alınmış Log backup ile son alınacak Log backup arasındaki veri farkı) herhangi bir zamana backuptan döndüğümüzde yanlışlıkla yapılmış işlemleri geri alabiliyor ya da verileri yeniden sisteme dahil edebiliyoruz.

Bu bilgiler doğrultusunda LSN number olarak adlandırdığımız bu yapıyı bir örnek üzerinden detaylandırarak incelemeye devam edelim.

Bunun için Dmc_Test adında bir database create ediyorum.

CREATE DATABASE Dmc_Test

Resim-1

Şimdi bu database için bir tablo oluşturalım.

CREATE TABLE Test

(

Id int,

Ad varchar(50),

Soyad varchar(50),

Tarih time(3)

)

Resim-2

Şimdi bu tablonun içine 3 saniyede bir random değerler girelim. Kayıt sayısını özellikle fazla tutarak ufak çaplı da olsa sürekli veri girişi yapılan bir sistemi hedefliyoruz .

DECLARE @i INT

SET @i = 1

WHILE(@i < 10000)

BEGIN

INSERT INTO Test

SELECT

Id = @i,

Ad = ‘Çağdaş_ ‘ + CAST(@i AS nvarchar(30)),

Soyad = ‘Koca ‘ ,

Tarih = CONVERT(time(3),GETDATE())

SET @i = @i + 1

WAITFOR DELAY 00:00:03

END

Resim-3

Tablomuzun bu haliyle bir Full backup almadan önce bu veritabanımız için backup listesine bakalım.

SELECT

       database_name,

       CASE [type]

             WHEND‘ THEN ‘Full

             WHENI‘ THEN ‘Differential

             WHEN L‘ THEN ‘Transaction Log

       END AS BackupType,

       first_lsn,

       last_lsn,

       database_backup_lsn,

       checkpoint_lsn

FROM msdb.dbo.backupset

WHERE database_name = ‘Dmc_Test

Resim-4

Görüldüğü üzere bu veritabanımız için herhangi bir backup bulunmamaktadır. Şimdi bir Full backup alalım.

BACKUP DATABASE [Dmc_Test] TO DISK = N’D:\Backups\Dmc_Test.bak’

WITH NOFORMAT, NOINITNAME = N’Dmc_Test-Full Database Backup’,

SKIP, NOREWIND, NOUNLOADSTATS = 10

Resim-5

Aldığımız ilk Full yedeği incelediğimizde, database_backup_lsn değeri 0 olarak gözükmektedir. Bu değer en son alınan Full yedeğin first_lsn değeridir. Daha önceden bir Full backup alınmadığı için ilk Full backuplarda her zaman 0 değerini görürüz. Bunu başka bir dbde şu şekilde de görebiliriz.

Resim-6

Şimdi örnek yaptığımız database e dönüp bir log backup alalım.

Resim-7

Aldığımız Transaction Log için database_backup_lsn değeri, alınan son Full backup için first_lsn değerine eşittir. Yukarıda da bahsettiğimiz gibi Log yedeğimiz LSN değeri üzerinden son Full backup ı referans alarak bir backup zinciri oluşturmaktadır. Bu sebeple belirli bir ana dönmek için kullandığımız Log backuplarımızı restore ederken, hangi full backuptan referans alacağını belirtmek için bir full backup seçerek ilerlemek gerekiyor. Belirtmediğimiz sürece SQL Server bunu çözümleyemeyeceği için bize bir uyarı vermektedir.

Bir Log zinciri oluşturmak için backuplar almaya devam ediyorum.

Resim-8

Art arda alınan log backuplara baktığımızda bir önceki last_lsn değeri, bir sonraki log backup için first_lsn değeri olarak belirlenir ve bu şekilde bir zincir oluşturulur. Örneğin yanlışlıkla bir veri silindi ve bizim bu veriyi kurtarmamız gerekiyor. Bu durumda veri kaybına sebep olan işlem saati belirlenerek o saati kapsayan full  + log backuplar ile istenilen saniyeye kadar dönebilirsiniz.

Örnek verecek olursak,bir sunucuda 00:00 da bir full backup ve 5 dk da bir olacak şekilde de log backup alınan bir yedekleme planı olduğunu düşünelim. Saat 01:28 de bir veri kaybı yaşandığında, 00:00 da alınmış bir full backup ve 5 dk bir alınan log backuplar 01:28’i de kapsayacak şekilde seçilerek restore edilebilir. Burada full backup dönüldükten sonra 5 dakikada bir alınan ve 01:30’a kadar olan log backuplar birer zincir halinde takip edecektir.01:10 da alınan log backup first_lsn değeri 01:05 te alınan log backup last_lsn değeri olacaktır. Ve 01:15 te alınan log backup first_lsn değeri 01:10 da alınan log backup ın last_lsn değeri olacaktır. Bu şekilde çaprazlama bir zincir ile uç uca eklenerek istenilen dakikaya gelebiliriz. Bu sebeple LSN değerini korumak önemlidir.

COPY_ONLY

Bazı durumlarda tanımlamış olduğumuz schedule dışında bir backup almamız gerekebilir. Örneğin çeşitli senaryolar sebebiyle bir backup alıp test ortamına dönmek durumunda kalabiliriz. Bu backup anlık olarak bir işlem için restore edildikten sonra bir değer ifade etmiyorsa ya da silinecekse, mevcutta oluşmuş olan bir zinciri kırmak risk demektir. Böyle bir durumda alacağımız backup, mevcut backup setine dahil edilsin istemiyorsak COPY_ONLY parametresini kullanabiliriz. COPY_ONLY ile alacağımız backup ile işimiz bittiğinde sildiğimizde bir sorun yaratmayacaktır. Fakat mevcutta yer alan backup zincirinden bir log backupta bozulma meydana varsa, kendisinden sonra gelen log backupların da bir anlamı kalmayacaktır.

Kullanımı ise SSMS üzerinden arayüz kullanarak yapılabildiği gibi, backup scriptimize WITH COPY_ONLY ekleyerek de alabiliriz. Arayüz üzerinden önce iki adet Copy_Only ile daha sonra Copy_Only parametresini seçmeden iki adet olmak üzere toplamda 4 adet Full Backup alıyorum.

Resim-9

Yazımızda yukarıda bahsettiğimiz gibi Full Backup için database_backup_lsn değeri bir önceki Full backupın first_lsn değerini alır demiştik. Fakat is_copy_only değeri 1 olan yani Copy_Only parametresi ile alınmış backuplara baktığımızda bir önceki full backupın değil, Copy_Only olmayan son Full backupın first_lsn değerini aldığını görüyoruz. Bu şekilde zincire dahil edilmediğini görmüş olduk.

Resim-10

Fakat is_copy_only 0 olan yani parametre kullanmadan aldığımız full backuplara baktığımızda bir önceki Full Backup ın first lsn değerini aldığını görüyoruz.

Resim-11

Bu süreçlerde ;

Log backuplarda sol alt çapraza doğru gittiğini söylemiştik. Copy_Only ile bir Log backup aldığımızda sol alt çapraz ilerleme koşulu bu sefer devam etmez. Çünkü aldığımız backupları backup setine dahil etmedik. Alttaki resimde de görüleceği üzere 1 numaralı alandaki last lsn değeri Copy Only ile alınan iki Log backup için(12-13.satırlar) first lsn değeri olarak devam ediyor.Fakat daha sonra Copy only olmayan(14.satır first lsn) Log Backupta da aynı lsn değerini görmekteyiz.Normal koşullarda birinci copy only backupın(12.satır) last lsn değeri ikinci copy only olan log backupın (13.satır) first lsn değeri olmalıydı.Bu şekilde devam etmemiş olması bu backupların backup setine dahil edilmediğini göstermektedir. Copy_Only olmayan 14.satırdaki first lsn değeri 6 numaralı log backupın last lsn değerini devralıp aynı şekilde sol alt zincir kuralına göre kaldığı yerden devam etmektedir.

Resim-12

Eğer veritabanının Recovery modeli değiştirilirse log zinciri bozulacaktır. Örneğin Full Recovery modelden Simple Recovery’e geçildiğinde transaction logların kayıt altına alma durumu değiştiğinden log backup alamayız. Göz önünde bulundurmakta fayda var. Eğer aksi bir durumda backup zinciri kırıldığında FULL backup alınana kadar geçen sürede olası veri kaybını yaşamamak için backup süreçleri iyi belirlenmeli ve gereksiz müdahalelerde bulunmaktan kaçınmalıyız. Eğer gerçekten geçici bir backup ihtiyacımız varsa Copy_Only seçeneğini değerlendirmeliyiz.

Bu yazımızda alınan backupların oluşturduğu zinciri,aralarındaki ilişkiyi ve COPY_ONLY ile alınan yedeklerin nasıl bir yapıda tutulduğunu aktarmaya çalıştım.

Umarım faydalı bir yazı olmuştur.

Hoşça kalın.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir