10 Ocak 2017 Salı

Yedek alırken bütünlük kontrolü yapıyor musunuz?

Aralık ayı içerisinde 2 farklı yazı ile (biri ve diğeri) yedek almanın önemine değinmiştim. Bu yazı ile de, SQL Server'da yedek alırken kullanılabilecek önemli bir parametreye değinmek istiyorum.

Biliyorum, birçok kurumun maalesef hala belirlenmiş RPO ve RTO değerleri yok ve yedek alma işi sadece "yapılması gereken standart işlerden bir diğeri" gibi görülüyor. Bir felaket durumunda da tabiri caizse elde harddisk "verilerimizi nasıl kurtarabiliriz?" diye kapı kapı dolanan arkadaşları görüyoruz. Bu yazım ise tabii ki RPO ve RTO değerlerinin anlamını bilip, yedek almaya gerekli özeni gösteren kurum ve çalışanları için.

Konuya giriş yapmam için önece bazı terim ve kavramları izah etmem gerekiyor.

SQL Server'da veriler en küçük depolama birimi olan Page'lere kaydedilir. Page'ler diskte 8 kilobaytlık bir alan kaplar. Bir Page tablo yapınızda kullandığınız veritipleriniz ve verinize göre bir veya daha fazla kayıt içerebilir. SQL Server verileri Page'lere kaydettikten sonra otomatik ve rutin bir şekilde tekrar tekrar dönüp Page'lerin sağlık durumunu kontrol etmez ve Page'lerin sağlık ve bütünlük durumu fiziksel disk yapısındaki fiziksel bir sıkıntıdan, SQL Server'daki bir Bug'tan veya SQL Server'ın sağlıklı bir şekilde kapatılmaması gibi sebeplereden dolayı bozulabilir.

SQL Server 2005 ile birlikte Page'lerin veri bütünlüğünü kontrol seçenekleri arasına Checksum da katıldı. Öncesinde ise 2 seçenek vardı, ya bu kontrol hiç yapılmasın ya da Torn Page, bu seçenekler yeterince koruma sağlamıyordu, bu nedenle Checksum seçeneği geldi ve SQL Server 2005 ile birlikte varsayılan seçenek oldu. 

Page bütünlüğü için Checksum seçeneği kullanıldığında SQL Server tüm Page'in bütünlüğünü dikkate alarak bir Checksum hesaplar ve bunu da Page diske yazılırken Page'in içerisindeki Page Header'a "m_tornBits" etiketiyle kaydeder. Bu Page diskten okunurken Checksum tekrar hesaplanır ve "m_tornBits"teki değer ile (örnek değer: -1433260509) karşılaştırılır. Eğer eşleşme sağlanamazsa, o zaman SQL Server Error Log ve Windows Application Event Log'a 824 hata numarasıyla kaydedilir. Bu sayede üst seviye bütünlük kontrolü sağlanmış olur.

Torn Page'in yeterince koruma sağlamadığını söylemiştim, Checksum ile farkını belirginleştirmek için bir örnek vereyim. Sanırım birçoğunuz hayatınızın bir döneminde bir Hex Editor kullanmıştır. Örneğin Page doğrulama özelliği Torn Page olan bir sayfayı, ilgili veritabanını Offline duruma alarak bir Hex Editor ile değiştirebilirsiniz ve DBCC CHECKDB ile bütünlük kontrolü yapmadığınız sürece bu değişikliği kimse fark etmez. Fakat aynı Page Checksum doğrulamasıyla ayarlansaydı, Hex Editor ile değişiklik yapıp veritabanını tekrar Online duruma getirip ilgili kayıtları sorguladığınızda aşağıdaki gibi bir hata alırdınız:

Msg 824, Level 24, State 2, Line 1
SQL Server detected a logical consistency-based I/O error: incorrect checksum (expected: 0x34bf84e5; actual: 0x31268142). It occurred during a read of page (1:654) in database...

"Peki tüm bunların yedekleme ile ne ilgisi var kardeşim?" deme noktasına getirdiysem sizi, elbet bir nedeni var. Açıklayayım efendim.

SQL Server 2014 ile birlikte yedek alırken Checksum kontrolü seçeneği de geldi. Bu özellik 2 şekilde kullanılabilir.

1- Instance düzeyinde, "sp_configure" ile aşağıdaki gibi etkinleştirilebilir.

EXEC sp_configure 'backup checksum default', 1;
RECONFIGURE
GO

2- Her bir yedek alma komutuyla birlikte aşağıdaki gibi kullanılabilir:

BACKUP DATABASE X TO DISK = N'xxx' WITH CHECKSUM

Eğer birinci seçeneği kullanırsanız, veritabanı yedekleriniz varsayılan olarak Checksum kontrolü yapılarak alınır ve ilgili sistem tablolarında da kayıtları aşağıdaki gibi görürsünüz:


Bu kullanım size pratikte yukarıda bahsini ettiğim örnekte olduğu gibi bütünlük uyuşmazlığı yaşanan durumlarda haberdar olmanızı sağlayacaktır.

Örneğin test ortamımda bir sayfasını kasten bozduğum bir veritabanım var. Bu veritabanımın yedeğini aşağıdaki komut ile aldığımda hiçbir hata ile karşılaşmıyorum:

USE [master]
GO
BACKUP DATABASE [AdventureWorks2012_corruptionTest] TO DISK = N'C:\temp\corrupt_db.bak';
GO

Fakat aynı yedeği aşağıdaki komut ile alırsam (veya yukarıda 1. seçenek olarak belirttiğim gibi bu özelli Instance düzeyinde etkinleştirirsem)

USE [master]
GO
BACKUP DATABASE [AdventureWorks2012_corruptionTest] TO DISK = N'C:\temp\corrupt_db.bak' WITH CHECKSUM;
GO

O zaman aşağıdaki gibi bir hata alıyorum:

Msg 3043, Level 16, State 1, Line 6
BACKUP 'AdventureWorks2012_corruptionTest' detected an error on page (1:11984) in file 'C:\temp\AdventureWorks2012_Data.mdf'.
Msg 3013, Level 16, State 1, Line 6
BACKUP DATABASE is terminating abnormally.

Sonuç itibariyle, bu tür sorunlardan en kısa sürede haberdar olmak için:
- Tüm veritabanlarınızın Page Verification özelliğinin CHECKSUM olduğundan,
- SQL Server 2014 ve üzeri versiyonlardaki Instance'larınızda "backup checksum default" özelliğini etkinleştirdiğinizden,
- Tüm kritik veritabanlarınız için düzenli olarak DBCC CHECKDB kontrolü yaptığınızdan emin olun.

Olası bir bütünlük sorunundan ne kadar erken haberdar olursanız veri kaybı yaşama olasılığınız o kadar düşük olur. Bu nedenle uygulamalarınızın ihtiyaçlarını da düşünerek olabildiğince çok güvenlik önlemi almanız gerekiyor. Böyle derken kastettiğim şu Checksum ve DBCC CHECKDB gibi uygulamaların elbette bir kaynak bedeli var, CPU ve IO yükünü arttırırlar. Hangi işlemi ne zaman ve nasıl yaptığınız çok önemli. Operasyonlarınızı da aksatmak istemezsiniz, güvenlikten de feragat etmek istemezsiniz. Yarın üzülmemek için kendi ortamınızda, kendi uygulamalarınızın ihtiyaçlarını ve donanım kaynaklarınızı da dikkate alarak testlerinizi yapmalı ve bu uygulamaları devreye almalısınız.

Ekrem Önsoy

Hiç yorum yok: