İÇİNDEKİLER
- •SQL Server’da Shrink Ne Yapar?
- •SQL Server için Uzman Desteğine mi İhtiyacınız Var?
- •Shrink Neden Rutin Bir Bakım İşlemi Olmamalı?
- •AUTO_SHRINK Kapalı Olmalı
- •Shrink Ne Zaman Gerçekten Gerekli?
- •Shrink Öncesi: Gerçekte Ne Kadar Boş Alan Var?
- •Veri Dosyasını Güvenli Şekilde Küçültmek
- •DBCC SHRINKFILE seçenekleri
- •Shrink Sonrası: Fragmentation’ı Giderin
- •Log Dosyasını Küçültmek
- •Shrink Yerine Ne Yapılmalı?
- •Sık Sorulan Sorular
- •Disk Alanı Sorununu Shrink ile Değil, Planla Çözelim
SQL Server’da disk dolmaya başladığında akla gelen ilk komutlardan biri shrink’tir. Doğru durumda, doğru şekilde kullanıldığında gerçekten yer kazandırır. Yanlış kullanıldığında ise index’leri parçalar, saatlerce kaynak tüketir, kullanıcı sorgularını bloklar ve birkaç gün sonra dosya yeniden büyüdüğünde kazanılan alan da kaybolur.
Bu yazıda SQL Server’da shrink’in tam olarak ne yaptığını, neden rutin bir bakım işlemi olmaması gerektiğini, hangi durumlarda gerçekten gerekli olduğunu ve gerektiğinde veri ve log dosyalarının güvenli şekilde nasıl küçültüleceğini adım adım anlatıyoruz.
SQL Server’da Shrink Ne Yapar?
Shrink, bir veritabanı dosyasının diskte kapladığı alanı küçültür. Ancak veri dosyası ile log dosyası için çalışma şekli farklıdır:
- Veri dosyalarında (
.mdf,.ndf): SQL Server, dosyanın sonundaki kullanılan sayfaları dosyanın başındaki boş alanlara taşır. Dosyanın sonunda yeterli boş alan oluştuğunda bu kısım işletim sistemine geri verilir. Bu sayfa taşıma işlemi, shrink’in hem yavaş hem de zararlı olabilmesinin nedenidir. - Log dosyasında (
.ldf): sayfa taşınmaz. Log dosyasının sonundaki kullanılmayan virtual log file (VLF) bölümleri kaldırılır. Log’un sonundaki bölüm hâlâ kullanılıyorsa log, hedef boyuta inmez.
İki komut vardır: DBCC SHRINKDATABASE veritabanının tüm dosyalarını bir yüzde hedefine göre küçültür, DBCC SHRINKFILE ise tek bir dosyayı belirli bir MB hedefine küçültür. Hangi dosyanın ne kadar küçüleceğini kontrol edebildiğiniz için pratikte neredeyse her zaman DBCC SHRINKFILE tercih edilmelidir.
SQL Server için Uzman Desteğine mi İhtiyacınız Var?
Kıdemli veritabanı ekibimiz SQL Server performans ayarlama, sağlık kontrolleri, migrasyonlar, Remote DBA hizmetleri ve acil operasyonel sorunlarda destek sağlar.
Shrink Neden Rutin Bir Bakım İşlemi Olmamalı?
Microsoft bu konuda nettir: shrink işlemleri düzenli bakım olarak görülmemelidir ve düzenli iş yükü nedeniyle büyüyen veri ve log dosyalarının shrink edilmesine gerek yoktur. Nedenleri:
- Index fragmentation: taşınan sayfalar dosyadaki herhangi bir boş yere yerleştirilir. Bu, index’lerin fiziksel sırasını bozar ve büyük aralık taramaları yapan sorguları yavaşlatır.
- Kaynak tüketimi: veri dosyası shrink’i uzun süren, yoğun I/O ve CPU kullanan ve tamamen loglanan bir işlemdir.
- Bloklama: shrink, sayfaları taşırken kısa süreli schema modification (
Sch-M) kilitlerine ihtiyaç duyar. Uzun süren bir sorgu shrink’i bekletebilir; bekleyen shrink’in arkasına yeni sorgular da sıraya girebilir. - Kazanç kalıcı değildir: veritabanı normal çalışırken boş alana ihtiyaç duyar. Küçültülen dosya kısa sürede yeniden büyür; her autogrowth olayı da o sırada işlemleri yavaşlatır. Microsoft’un ifadesiyle, sürekli küçültüp yeniden büyüyen bir veritabanını tekrar tekrar shrink etmek boşa harcanmış bir işlemdir.
Bu nedenle bakım planlarında “Shrink Database” adımı bulunmamalı ve shrink, zamanlanmış bir job ile düzenli çalıştırılmamalıdır. Bakım planlarını nasıl kurgulamanız gerektiğini SQL Server Bakım Planları yazımızda ele aldık.
AUTO_SHRINK Kapalı Olmalı
AUTO_SHRINK seçeneği açık olan bir veritabanında SQL Server, dosyanın %25’inden fazlası boş kaldığında dosyayı arka planda otomatik olarak küçültür. Bu, yukarıdaki tüm sorunları kontrolsüz ve öngörülemez zamanlarda yaşamak demektir. Varsayılan olarak kapalıdır, ancak eski veya taşınmış veritabanlarında açık kalmış olabilir. Tüm sunucuyu tek sorguda kontrol edin:
-- AUTO_SHRINK açık olan veritabanları
SELECT name, is_auto_shrink_on
FROM sys.databases
WHERE is_auto_shrink_on = 1;
-- Kapatmak için
ALTER DATABASE [SalesDB] SET AUTO_SHRINK OFF;
SSMS’te veritabanına sağ tıklayıp Properties → Options sayfasındaki Auto Shrink değerini False olarak da ayarlayabilirsiniz.
Shrink Ne Zaman Gerçekten Gerekli?
Shrink’in meşru olduğu durumlar, büyük miktarda alanın kalıcı olarak boşaldığı ve bir daha kullanılmayacağı durumlardır:
- Büyük bir arşivleme veya veri temizliği sonrasında, silinen verinin geri gelmeyeceği biliniyorsa.
- Büyük tablolar veya kullanılmayan büyük index’ler kalıcı olarak kaldırıldıysa.
- Tek seferlik bir işlem (örneğin büyük bir veri yükleme veya migration) log’u olağan boyutunun çok üzerine çıkardıysa.
- Bir veri dosyası tamamen boşaltılıp veritabanından kaldırılacaksa (
EMPTYFILE).
İpucu
Microsoft da shrink’in en etkili olduğu durumun, büyük bir DELETE, TRUNCATE TABLE veya DROP TABLE gibi büyük miktarda kullanılmayan alan yaratan bir işlemin hemen ardından olduğunu belirtir.
Shrink Öncesi: Gerçekte Ne Kadar Boş Alan Var?
Shrink’e karar vermeden önce her dosyada ne kadar boş alan olduğuna bakın. Aşağıdaki sorgu, ilgili veritabanının içinde çalıştırıldığında her dosya için ayrılmış, kullanılan ve boş alanı MB cinsinden gösterir:
USE [SalesDB];
SELECT name,
type_desc,
CAST(size / 128.0 AS decimal(18, 2)) AS allocated_mb,
CAST(FILEPROPERTY(name, 'SpaceUsed') / 128.0 AS decimal(18, 2)) AS used_mb,
CAST((size - FILEPROPERTY(name, 'SpaceUsed')) / 128.0 AS decimal(18, 2)) AS free_mb,
growth,
is_percent_growth
FROM sys.database_files;
Bir dosyanın içinde boş alan yoksa shrink hiçbir şey kazandırmaz. Log dosyası büyük ama doluysa sorun shrink ile değil, log’un neden temizlenemediğini bularak çözülür. Bunu SQL Server Transaction Log Çok mu Büyük? yazımızda ayrıntılı anlattık.
Veri Dosyasını Güvenli Şekilde Küçültmek
Shrink’in gerçekten gerekli olduğuna karar verdiyseniz, şu adımları izleyin:
- Önce geri yüklenebilir bir backup’ınız olduğundan emin olun.
- Düşük yoğunluklu bir zaman seçin. Shrink sırasında backup alınamaz; backup sırasında da shrink yapılamaz. Bakım pencerenizi backup job’larıyla çakışmayacak şekilde planlayın.
- Gerçekçi bir hedef boyut belirleyin. Dosyayı tamamen sıfıra yakın küçültmeyin; veritabanının önümüzdeki aylarda ihtiyaç duyacağı boş alanı bırakın. Aksi halde dosya hemen yeniden büyür.
- Büyük dosyaları parça parça küçültün. 500 GB’lık bir dosyayı tek komutta 200 GB’a indirmek yerine her seferinde birkaç on GB küçültmek, işlemi daha kontrol edilebilir kılar.
DBCC SHRINKFILEistenildiği an durdurulabilir ve o ana kadar yapılan iş korunur. - Bloklamayı izleyin. SQL Server 2022 ve sonrasında
WAIT_AT_LOW_PRIORITYseçeneğini kullanın. Bu modda shrink, kullanıcı sorgularını bloklamaz; gereken kilidi bir dakika içinde alamazsa kendini sonlandırır.
USE [SalesDB];
-- Dosyanın logical adını ve file_id değerini bulun
SELECT file_id, name, type_desc, size / 128 AS size_mb
FROM sys.database_files;
-- Veri dosyasını 200.000 MB hedefine küçült (adım adım ilerleyin)
DBCC SHRINKFILE (N'SalesDB_Data', 200000);
-- SQL Server 2022+: kullanıcı sorgularını bloklamadan dene
DBCC SHRINKFILE (N'SalesDB_Data', 200000)
WITH WAIT_AT_LOW_PRIORITY (ABORT_AFTER_WAIT = SELF);
Shrink devam ederken ilerlemesini başka bir oturumdan izleyebilirsiniz:
SELECT session_id, command, percent_complete,
estimated_completion_time / 60000 AS est_minutes_left,
blocking_session_id, wait_type
FROM sys.dm_exec_requests
WHERE command LIKE N'Dbcc%';
Shrink, row versioning kullanan (örneğin snapshot isolation altında çalışan) uzun bir transaction tarafından da bekletilebilir. Bu durumda SQL Server, error log’a shrink’in hangi transaction’ı beklediğini belirten bilgi mesajları (SHRINKFILE için 5203) yazar.
DBCC SHRINKFILE seçenekleri
| Seçenek | Ne yapar? | Ne zaman kullanılır? |
|---|---|---|
target_size (MB) |
Sayfaları taşıyarak dosyayı hedef boyuta küçültmeye çalışır. Kullanılan veri miktarının altına inmez. | Standart kullanım. Her zaman açık bir hedef verin. |
TRUNCATEONLY |
Sayfa taşımaz; yalnızca dosyanın sonundaki boş alanı işletim sistemine geri verir. | İlk denenecek seçenek: fragmentation yaratmaz ve hızlıdır. Boş alan dosyanın sonundaysa yeterli olur. |
NOTRUNCATE |
Sayfaları dosyanın başına taşır ama alanı işletim sistemine geri vermez. Yalnızca veri dosyaları için geçerlidir. | Nadiren gerekir. |
EMPTYFILE |
Dosyadaki tüm veriyi aynı filegroup’taki diğer dosyalara taşır ve dosyaya yeni veri yazılmasını engeller. | Bir veri dosyasını veritabanından tamamen kaldırmadan önce (ALTER DATABASE ... REMOVE FILE). |
Bir dosya, oluşturulduğu boyutun veya en son elle ayarlanan boyutun altına DBCC SHRINKDATABASE ile küçültülemez. DBCC SHRINKFILE ise bu minimum boyutu yeni hedefe göre sıfırlayabilir.
Shrink Sonrası: Fragmentation’ı Giderin
Veri dosyası shrink’inden sonra index’ler büyük olasılıkla parçalanmış olur. Microsoft, fragmentation’ı gidermek için shrink sonrasında index’lerin yeniden oluşturulmasını (rebuild) önerir. Burada dikkat edilmesi gereken bir denge vardır:
ALTER INDEX ... REBUILDfragmentation’ı tamamen giderir, ancak index’in yeni bir kopyasını oluşturmak için boş alana ihtiyaç duyar. Büyük bir index’i rebuild etmek, az önce küçülttüğünüz dosyayı yeniden büyütebilir.ALTER INDEX ... REORGANIZEsayfaları yerinde düzenler ve dosyayı büyütmez, ancak fragmentation’ı daha az etkili giderir ve büyük index’lerde uzun sürer.
Not
Pratik yaklaşım: tüm index’leri körü körüne rebuild etmek yerine, sys.dm_db_index_physical_stats ile shrink sonrası gerçekten parçalanmış ve sorgu performansını etkileyen büyük index’leri belirleyip yalnızca onlara müdahale etmek. Shrink hedefinizi, bu rebuild’lerin ihtiyaç duyacağı boş alanı da hesaba katarak belirleyin. Index bakımının güncel yaklaşımı için SQL Server Automatic Index Compaction yazımıza da göz atabilirsiniz.
Log Dosyasını Küçültmek
Log dosyası shrink’i veri dosyasından farklıdır: sayfa taşınmaz, fragmentation oluşmaz. Ancak log yalnızca sonundaki VLF’ler kullanılmıyorsa küçülebilir. Doğru sıra şudur:
- Log’un neden büyüdüğünü bulun ve nedeni çözün (
sys.databasesiçindekilog_reuse_wait_desc). - Full recovery model’de bir log backup alarak log’un temizlenmesini sağlayın.
- Log’u küçültün, ardından gerçek ihtiyaca göre tek adımda yeniden büyütüp sabit bir autogrowth değeri verin. Bu, VLF sayısını da makul seviyede tutar.
USE [SalesDB];
BACKUP LOG [SalesDB]
TO DISK = N'E:\Backup\SalesDB_LOG_before_shrink.trn'
WITH COMPRESSION, CHECKSUM;
DBCC SHRINKFILE (N'SalesDB_log', 1024);
ALTER DATABASE [SalesDB]
MODIFY FILE (NAME = N'SalesDB_log', SIZE = 8192MB, FILEGROWTH = 512MB);
Microsoft’un kendi örneklerinde log’u temizlemek için veritabanını geçici olarak simple recovery model’e almak da gösterilir. Ancak bu, production’daki bir veritabanında log zincirini kırar ve point-in-time restore yeteneğini ortadan kaldırır. Bu yolu kullanmak zorunda kalırsanız hemen full modda geri dönüp bir full backup alın. VLF’lerin performansa etkisi için Yüksek VLF Sayıları SQL Performansınızı Nasıl Öldürür? yazımıza bakabilirsiniz.
Shrink Yerine Ne Yapılmalı?
Shrink’e sık ihtiyaç duyuyorsanız, asıl sorun genellikle başka bir yerdedir:
- Kapasite planlaması: dosyaları gerçek büyüme hızına göre boyutlandırın ve diski buna göre planlayın. Veritabanının kullanmadığı ama ileride kullanacağı boş alan bir sorun değil, bir rezervdir.
- Sabit autogrowth: veri ve log dosyalarında yüzde yerine sabit MB değerleri kullanın.
- Instant file initialization: SQL Server servis hesabına Perform volume maintenance tasks yetkisi vermek, veri dosyası büyümelerini neredeyse anında gerçekleştirir; böylece dosyaları önceden büyük tutmanın maliyeti azalır.
- Arşivleme stratejisi: eski veriyi düzenli olarak ayrı bir veritabanına veya partition’a taşımak, ana veritabanının kontrolsüz büyümesini önler.
- Doğru disk yapılandırması: veri, log ve tempdb dosyalarını uygun disklere yerleştirmek. Bkz. SQL Server’da Disk Depolama İçin Best Practices.
Sık Sorulan Sorular
DBCC SHRINKFILE. Hangi dosyanın hangi boyuta küçüleceğini doğrudan kontrol edebilirsiniz. DBCC SHRINKDATABASE tüm dosyaları bir yüzde hedefine göre küçültür ve log dahil gereksiz dosyalara da dokunabilir.DBCC SHRINKFILE istenildiği an durdurulabilir ve o ana kadar tamamlanan iş korunur. Bu, büyük dosyaları parça parça küçültmeyi güvenli hale getirir. EMPTYFILE ile çalışırken iptal ederseniz dosya yeni veri yazılmasına karşı işaretlenmez.log_reuse_wait_desc ile nedeni bulun, log backup alın ve shrink’i tekrar deneyin.İlgili Yazılar
- SQL Server Transaction Log Çok mu Büyük? Nedenleri, Teşhisi ve Güvenli Çözümü
- Yüksek VLF Sayıları SQL Performansınızı Nasıl Öldürür?
- SQL Server Bakım Planları
- SQL Server Automatic Index Compaction: İndeks Bakımının Sonu mu?
- SQL Server’da Disk Depolama İçin Best Practices
- Yönetilen Veritabanı Hizmetleri
SQL Server Yönetilen DBA Hizmetleri
Disk Alanı Sorununu Shrink ile Değil, Planla Çözelim
Aryasoft’un kıdemli DBA ekibi veritabanı dosyalarınızın büyümesini izler, kapasiteyi planlar ve gerektiğinde shrink ile index bakımını iş yükünüzü aksatmadan, kontrollü şekilde uygular.