Windows’ta Disk I/O Performans Sorunlarını Çözme

Bir production sunucusunda disk I/O kaynaklı yavaşlama yaşamak, gece 2’de çalan bir telefon kadar sinir bozucudur. “Uygulama yavaş” şikayetiyle başlayan süreç, saatler içinde veritabanı ekibiyle, uygulama geliştiricileriyle ve bazen de tedarikçilerle yapılan toplantılara dönüşebilir. Bu yazıda, Windows sunucularda disk I/O performans sorunlarını tespit etmek ve çözmek için kullandığım yöntemleri paylaşacağım.

Önce Sorunun Gerçekten I/O Kaynaklı Olup Olmadığını Doğrula

Klasik bir hata: hemen diske bakmaya başlamak. Ama CPU doygunluğu, bellek yetersizliği veya ağ gecikmesi de aynı semptomlara yol açabilir. Önce doğru düşmanı tanımlamamız lazım.

Performance Monitor (perfmon) ile başlayın. Komut satırından direkt açabilirsiniz:

perfmon /sys

Eklemeniz gereken ilk counter’lar şunlar:

  • PhysicalDiskAvg. Disk Queue Length: 2’nin üzerindeyse alarm verin
  • PhysicalDiskAvg. Disk sec/Read: 20ms üzeri ciddi sorun
  • PhysicalDiskAvg. Disk sec/Write: 20ms üzeri ciddi sorun
  • PhysicalDisk% Disk Time: Sürekli %80 üzeriyse disk doymuş demektir
  • MemoryAvailable MBytes: Düşükse, Windows sanal bellek için diske yazıyor olabilir

Bir de şunu bilmek gerekiyor: Windows’un disk performansını ölçmek için kullandığı bazı counter’lar, disk controller driver’ının güncel olmaması durumunda yanlış değer döndürebilir. Bu yüzden driver güncellemelerini kontrol etmeyi unutmayın.

PowerShell ile Hızlı Durum Tespiti

Bir sunucuya bağlandığınızda ilk 5 dakikada ne yapıyorsunuz? Ben şu scriptle başlıyorum:

# Anlık disk I/O durumunu göster
Get-Counter -Counter "PhysicalDisk(*)Avg. Disk Queue Length",
            "PhysicalDisk(*)Avg. Disk sec/Read",
            "PhysicalDisk(*)Avg. Disk sec/Write",
            "PhysicalDisk(*)Disk Reads/sec",
            "PhysicalDisk(*)Disk Writes/sec" |
Select-Object -ExpandProperty CounterSamples |
Where-Object { $_.InstanceName -ne "_total" } |
Format-Table Path, CookedValue -AutoSize

Bu komut size anlık bir fotoğraf verir. Ama I/O sorunları genellikle anlık değil dönemsel olduğu için, birkaç dakika boyunca örnekleme yapmanız gerekir:

# 60 saniye boyunca her 5 saniyede bir örnekle ve CSV'ye kaydet
$output = @()
1..12 | ForEach-Object {
    $samples = Get-Counter -Counter "PhysicalDisk(*)Avg. Disk Queue Length" |
               Select-Object -ExpandProperty CounterSamples
    $output += $samples | Select-Object Timestamp, InstanceName, CookedValue
    Start-Sleep -Seconds 5
}
$output | Export-Csv -Path "C:Tempdisk_io_log.csv" -NoTypeInformation
Write-Host "Veri toplama tamamlandi: C:Tempdisk_io_log.csv"

Bu CSV’yi daha sonra Excel’de açıp grafik çizdiğinizde, sorunun periyodik mi yoksa sürekli mi olduğunu görebilirsiniz.

Hangi Process Diski Çalıştırıyor?

“Disk dolu” diyorsunuz ama hangi süreç? Bunu bulmak için Process Monitor (ProcMon) kullanmak en sağlıklı yol olsa da, her zaman GUI araçlarına erişiminiz olmaz. PowerShell ile de bu bilgiye ulaşabilirsiniz:

# En fazla I/O yapan process'leri listele
Get-Process | 
Sort-Object -Property @{Expression={$_.WorkingSet64}; Descending=$true} |
Select-Object -First 15 Name, Id, 
    @{N='IO Read MB';E={[math]::Round($_.WorkingSet64/1MB,2)}},
    @{N='Handles';E={$_.HandleCount}} |
Format-Table -AutoSize

# Daha spesifik I/O bilgisi için WMI kullan
Get-WmiObject Win32_PerfRawData_PerfProc_Process |
Where-Object { $_.Name -ne "_Total" -and $_.Name -ne "Idle" } |
Sort-Object -Property IODataOperationsPersec -Descending |
Select-Object -First 10 Name, IODataOperationsPersec, 
              IOReadBytesPersec, IOWriteBytesPersec |
Format-Table -AutoSize

Gerçek bir senaryodan bahsedeyim: Bir müşterimizin SQL Server sunucusunda her gece 23:00-02:00 arası performans düşüşü yaşanıyordu. Kullanıcılar görmüyor ama monitörlerimiz yakalıyordu. Bu scriptle baktığımda, TiWorker.exe (Windows Update) ve Windows Defender’ın aynı anda çalıştığını gördük. SQL Server yedekleme süreciyle üst üste biniyordu. Üç ayrı iş bir arada çalışınca, disk queue length 15-20’ye çıkıyordu.

Resource Monitor ile Gerçek Zamanlı Analiz

Komut satırını seven biri olarak şunu söylemeliyim: bazen GUI araçları işi çok daha hızlı çözer. Resource Monitor bu durumların başında gelir:

# Resource Monitor'u aç
resmon.exe

Disk sekmesinde şunları görebilirsiniz:

  • Hangi process’in hangi dosyaya yazdığı/okuduğu
  • Read ve write hızları
  • Response time değerleri

Özellikle “Disk Activity” bölümü altında dosya yollarına bakın. Eğer bir uygulama log dosyasına saniyede binlerce kez yazıyorsa ve o log dosyası yanlış bir disk partisyonundaysa, çözüm bazen sadece dizin değiştirmek kadar basit olabilir.

Windows Event Log ile Geçmişe Bakma

Sorun şu an olmayabilir ama “dün gece ne oldu?” sorusunu yanıtlamak için Event Log’lara bakın:

# Disk ile ilgili kritik olayları son 24 saate göre filtrele
$startTime = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{
    LogName = 'System'
    Level = 1,2,3
    StartTime = $startTime
} | Where-Object { 
    $_.ProviderName -match 'disk|storage|ntfs|volsnap|storport' 
} | Select-Object TimeCreated, Id, LevelDisplayName, Message |
Format-List

Özellikle dikkat edilmesi gereken Event ID’ler:

  • Event ID 11: Disk hatası, donanım sorunu işareti
  • Event ID 51: Disk I/O hatası, yavaş yanıt
  • Event ID 129: Reset to device issued, controller sorunu
  • Event ID 153: IO operation retried, ciddi gecikme

Bu event’leri periyodik olarak görüyorsanız, donanım arızasına doğru gidiyorsunuz demektir. RAID controller veya disk değişimi gündemdeyse procurement sürecini başlatın.

StorPort ve Disk Performans Logları

Daha derin bir analize ihtiyaç duyduğunuzda, Windows’un yerleşik disk tracing mekanizmasını kullanabilirsiniz:

# Disk performans logunu etkinleştir
# Önce mevcut durumu kontrol et
diskperf -y

# Tüm fiziksel ve mantıksal disk counter'larını etkinleştir
diskperf -yv

# Logman ile detaylı I/O trace başlat
logman create counter DiskIO -c "PhysicalDisk(*)*" "LogicalDisk(*)*" -f csv -o C:TempDiskIO_trace.csv -si 5 -cnf 00:30:00
logman start DiskIO

# 30 dakika sonra durdur
logman stop DiskIO
logman delete DiskIO

Bu trace’i problematik bir zaman diliminde çalıştırıp, sonuçları analiz etmek çok değerli veri üretir. Özellikle dışarıdan izleme araçlarınız yoksa veya SAN/NAS tarafında görünürlüğünüz kısıtlıysa bu yöntem hayat kurtarır.

IOPS Testi ile Temel Hat Belirleme

Bir diskin ne kadar performans vermesi gerektiğini bilmeden sorun çözmek, referans noktası olmadan navigasyon yapmaya benzer. DiskSpd aracı Microsoft’un kendi geliştirdiği ücretsiz bir test aracıdır:

# DiskSpd indir ve çalıştır (Microsoft'un resmi aracı)
# https://github.com/microsoft/diskspd adresinden indir

# Önce DiskSpd'yi C:Tools altına kopyala

# 4K rastgele okuma testi (OLTP workload simülasyonu)
C:Toolsdiskspd.exe -b4K -d30 -o32 -t4 -r -w0 -L C:Temptestfile.dat > C:Tempread_test.txt

# 4K karışık okuma/yazma testi (%70 okuma, %30 yazma)
C:Toolsdiskspd.exe -b4K -d30 -o32 -t4 -r -w30 -L C:Temptestfile.dat > C:Tempmixed_test.txt

# Sonuçları görüntüle
Get-Content C:Tempmixed_test.txt | Select-String "total|Read|Write|Latency"

Bu testleri sunucuyu production’a almadan önce ve sonra çalıştırırsanız, baseline değerleriniz olur. Sonraki performans sorunlarında “disk eskiden bu kadar IOPS veriyordu, şimdi yarıya düştü” diyebilirsiniz, bu ciddi bir fark yaratır.

Parametreler kısaca:

  • -b4K: Blok boyutu 4KB (OLTP için tipik)
  • -d30: 30 saniyelik test süresi
  • -o32: Queue derinliği 32
  • -t4: 4 thread
  • -r: Rastgele I/O
  • -w30: %30 yazma oranı

Sık Karşılaşılan Sorunlar ve Çözümleri

Sayfa Dosyası (Page File) Disk Baskısı

Yanlış yerleştirilmiş veya hatalı yapılandırılmış page file, disk I/O’yu ciddi ölçüde artırabilir. Özellikle RAM yetersiz sunucularda sayfa dosyası defalarca okunup yazılır:

# Mevcut page file ayarlarını kontrol et
Get-WmiObject Win32_PageFileUsage | 
Select-Object Name, AllocatedBaseSize, CurrentUsage, PeakUsage |
Format-List

# Tavsiye: Page file'ı işletim sistemi diskinden ayır
# Bunun için System Properties > Advanced > Performance Settings > Advanced > Virtual Memory
# GUI üzerinden değiştirin ya da PowerShell ile:
$cs = Get-WmiObject Win32_ComputerSystem -EnableAllPrivileges
$cs.AutomaticManagedPagefile = $false
$cs.Put()

Eğer RAM kullanımınız sürekli %85 üzerindeyse, page file ne kadar optimize edilirse edilsin, asıl çözüm RAM eklemektir.

NTFS Fragmentation

Eski bir sorun gibi görünse de, özellikle HDD’li sunucularda fragmentation hala önemli bir etken olabilir. SSD’lerde defragmantasyon yapmayın, Windows bunu zaten yönetiyor:

# Disk fragmantasyon durumunu analiz et
defrag C: /A /V

# Sadece analiz, otomatik optimizasyon için:
Optimize-Volume -DriveLetter C -Analyze -Verbose

# Fragmente durumdaysa optimize et (HDD için)
Optimize-Volume -DriveLetter C -Defrag -Verbose

# SSD için TRIM gönder
Optimize-Volume -DriveLetter C -ReTrim -Verbose

Antivirus Taramalarının I/O Etkisi

Gerçek hayattan bir örnek daha: Bir web sunucusunda günün belirli saatlerinde yanıt süreleri 3-4 kat artıyordu. Saatler harcanıp en sonunda Windows Defender scheduled scan’inin tam öğle vakti çalıştığı ortaya çıktı. IIS log dizinini tararken binlerce küçük dosyayı açıp kapatıyordu.

# Windows Defender dışlama listesini kontrol et
Get-MpPreference | Select-Object ExclusionPath, ExclusionExtension, ExclusionProcess

# Kritik dizinleri dışlama listesine ekle (SQL Server örneği)
Add-MpPreference -ExclusionPath "C:Program FilesMicrosoft SQL Server"
Add-MpPreference -ExclusionExtension ".mdf",".ldf",".ndf"
Add-MpPreference -ExclusionProcess "sqlservr.exe","sqlagent.exe"

# Scheduled scan saatini uygun bir zamana taşı
Set-MpPreference -ScanScheduleDay 0 -ScanScheduleTime 03:00:00

Write Cache ve Flush Davranışları

Disk controller’larında write cache enabled/disabled durumu performansı doğrudan etkiler. Ama dikkatli olmak lazım: write cache açıkken UPS’siz bir güç kesintisi veri kaybına yol açar:

# Disk write cache durumunu kontrol et
Get-Disk | ForEach-Object {
    $disk = $_
    Get-PhysicalDisk | Where-Object { $_.DeviceId -eq $disk.Number } |
    Select-Object FriendlyName, 
                  @{N='WriteCacheEnabled';E={$_.OperationalStatus}}
}

# PowerShell ile disk policy sorgula
$storagePool = Get-StorageSubSystem
Get-PhysicalDisk | Select-Object FriendlyName, OperationalStatus, HealthStatus

Uzun Vadeli İzleme Stratejisi

Tek seferlik incelemeler sorunları çözer ama tekrar yaşanmasını engellemez. Bunun için sürekli izleme şart. Küçük bir PowerShell scripti bile işe yarar:

# Disk I/O alert scripti - Task Scheduler ile her 15 dakikada çalıştır
$threshold = 20  # ms cinsinden maksimum kabul edilebilir yanıt süresi
$logPath = "C:Logsdisk_alerts.log"

$counters = Get-Counter -Counter "PhysicalDisk(*)Avg. Disk sec/Read",
                                  "PhysicalDisk(*)Avg. Disk sec/Write" |
            Select-Object -ExpandProperty CounterSamples |
            Where-Object { $_.InstanceName -ne "_total" }

foreach ($counter in $counters) {
    $valueMs = $counter.CookedValue * 1000  # saniyeyi milisaniyeye çevir
    if ($valueMs -gt $threshold) {
        $message = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') | UYARI: $($counter.Path) = $([math]::Round($valueMs,2)) ms (Esik: $threshold ms)"
        Add-Content -Path $logPath -Value $message
        Write-Warning $message
        
        # Opsiyonel: e-posta gönder
        # Send-MailMessage -To "[email protected]" -Subject "Disk I/O Uyari" -Body $message -SmtpServer "smtp.sirket.com"
    }
}

Bu scripti Task Scheduler’a ekleyin, alert log’larını merkezi bir yerde toplayın. Zaman içinde hangi saatlerde, hangi disklerde sorun yaşandığını görmek, proaktif kapasite planlaması yapmanızı sağlar.

SAN ve NAS Ortamlarında Dikkat Edilmesi Gerekenler

Fiziksel disk üzerinde sorun yoktur ama yine de I/O yavaştır. Bu durumda şüphe SAN/NAS tarafına kayar. Windows sunucu tarafında kontrol edebileceğiniz şeyler:

  • HBA driver sürümleri ve firmware güncelliği
  • Multipath I/O (MPIO) yapılandırması
  • LUN queue depth ayarları
  • iSCSI bağlantısı kullanılıyorsa jumbo frame ve flow control ayarları
# MPIO durumunu kontrol et
Get-MSDSMGlobalDefaultLoadBalancePolicy
Get-MPIOAvailableHW

# iSCSI initiator bağlantı durumu
Get-IscsiSession | Select-Object InitiatorNodeAddress, TargetNodeAddress, 
                                  IsConnected, NumberOfConnections |
Format-Table -AutoSize

# Storport mini-port istatistikleri
Get-StorageReliabilityCounter -PhysicalDisk (Get-PhysicalDisk) |
Select-Object DeviceId, ReadErrorsTotal, WriteErrorsTotal, 
              Temperature, Wear |
Format-Table -AutoSize

Sonuç

Windows’ta disk I/O performans sorunlarını çözmek, tek bir sihirli komut çalıştırıp bitmez. Metodoloji önemli: önce semptomları doğru ölçmek, sonra doğru süreci izole etmek, ardından kök nedeni tespit edip çözmek.

Genel bir sıralama yapacak olursam:

  • Önce Performance Monitor ve Resource Monitor ile hızlı triage yap
  • Hangi sürecin diski yorduğunu WMI veya ProcMon ile belirle
  • Event Log’larda donanım hatası işaretleri ara
  • DiskSpd ile baseline test yap ve mevcut performansla karşılaştır
  • Antivirus, page file, fragmentation gibi “kolay kazanımları” önce ele al
  • SAN/NAS tarafı söz konusuysa storage ekibiyle koordineli çalış
  • Uzun vadeli izleme altyapısı kur, reaktif değil proaktif ol

Disk sorunları çözüldükten sonra yapılan şeyin genellikle bir daha tekrar etmemesi için düzgün bir değişiklik yönetimi süreci yürütmek gerekiyor. Aynı sorunun üç ay sonra tekrar çıkması, hem zaman kaybettirir hem de güven sarsıcıdır. Bir kez çözdüğünüz sorunu belgeleyin, izlemeye alın ve gelecekteki benzer sorunlar için erken uyarı mekanizması kurun.

Bir yanıt yazın

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