MSSQL Server’da Ghost Record ve Ghost Cleanup Task

SQL Server, performans nedenleriyle veriyi silerken satırı sayfadan (page) hemen kaldırmak yerine, satır başlığındaki (record header) bir biti değiştirerek onu Ghost Record olarak işaretler.

SQL Server dünyasının perde arkasında çalışan en gizemli ama en kritik süreçlerden biri olan Ghost Cleanup Task (Hayalet Temizlik Görevi), veritabanı performansını doğrudan etkileyen bir mekanizmadır.

SQL Server’da bir veriyi sildiğinizde (DELETE işlemi), o veri aslında fiziksel olarak diskten anında kazınmaz. Bunun yerine, veri “Hayalet” (Ghost) olarak işaretlenir. Bu “hayaletlerin” temizlenmesi görevini ise Ghost Cleanup Task üstlenir.

  • Neden Hemen Silinmez. Eğer SQL her silme işleminde veriyi fiziksel olarak kaydırıp boşluğu doldurmaya çalışsaydı, işlem çok uzun sürer ve yoğun kilitlenmelere (locking) neden olurdu.

Bu süreç, arka planda (background process) çalışan tek izlekli (single-threaded) bir mekanizmadır. Süreç şu şekilde işler:

  1. Bir işlem veriyi siler ve işlemi “Ghost” olarak işaretleyip commit eder.
  2. Ghost Cleanup Task uyanır ve silinmiş olarak işaretlenen kayıtları barındıran sayfaları tarar.
  3. Bu kayıtları fiziksel olarak sayfadan kaldırır.
  4. Sayfada boşalan alanı sisteme geri kazandırır.

Neden Ghost Record Kullanılır:
1. Performans:
Silme işlemi pahalıdır (özellikle index’lerde). SQL Server, hızlıca işaretleyip gerçek temizliği daha sonra yaparak performansı artırır.
2. Row Versioning / Snapshot Isolation:
Bazı izolasyon seviyelerinde silinen satırın versiyon bilgisinin korunması gerekebilir. Ghost record bu süreçte yardımcı olur.
3. Transaction Rollback:
İşlem geri alınırsa satır yeniden aktif hâle getirilebilir.

Ghost Cleanup Task bir dosttur, ancak bazen performans darboğazlarına neden olabilir:

  • Olumlu Etki: Silme işlemlerinin milisaniyeler içinde tamamlanmasını sağlar. Fiziksel silme işlemini yoğun olmayan zamanlara yayarak kullanıcı deneyimini iyileştirir.
  • Olumsuz Etki (Storage): Eğer temizlik görevi yetişemezse (çok yoğun silme varsa), veritabanı dosyalarınız diskte aslında boş olan ama “hayaletlerle” dolu alanlar yüzünden şişmeye devam eder.
  • CPU Kullanımı: Çok büyük miktarda veri silindiğinde, temizlik görevi arka planda CPU tüketebilir.

Sisteminizde kaç tane temizlenmeyi bekleyen “hayalet” kayıt olduğunu merak ediyorsanız aşağıdaki T-SQL komutlarını kullanabilirsiniz.

Bu komut, her sayfadaki hayalet kayıt sayısını (ghost_record_count) gösterir:

SELECT
DB_NAME() AS DatabaseName,
object_name(p.object_id) AS TableName,
p.index_id,
sum(ps.ghost_record_count) AS TotalGhostRecords
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') AS ps
JOIN sys.partitions AS p ON ps.object_id = p.object_id AND ps.index_id = p.index_id
GROUP BY p.object_id, p.index_id;
  • TableName / index_id: Hangi tabloda ve hangi endekste bu kayıtların olduğunu gösterir.
  • TotalGhostRecords: Bu sütundaki değerlerin neredeyse tamamı 0. Sadece CommandLog tablosunda 1 adet kayıt görünüyor.

Performans testleri için bu görevi kapatmak isterseniz (üretim ortamında yapılması önerilmez):

-- Ghost Cleanup Task'ı durdurmak için
DBCC TRACEOFF (661, -1);

-- Tekrar başlatmak için
DBCC TRACEON (661, -1);

Eğer sisteminizde çok yüksek miktarda DELETE işlemi yapılıyor ve disk alanınız beklenmedik şekilde doluyorsa, Ghost Cleanup Task yetişemiyor olabilir. Bu durumda:

  • Büyük silme işlemlerini küçük parçalar (batch) halinde yapın.
  • Mümkünse DELETE yerine TRUNCATE kullanın (TRUNCATE işlemi Ghost Record oluşturmaz, direkt sayfayı serbest bırakır).

Özetle: Ghost Cleanup Task, SQL Server’ın performansını korumak için tasarlanmış, verileri “mantıksal” olarak sildikten sonra “fiziksel” temizliği yapan verimli bir temizlik işçisidir.

Yukarıdaki tabloda dönen değerlerin 0 veya çok düşük olması iyidir. Bu, sisteminizin silme işlemlerinden sonra temizlik işlemini (Ghost Cleanup) başarıyla gerçekleştirdiğini gösterir.

Eğer bu sayı binlerce veya milyonlarca olsaydı, şu sorunlardan şüphelenebilirdik:

  • Uzun Süren İşlemler: Aktif bir “Transaction” (işlem) bitmediği sürece SQL Server bu kayıtları silemez.
  • Aşırı Silme İşlemi: Çok kısa sürede çok fazla veri silinmişse, arka plandaki temizleme süreci (Ghost Cleanup Thread) yetişemiyor olabilir.
  •   G/Ç (I/O) Darboğazı: Disk yazma hızınız çok düşükse, temizleme işlemi kuyruğa girebilir.

Sorgu sonucunda binlerce hayalet kayıt görüyorsanız ve bu sayı zamanla azalmıyorsa:

 1. Index Rebuild: Yoğunluğun az olduğu bir zamanda endeksi yeniden oluşturmak (rebuild) bu kayıtları fiziksel olarak hemen temizler.

Bir index’i REBUILD ettiğinizde, SQL Server tabloyu veya index’i fiziksel olarak yeniden oluşturur. Bu işlem sırasında tüm “Ghost” kayıtlar pas geçilir ve yeni oluşturulan yapı tamamen temiz olur.

-- Belirli bir tablodaki tüm hayalet kayıtları temizlemek için en etkili yöntemdir
ALTER INDEX ALL ON TabloAdiniz REBUILD;

-- Eğer tablo çok büyükse ve kesinti istemiyorsanız (Enterprise Edition gerektirir)
ALTER INDEX ALL ON TabloAdiniz REBUILD WITH (ONLINE = ON);

 2. Açık İşlemleri Kontrol Edin: DBCC OPENTRAN komutu ile arka planda kalmış, tamamlanmamış bir işlem olup olmadığını kontrol edin.

 3. İstatistik Güncelleme: Hayalet kayıtların çok olması, Cardinality Estimation (satır tahminleme) hatalarına yol açarak sorgu performansını düşürebilir.

Heap tablolarda “ghost page” diye adlandırılan şey aslında SQL Server’da teknik olarak “ghost record” (hayalet kayıt) kavramına dayanır.
Genelde günlük dilde ghost page dense de, doğru terim ghost record’dur. Heap tablolarda bu durum daha sık ve görünür olur.

SQL Server’da gizli (undocumented) bir komut olan bu araç, Ghost Cleanup görevini beklemeden manuel olarak tetiklemeye çalışır. Ancak unutmayın; eğer sistem o an çok yoğunsa, SQL Server bu komutu düşük öncelikli sıraya alabilir.

-- Veritabanı bazında hayalet temizliğini zorlar
DBCC FORCEGHOSTCLEANUP ( 'Veritabani_Adiniz' );
GO

Eğer temizlik bir türlü gerçekleşmiyorsa, şu üç durumu kontrol etmelisiniz:

  • Açık Transaction’lar: Eğer çok eski bir BEGIN TRAN komutu açık kaldıysa ve kapatılmadıysa (Commit/Rollback), SQL Server o işlemden sonrasını temizleyemez.
    • Kontrol: DBCC OPENTRAN
  • Snapshot Isolation / Versioning: Eğer Snapshot Isolation kullanıyorsanız, bu veriye hala ihtiyaç duyan bir sorgu olduğu sürece SQL Server o kayıtları “Ghost” olarak tutmaya devam eder.
  • Always On / Mirroring: İkincil sunucuda (Secondary) bir sorun varsa veya veri henüz oraya yazılmadıysa, ana sunucu (Primary) kayıtları temizlemeyebilir.

Bu işlemin sabit bir “X dakikada bir çalışır” kuralı yoktur; ancak genel çalışma prensibi genellikle her 5 saniyede bir uyanır ve temizlenecek iş olup olmadığına bakar. Eğer temizlenecek çok fazla kayıt varsa, sistem kaynaklarını (CPU/IO) aşırı tüketmemek için kısa süre çalışıp tekrar uykuya dalar. Bu işlem düşük öncelikli bir arka plan görevidir. Eğer sunucu o an çok yoğunsa (yüksek CPU kullanımı varsa), Ghost Cleanup işlemi yavaşlar veya beklemeye alınır.

Bu makalede Ghost Record ve Cleanup Task işlemlerini detaylı bir şekilde görmüş olduk. Başka makalede görüşmek dileğiyle..

Huzur Allah’tandır. (Necm-43)

Author: Yunus YÜCEL

Bir yanıt yazın

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