Disk I/O darboğazı tespiti, sunucu teşhisinde en çok atlanan adımdır çünkü belirtileri başka bir sorunun belirtileriyle birebir örtüşür. Site yavaşlar, yük ortalaması tırmanır, sayfa süreleri uzar — bakan kişi "CPU yetmiyor" der ve daha güçlü bir pakete geçer. Sonra hiçbir şey değişmez, çünkü işlemci zaten boştaydı; sadece diskin cevap vermesini bekliyordu.
Bu iki durumu ayırmak aslında tek bir sütuna bakmak kadar kolaydır ve bu yazıda önce o sütunu tanıtacağım. Ardından iostat ve iotop ile hangi cihazın doyduğunu ve hangi sürecin diski doldurduğunu nasıl bulacağını, disk gecikmesinin sayfa sürelerine nasıl yansıdığını ve darboğazı gidermek için hangi sırayla müdahale etmen gerektiğini anlatacağım. Komutların hepsi çalışır durumda; kendi sunucunda doğrudan deneyebilirsin.
iowait: Teşhisin Başladığı Tek Sayı#
iowait, işlemcinin boşta olduğu ama tamamlanmamış bir disk isteği beklediği zamanın yüzdesidir. Tanımdaki "boşta" kelimesi kritiktir: iowait yüksekken CPU aslında iş yapmıyordur, elleri bağlı beklemektedir. Bu yüzden yüksek iowait gördüğünde daha fazla çekirdek almak hiçbir sorunu çözmez.
En hızlı bakış vmstat iledir:
# Beş saniyelik örnekleme: wa sütunu iowait yüzdesidir
vmstat 2 5
# procs -----------memory---------- ---swap-- -----io---- --system-- ------cpu-----
# r b swpd free buff cache si so bi bo in cs us sy id wa st
# 2 6 0 240112 8200 3120044 0 0 4820 1960 2100 4300 9 4 21 66 0
# Yukarıda: wa=66 -> CPU zamanının üçte ikisi disk beklemekle geçiyor
# us=9 -> uygulama neredeyse hiç çalışmıyor
Bu çıktıdaki b sütunu da öğreticidir: kesintisiz uykuda bekleyen süreç sayısını gösterir ve neredeyse her zaman disk beklemesini işaret eder. b sürekli sıfırdan büyükse süreçler diskte kuyruktadır.
Tabloyu doğru okumak için üç senaryoyu birbirinden ayırman gerekir:
us | wa | st | Teşhis | Doğru hamle |
|---|---|---|---|---|
| Yüksek | Düşük | Düşük | Gerçek CPU yükü | Önbellek, kod, çekirdek sayısı |
| Düşük | Yüksek | Düşük | Disk darboğazı | Bu yazının konusu |
| Düşük | Düşük | Yüksek | Aşırı satılmış düğüm | Sağlayıcıyla konuş |
| Düşük | Yüksek | Düşük | Takas trafiği olabilir | Önce si/so sütunlarına bak |
Son satır önemli bir tuzağa işaret eder: swap trafiği de iowait olarak görünür. Yani yüksek iowait gördüğünde ilk ayırman gereken şey, diskin gerçek uygulama verisi mi yoksa takasa itilen bellek sayfaları mı taşıdığıdır. vmstat çıktısındaki si ve so sütunları sürekli sıfırdan büyükse sorun aslında bellektedir ve çözüm disk tarafında değildir — o durumun tam anlatımı RAM yetersizliği ve swap etkisi yazısında.
iostat ile Cihaz Düzeyinde Ölçüm#
iowait sana bir sorun olduğunu söyler ama hangi diskte olduğunu söylemez. Onu iostat gösterir. Bu araç sysstat paketiyle gelir; kurulu değilse dağıtımının paket yöneticisinden eklemen gerekir.
# Genişletilmiş istatistikler, 2 saniyede bir, 5 örnek
# İlk örnek açılıştan beri olan ortalamadır, ONU YOK SAY
iostat -xz 2 5
# Örnek (ilgili sütunlar):
# Device r/s w/s rkB/s wkB/s r_await w_await aqu-sz %util
# nvme0n1 820.0 310.0 12400.0 8200.0 0.42 0.61 1.20 18.5
# sda 95.0 40.0 1520.0 980.0 24.80 31.40 9.80 99.2
Bu çıktıda dört sütun her şeyi söyler:
%util— cihazın ne kadar zamanının istek işlemekle geçtiği. 90'ın üstü doyum işaretidir. Ancak dikkat: modern NVMe sürücülerde bu değer paralel kuyruk yapısı nedeniyle yanıltıcı olabilir, tek başına karar verme.r_await/w_await— bir okuma/yazma isteğinin ortalama tamamlanma süresi (milisaniye). NVMe'de tipik olarak 1 ms'nin altında, iyi bir SATA SSD'de birkaç milisaniye olmalıdır. Yukarıdaki örnektesdaiçin 24-31 ms görülüyor; bu, isteklerin kuyrukta beklediğini gösterir.aqu-sz— ortalama kuyruk uzunluğu. Sürekli 1'in belirgin üstündeyse cihaza gelen iş, cihazın işleyebildiğinden fazladır.r/svew/s— saniyedeki okuma ve yazma işlemi sayısı; yükün okuma mı yazma mı ağırlıklı olduğunu söyler.
Yukarıdaki örnek tablo çok net bir teşhis içeriyor: nvme0n1 rahat çalışıyor (%util 18, await 0,4 ms) ama sda tamamen doymuş (%util 99, await 25-31 ms, kuyruk 9,8). Yani sunucuda iki disk var ve iş yükünün yanlış olanının üzerinde olduğu anlaşılıyor — bu, veritabanının ya da günlük dosyalarının yanlış diskte durduğu klasik durumdur.
⚠️ İlk iostat örneğini her zaman yok say; o değerler sistemin açılışından bu yana geçen sürenin ortalamasıdır ve anlık durumu yansıtmaz. Bu, aracı ilk kullananların en sık yaptığı hatadır.
Hangi Süreç Diski Dolduruyor#
Cihazı bulduktan sonra sıra sorumluyu bulmaya gelir. iotop bunun için tasarlanmıştır ve kök yetkisi gerektirir:
# Yalnızca gerçekten I/O yapan süreçleri toplu modda listele
sudo iotop -b -o -n 3 -d 2 | head -30
# Kümülatif mod: hangi süreç toplamda en çok okuma/yazma yaptı
sudo iotop -b -o -a -n 2 -d 5 | head -20
-o bayrağı boşta olan süreçleri gizler, -a ise anlık hız yerine birikimli toplamı gösterir. İkinci komut özellikle yararlıdır: anlık ölçümde göze çarpmayan ama sürekli az az yazan bir süreç (örneğin ayrıntılı hata ayıklama günlüğü açık kalmış bir uygulama) toplamda listenin başında çıkar.
iotop kurulu değilse çekirdeğin kendi sayaçlarına doğrudan bakabilirsin:
# Süreç başına toplam okunan/yazılan bayt (kök yetkisi gerekir)
for p in /proc/[0-9]*; do
[ -r "$p/io" ] || continue
r=$(awk '/^read_bytes/{print $2}' "$p/io")
w=$(awk '/^write_bytes/{print $2}' "$p/io")
t=$(( (r + w) / 1048576 ))
[ "$t" -gt 100 ] && echo "$t MB $(cat $p/comm) pid=$(basename $p)"
done | sort -rn | head -15
Bu döküm, süreçlerin başlangıcından bu yana toplam disk trafiğini MB cinsinden verir. Listenin başında beklemediğin bir şey varsa (bir yedekleme aracı, bir arama indeksleyici, bir günlük toplayıcı) sorunu bulmuşsun demektir.
Veritabanı listenin başındaysa bir adım daha atman gerekir: veritabanı diske gitmek zorunda mı, yoksa bellek havuzu küçük olduğu için mi gidiyor?
-- Havuzdan karşılanan okuma vs diskten okuma
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';
-- Innodb_buffer_pool_reads (diskten) / Innodb_buffer_pool_read_requests (toplam)
-- Bu oran binde birkaçın üstündeyse havuz küçük demektir
-- Havuz boyutunu gör
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
-- Yavaş sorguları yakala: indekssiz bir sorgu tek başına diski doldurabilir
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5;
Çoğu durumda cevap "havuz küçük"tür ve çözüm disk değiştirmek değil, belleği doğru dağıtmaktır.
Disk Gecikmesi Sayfa Süresine Nasıl Yansır#
Disk darboğazının sinsi tarafı, tek bir yavaş işlemin görünmez olmasıdır. 20 milisaniyelik bir disk erişimi hiçbir şey gibi durur — ama bir sayfa yüklemesi sırasında yüzlerce disk erişimi olur ve bunlar toplanır.
Somut bir örnek üzerinden düşün: bir sayfa üretilirken 150 küçük dosya okuması ve 40 veritabanı sayfası erişimi yapılıyor olsun. Disk gecikmesi 0,4 milisaniye ise toplam disk maliyeti yaklaşık 76 milisaniyedir ve fark edilmez. Aynı sayfa, await değeri 25 milisaniyeye çıkmış doymuş bir diskte 4,75 saniye disk beklemesi üretir. Kod aynıdır, sunucu aynıdır, tek değişen diskin kuyruk durumudur.
Bu yüzden disk teşhisinde ortalamalara değil kuyruk davranışına bakmak gerekir. Sistem hafif yüklüyken ölçüm alırsan her şey mükemmel görünür; darboğaz yalnızca eşzamanlılık arttığında ortaya çıkar. Ölçümlerini mutlaka tepe saatte al.
Sunucu ile site arasındaki bağı doğrulamak için ikisini eşzamanlı ölçebilirsin:
# Bir terminalde disk durumunu izle
iostat -xz 2 30
# Başka bir terminalde aynı anda sayfa sürelerini ölç
for i in $(seq 1 30); do
curl -s -o /dev/null -w "$(date +%T) ttfb=%{time_starttransfer}\n" https://firmaniz.com/
sleep 2
done
await değerinin tırmandığı anlarla TTFB'nin tırmandığı anlar örtüşüyorsa nedensellik kanıtlanmıştır. Örtüşmüyorsa yavaşlığın sebebi başkadır ve disk tarafında harcayacağın zamanı kurtarmış olursun.
Darboğazı Giderme Sırası#
Teşhis netleştikten sonra müdahale sırası şudur; en ucuz ve en etkiliden başlar.
Birinci adım: diske hiç gitme. Tam sayfa önbelleği devredeyken bir istek ne PHP dosyalarını okur ne de veritabanına gider. Bu, disk yükünü azaltmanın en radikal yoludur ve maliyeti sıfırdır. Kurulum için Nginx FastCGI cache yapılandırma ya da LiteSpeed Cache yazılarına bakabilirsin.
İkinci adım: sıcak veriyi belleğe al. Veritabanı tampon havuzunu doğru boyutlandırmak, çoğu sunucuda disk okumalarının büyük kısmını ortadan kaldırır. Nesne önbelleği (Redis, Memcached) ise sorgu sonuçlarını bellekte tutarak aynı işi uygulama katmanında yapar; Memcached nedir yazısı bu katmanı anlatıyor.
Üçüncü adım: gereksiz yazmayı kes. Disk darboğazlarının şaşırtıcı biçimde büyük kısmı yazma kaynaklıdır ve suçlu genellikle günlüklerdir. Kontrol edilecekler: ayrıntılı hata ayıklama günlüğü üretimde açık kalmış mı, erişim günlüğü her isteği diske yazıyor mu, oturum dosyaları diskte mi tutuluyor, uygulama her sayfada bir sayaç güncelliyor mu.
# Son 24 saatte en çok büyüyen dosyalar: sürekli yazılanları bulur
find /var/log /var/www -type f -mmin -1440 -size +50M -exec ls -lh {} \; 2>/dev/null | head -20
# Dosya sistemi bağlama seçenekleri: noatime her okumada yazmayı önler
mount | grep -E "^/dev"
atime güncellemesi klasik bir gizli yazma kaynağıdır: varsayılan ayarlarda her dosya okuması bir zaman damgası yazması tetikleyebilir. Çoğu modern dağıtım bunu relatime ile hafifletir ama yoğun okuma yapan sunucularda noatime ile tamamen kapatmak ölçülebilir kazanç sağlar.
Dördüncü adım: yükü zamana yay. Yedekleme, arşivleme, günlük döndürme ve toplu içe aktarma gibi işler diski doyurur. Bunları trafiğin düşük olduğu saatlere al ve mümkünse önceliklerini düşür:
# Yedeklemeyi düşük I/O önceliğiyle çalıştır: canlı trafiği ezmez
ionice -c 3 nice -n 19 tar -czf /yedek/site-$(date +%F).tar.gz /var/www/firmaniz.com
# ionice -c 3 = "idle" sınıfı: yalnızca disk boştayken çalışır
ionice -c 3 bayrağı, işi yalnızca disk boştayken çalıştırır; yedekleme süresi uzar ama canlı trafiği hiç etkilemez. Bu tek satır, "her gece 3'te site donuyor" şikâyetlerinin büyük kısmını çözer.
Beşinci adım: donanımı değiştir. Yukarıdakileri yaptıktan sonra hâlâ doyumdaysan gerçekten daha hızlı diske ihtiyacın var demektir. Bu noktada NVMe'ye geçmek anlamlıdır; ne kadar fark yaratacağını NVMe ve SATA SSD hız farkı yazısında ölçümlerle karşılaştırdım.
Paylaşımlı Hostingde Disk Teşhisi#
Paylaşımlı bir pakette iostat ve iotop çalıştıramazsın; bu araçlar sistem geneli bilgi verdiği için kısıtlanmıştır. Ama teşhis yine de mümkündür.
Birinci yöntem, kontrol panelindeki kaynak grafiklerine bakmaktır. Modern paylaşımlı sunucularda hesap başına disk işlemi (IO ve IOPS) kotası vardır ve panelde ihlal sayısı görünür. Bu kotaya çarpıyorsan sağlayıcı seni yavaşlatıyor demektir; belirtisi tam olarak disk darboğazıyla aynıdır. Kotaların nasıl işlediğini paylaşımlı hostingde hız limitleri yazısında anlattım.
İkinci yöntem, kendi hesabındaki disk trafiğini azaltmaktır. Paylaşımlı ortamda en sık görülen disk tüketicileri şunlardır:
- Site içine yedek alan eklentiler — hem yazma yapar hem inode tüketir.
- Diskte tutulan oturum dosyaları ve temizlenmeyen geçici klasörler.
- Yükleme anında görsel yeniden boyutlandırma yapan eklentiler.
- Ayrıntılı hata ayıklama günlüğünün üretimde açık kalması.
- Arama indeksi oluşturan eklentilerin sürekli yeniden indeksleme yapması.
Üçüncü yöntem ise davranışsal testtir: statik bir dosya ile dinamik bir sayfayı karşılaştır. İkisi de yavaşsa ve TLS süresi normalse disk ya da genel sunucu doygunluğu olasıdır; yalnızca dinamik sayfa yavaşsa sorun büyük olasılıkla CPU ya da veritabanı tarafındadır. Bu ayrımın ayrıntısı CPU limiti aşımı kaynaklı yavaşlama yazısında.
Sık Yapılan Hatalar#
iowait'i CPU yükü sanmak. Yük ortalaması yüksek diye çekirdek eklemek, iowait yüksekken atılan en pahalı yanlış adımdır. İşlemci zaten boştur.
iostat çıktısının ilk örneğine bakmak. İlk satır açılıştan bu yana olan ortalamadır ve anlık durumu göstermez. Her zaman ikinci ve sonraki örnekleri oku.
Swap trafiğini disk sorunu sanmak. Takasa itilen bellek sayfaları da iowait üretir; si/so sütunlarını kontrol etmeden disk yükseltmeye kalkma.
Sadece %util değerine bakmak. Modern NVMe sürücülerde bu sayaç paralel kuyruk yapısı yüzünden yanıltıcı olabilir; asıl kanıt await ve aqu-sz değerleridir.
Ölçümü boş saatte yapmak. Disk darboğazı bir kuyruk problemidir ve kuyruk yalnızca eşzamanlılık artınca oluşur. Gece alınan ölçüm sana hiçbir şey söylemez.
Yedeklemeyi öncelik ayarı olmadan çalıştırmak. Canlı trafikle aynı öncelikte çalışan bir yedekleme, her gece siteyi dize getirir. ionice -c 3 ile çözülür.
Hata ayıklama günlüğünü üretimde açık unutmak. Ayrıntılı günlük, yoğun bir sitede günde gigabaytlarca yazma üretir ve hem diski hem disk alanını tüketir.
Sıkça Sorulan Sorular#
iowait yüzde kaç olursa sorun sayılır#
Tek bir eşik yoktur çünkü değer çekirdek sayısına ve iş yükünün doğasına bağlıdır. Pratik kural şudur: wa değeri sürekli yüzde 20'nin üstündeyse ve aynı anda us düşükse ciddi bir disk darboğazı vardır. Kısa süreli tepeler (yedekleme, güncelleme) normaldir; kalıcı yüksek iowait ise sorunun ta kendisidir. Kararı wa ile birlikte await ve aqu-sz değerlerine bakarak ver.
iostat çıktısında hangi sütuna bakmalıyım#
Öncelik sırası şudur: r_await/w_await (istek başına ortalama bekleme, milisaniye), aqu-sz (ortalama kuyruk uzunluğu) ve son olarak %util. NVMe'de await 1 ms'nin altında, iyi bir SATA SSD'de birkaç milisaniye olmalıdır; onlarca milisaniye görüyorsan istekler kuyrukta bekliyor demektir. %util tek başına yanıltıcı olabilir, özellikle paralel kuyruklu NVMe sürücülerde.
Hangi sürecin diski doldurduğunu nasıl bulurum#
En doğrudan yol sudo iotop -b -o -n 3 -d 2 komutudur; -o bayrağı boşta olan süreçleri gizler. Birikimli toplamı görmek için -a bayrağını ekle — anlık ölçümde göze çarpmayan ama sürekli az az yazan süreçler orada ortaya çıkar. iotop kurulu değilse /proc/[pid]/io dosyalarından süreç başına toplam okuma/yazma baytlarını okuyabilirsin.
Disk sorununu bellekle çözebilir miyim#
Çoğu zaman evet ve bu genellikle en ucuz çözümdür. Sıcak veri belleğe sığdığında disk erişimi kendiliğinden azalır: veritabanı tampon havuzunu büyütmek, nesne önbelleği kurmak ve tam sayfa önbelleği devreye almak disk okumalarının büyük kısmını ortadan kaldırır. Yalnız dikkat: belleği aşırı ayırırsan sistem takasa düşer ve bu, disk sorununu çözmek yerine ikiye katlar.
Yedekleme sırasında sitem neden yavaşlıyor#
Çünkü yedekleme, diskten yoğun okuma ve arşive yoğun yazma yapar; canlı trafikle aynı öncelikte çalıştığında disk kuyruğunu doldurur ve tüm istekler beklemeye başlar. Çözüm yedeklemeyi ionice -c 3 nice -n 19 ile düşük öncelikte çalıştırmak ve trafiğin en düşük olduğu saate almaktır. Yedek dosyasını farklı bir diske ya da uzak bir hedefe yazmak da yükü belirgin biçimde dağıtır.
iowait yüksek ama disk testi hızlı çıkıyor, neden#
Büyük ihtimalle testi yanlış yapıyorsun. Sistem boştayken alınan disk testi cihazın en iyi hâlini ölçer; darboğaz ise yalnızca eşzamanlılık artınca oluşan bir kuyruk problemidir. Testini tepe saatte tekrarla ve fio kullanıyorsan yüksek kuyruk derinliğiyle (örneğin --iodepth=32 --numjobs=4) çalıştır. Ayrıca dd ile test ediyorsan oflag=dsync bayrağını unutma; yoksa diski değil belleği ölçersin.
Kapanış#
Disk darboğazı teşhisinde dört alışkanlık seni yanlış yollardan kurtarır. Birincisi, her performans şikâyetinde önce vmstat çıktısına bak ve us, wa, st sütunlarını ayır; bu tek adım sorunun hangi katmanda olduğunu saniyeler içinde söyler. İkincisi, iostat kullanırken ilk örneği yok say ve kararını await ile aqu-sz üzerinden ver. Üçüncüsü, ölçümlerini her zaman tepe saatte al — kuyruk problemleri boş sistemde görünmez. Dördüncüsü, donanım değiştirmeden önce sırayla önbellek, bellek havuzu ve gereksiz yazma temizliğini yap; bu üçü çoğu sunucuda darboğazı tamamen ortadan kaldırır.
Ölçümlerin gerçekten daha hızlı depolamaya ihtiyaç duyduğunu gösteriyorsa Clou.TR paketleri NVMe disk üzerine kuruludur. Veritabanı yoğun siteler için e-ticaret hosting ve WordPress hosting, kendi disk düzenini ve önbellek katmanını kurmak isteyenler için VDS sunucu ya da tam donanım kontrolü veren dedicated sunucu seçenekleri var. Yedeklemeyi canlı sunucudan ayırmak istersen yedekleme hizmetimiz yükü sunucunun dışına taşır; izleme ve ayar tarafını hiç kurcalamak istemiyorsan sunucu yönetimi ekibimize bırakabilirsin.