SQL Server Always On Availability Groups (AG) mimarisinde, yüksek erişilebilirlik ve veri güvenliği birincil önceliktir. Ancak, özellikle büyük ölçekli veritabanlarında gerçekleştirilen Index Rebuild gibi yoğun I/O işlemlerinde, sistemin doğal işleyişi bazen beklenmedik performans sorunlarına yol açabilir. Bu makalede, bir Rebuild işleminin Transaction Log (LDF) dosyası üzerindeki etkilerini, log yedeklemesine rağmen neden yer açılamadığını ve Secondary sunuculardaki veri gecikmesinin (Redo Queue) teknik nedenlerini inceleyeceğiz.
SQL Server’da veritabanı üzerinde yapılan her işlem (INSERT, UPDATE, DELETE, REBUILD vb.), Transaction Log dosyasına LSN (Log Sequence Number) adı verilen benzersiz ve ardışık numaralarla kaydedilir. Log yapısı doğası gereği sıralı bir işleyişe sahiptir.
Büyük bir Index Rebuild işlemi başlatıldığında, bu operasyon devasa sayıda LSN kaydı oluşturur. Ancak bu süreçte veritabanı dış dünyaya kapalı değildir; kullanıcıların yaptığı küçük çaplı işlemler de aynı LDF dosyasına yeni LSN değerleriyle, Rebuild kayıtlarının arasına bir örgü (interleaved) gibi yazılmaya devam eder.
Rebuild işlemi, SQL Server tarafından tek ve büyük bir Transaction olarak kabul edilir. Bu durum, log yönetimi açısından kritik bir kısıtlamayı beraberinde getirir:
- SQL Server’da bir işlem bitip COMMIT edilmeden, o işleme ait en eski LSN (MinLSN) “Aktif Log” olarak kabul edilir.
- Siz log yedeği (Log Backup) alsanız dahi, yedeğe alınan veriler diskten silinemez (Truncate edilemez). Çünkü SQL Server, devam eden bir işlemin (Rebuild) olası bir hata durumunda geri dönülebilmesi (Rollback) için o log kayıtlarına ihtiyaç duyar.
Rebuild işlemi LSN 1000’de başladı ve hala devam ediyor. Bu sırada LSN 12000’e kadar birçok farklı işlem de loglandı. Siz log yedeği aldığınızda 1000 ile 12000 arası yedeklenir; ancak Rebuild bitmediği sürece MinLSN hala 1000 olduğu için log dosyasında 1 byte bile yer açılmaz.
MinLSN Neden Bir Çapa (Anchor) Görevi Görür?
Senaryomuzu teknik bir çizelgeye oturtursak:
- LSN 1000: Rebuild işlemi başladı (MinLSN buraya çakıldı).
- LSN 1001 – 4999: Rebuild’in bir kısmı ve araya giren diğer kullanıcıların (INSERT/UPDATE) işlemleri.
- LSN 5000: Rebuild hala devam ediyor (Şu anki yazma noktası).
- LSN 5001 – 12000: Rebuild devam ederken arkadan gelen diğer tüm işlemler.
Bu noktada log yedeği aldığınızda, SQL Server 1000 ile 12000 arasındaki her şeyi yedek dosyasına yazar. Ancak LDF dosyasında yer açmaya (Truncate) geldiğinde şuna bakar:
“Şu an sistemde hala çalışan en eski işlem hangisi? LSN 1000’de başlayan Rebuild. O zaman ben LSN 1000’den önceki yerleri boşaltabilirim ama 1000 ve sonrasına dokunamam.”
“Rebuild 5000’de, ama 5001 ile 12000 arasındaki işlemler bitti (Commit oldu), onları neden silmiyoruz?” diye düşünebilirsiniz. Sebebi Log Dosyasının Dairesel (Circular) Yapısıdır:
- Sıralı Takip: SQL Server logları bir zincir halkası gibi birbirine bağlıdır. Zincirin en başındaki halka (LSN 1000) kopmadan, zincirin ortasındaki veya sonundaki halkaları çıkarıp atamazsınız.
- Fiziksel Dosya Düzeni: Log dosyası (LDF) sanal log dosyalarından (VLF) oluşur. Rebuild’in başladığı VLF “Active” olarak işaretlendiği için, o VLF ve ondan sonra gelen tüm VLF’ler (içindeki işlemler bitmiş olsa bile) Rebuild bitene kadar “Active” statüsünde kalmaya mahkumdur.
Rebuild işlemi 5000 LSN değerinde olsa bile, bu işlemin başlangıç noktası (LSN 1000) hala “yaşıyor” kabul edilir. Bu “yaşayan” en eski nokta, log dosyasının önünü tıkayan bir baraj gibidir. Baraj yıkılmadan (Rebuild COMMIT olmadan) arkasındaki hiçbir su (diğer LSN’ler) tahliye edilemez.
Always On mimarisinde veri aktarımı iki temel aşamadan oluşur: Send (Gönderme) ve Redo (İşleme).
- Gönderme (Send): Primary sunucu, Rebuild sırasında oluşan log bloklarını anlık olarak Secondary sunucuya iletir. Çoğu zaman ağ hızı yeterliyse loglar hızla karşı tarafa ulaşır (Harden süreci).
- Yazma (Redo): Gecikmenin asıl kaynağı burasıdır. Secondary sunucu, aldığı logları veritabanına sırayla işlemek zorundadır. SQL Server’ın WAL (Write Ahead Logging) prensibi gereği log hiyerarşisi bozulamaz.
Secondary sunucudaki Redo Thread, LSN 1000’den başlayan o devasa Rebuild operasyonunu veritabanına yazarken, arkadan gelen (örneğin LSN 12000’deki) küçük bir INSERT işlemine sıra gelmez. Rebuild işlemi bitene kadar aradaki tüm işlemler kuyrukta bekler. Bu durum, Secondary sunucuda 1-2 günlük, hatta daha uzun süreli veri gecikmelerine (Redo Queue) neden olabilir.
Index Rebuild operasyonları tamamlanıp COMMIT edilene kadar; ne LDF dosyasındaki şişme durur, ne de Secondary sunucu güncel verilere ulaşabilir. Operasyon bittiği anda, alınacak ilk log yedeği ile devasa alan temizlenir ve Secondary tarafındaki kuyruk erimeye başlar.
Büyük tablolarda bu darboğazı yönetmek için şu adımlar izlenmelidir:
- Disk Alanı Kontrolü: İşlem süresince log dosyasının aşırı büyüme ihtimaline karşı disk kapasitesi önceden doğrulanmalıdır.
- Resumable Index Rebuild: SQL Server 2017 ve üzeri sürümlerde RESUMABLE = ON seçeneği kullanılmalıdır. Bu sayede işlem parçalara bölünebilir; her duraklatma (Pause) anında o ana kadar olan loglar truncate edilebilir ve sistem nefes alır.
- Operasyon sırasında sys.dm_exec_requests ve sys.dm_os_waiting_tasks üzerinden log hızı ve bekleme türleri anlık takip edilmelidir.
Başka makalede görüşmek dileğiyle..
Emanetlerinizi ve sözlerinizi tutun. Müminun-8
