WordPress

    WordPress Zamanla Yavaşladı: wp_options Autoload Şişmesini Bulma ve Temizleme

    wp_options autoload verisinin her istekte belleğe yüklenmesinden doğan sinsi yavaşlamayı ölçme ve temizleme rehberi.

    13 dk okuma Güncellendi: 18 Ağustos 2026

    Site iki yıl önce kurulduğunda uçuyordu. Şimdi hiçbir şey değişmemiş gibi görünüyor: trafik aynı, tema aynı, paket aynı. Ama yönetici paneline girmek 3 saniye sürüyor, yazı listesi geç açılıyor, ön yüzde en boş sayfa bile ağır. Bir önbellek eklentisi kurdunuz, GTmetrix skoru düzeldi ama panel hâlâ hantal. Hosting desteğine yazdınız, "kaynak kullanımınız normal" cevabı geldi.

    Buradaki en önemli ipucu genellikle gözden kaçar: yavaşlık sayfaya göre değişmiyor. Ağır bir ürün listesi ile üç satırlık bir "İletişim" sayfası neredeyse aynı sürede açılıyorsa, sorun o sayfanın içeriğinde değildir. WordPress'in her istekte, sayfa ne olursa olsun yaptığı bir işte gizlidir. Bu işlerin en pahalısı ve en sessiz olanı, wp_options tablosundaki autoload verisidir.

    Bu rehber tek bir soruna odaklanıyor: her sayfa açılışında belleğe yüklenen seçenek verisinin şişmesi. Önce mekanizmayı, sonra ölçümü (rakam olmadan müdahale etmeyeceğiz), sonra ölçtüğünüz kaydın hangi eklentiye ait olduğunu nasıl bulacağınızı, ardından güvenli temizlik sırasını ve en sonunda "işe yaradı mı" sorusunun cevabını aynı sorguyla nasıl kanıtlayacağınızı göreceğiz. Revizyon, spam yorum ve çöp temizliği gibi genel bakım adımları bu yazının konusu değil; onlar için WordPress veritabanı optimizasyon rehberimiz var.

    Autoload Nedir ve Neden Her İsteği Etkiler?#

    WordPress ayarlarını wp_options tablosunda tutar. Bu tablonun her satırında bir option_name, bir option_value ve bir de autoload sütunu vardır. Autoload sütunu tek bir soruyu cevaplar: "Bu kayıt, daha kimse istemeden, her sayfa açılışında belleğe yüklensin mi?"

    Cevap "evet" ise WordPress önyükleme sırasında wp_load_alloptions() fonksiyonunu çalıştırır. Bu fonksiyon tek bir sorguyla autoload işaretli tüm satırları çeker, hepsini birden PHP dizisine unserialize eder ve alloptions adlı tek bir önbellek anahtarında tutar. Yani autoload verisi bir "sayfa maliyeti" değil, bir istek maliyetidir. Şu isteklerin hepsi bu bedeli öder:

    İstek türüAutoload bedeli ödenir mi?Not
    Önbellekten dönen anonim sayfaHayırPHP hiç çalışmaz
    Önbelleğe girmeyen ön yüz isteği (sepet, ödeme, oturum açmış ziyaretçi)EvetHer istekte
    Yönetici paneli (wp-admin) her ekranEvetPanelin yavaşlamasının ana nedeni
    admin-ajax.php ve ?wc-ajax= çağrılarıEvetArka planda dakikada onlarca kez
    REST API (/wp-json/) istekleriEvetBlok editörü sürekli çağırır
    WP-Cron tetiklemeleriEvetHer ziyaretçi bir cron tetikleyebilir

    Buradaki en önemli sonuç şu: önbellek eklentisi bu sorunu çözmez, saklar. Tam sayfa önbelleği anonim ziyaretçiyi kurtarır, ama panel, AJAX, REST ve oturumlu istekler önbellekten geçmez. Bu yüzden "önbellek kurdum, ziyaretçi tarafı hızlandı ama panel hâlâ ağır" tablosu, autoload şişmesinin klasik imzasıdır.

    Object Cache Kurmak Kurtarmıyor, Bazen Kötüleştiriyor#

    Yaygın bir yanlış inanış, Redis veya Memcached kurulunca autoload verisinin "bedava" hâle geldiğidir. Öyle değil. Harici bir object cache'te alloptions tek bir dev anahtar olarak durur; her istekte bu anahtar ağ soketi üzerinden çekilir ve PHP tarafında baştan unserialize edilir. 3 MB'lık bir autoload yükü, Redis'te de her istekte 3 MB taşınıp açılan bir yüktür.

    Memcached'de durum daha da serttir: varsayılan maksimum öğe boyutu 1 MB'tır. alloptions dizisi bu sınırı aşarsa hiç yazılamaz, dolayısıyla her istekte önbellek ıskalar ve veritabanına geri dönülür. Yani object cache kurmak, eşiği aşan bir sitede hiçbir şey kazandırmaz. Object cache'in doğru kurulumu için Redis object cache rehberimize bakabilirsiniz; ama autoload temizliğini onun yerine geçecek bir çözüm olarak görmeyin.

    WordPress 6.6 ile autoload Sütunu Değişti: Eski Sorgu Artık Eksik Ölçüyor#

    İnternetteki hemen her rehber şu sorguyu verir:

    SELECT SUM(LENGTH(option_value)) FROM wp_options WHERE autoload = 'yes';
    

    WordPress 6.6'dan itibaren bu sorgu eksik sonuç döndürür. Options API'si yeniden yazıldı ve autoload sütunu artık sadece yes/no değil, beş değer alabiliyor:

    DeğerAnlamıYüklenir mi?
    onAçıkça "autoload edilsin" denmişEvet
    offAçıkça "edilmesin" denmişHayır
    autoDeğer belirtilmemiş, çekirdeğin varsayılanıEvet
    auto-onÇekirdek boyuta bakıp "yüklensin" demişEvet
    auto-offÇekirdek boyuta bakıp "yüklenmesin" demişHayır
    yes / no6.6 öncesinden kalan eski kayıtlaryes evet, no hayır

    Çekirdek bu kararı verirken bir boyut eşiği kullanır: varsayılan olarak 150.000 bayt (yaklaşık 146 KB). Bundan büyük bir seçenek, açıkça on denmediyse auto-off olarak yazılır. Eşik wp_max_autoloaded_option_size filtresiyle değiştirilebilir, ama yükseltmenin tek sonucu daha yavaş bir sitedir.

    Gerçekten yüklenen değerlerin listesini çekirdek wp_autoload_values_to_autoload() fonksiyonuyla verir ve bu liste yes, on, auto-on, auto şeklindedir. Ölçüm sorgularınızın tamamı bu dört değeri kapsamalı. Aksi hâlde 6.6 sonrası kurulmuş bir sitede "autoload verim 40 KB" gibi sahte bir rahatlama yaşarsınız.

    Sitenizin hangi dünyada olduğunu tek sorguyla görün:

    SELECT autoload,
           COUNT(*) AS kayit,
           ROUND(SUM(LENGTH(option_value)) / 1024, 2) AS kb
    FROM wp_options
    GROUP BY autoload
    ORDER BY kb DESC;
    

    Sonuçta yalnız yes/no görüyorsanız site 6.6 öncesinden geliyor demektir; auto ve auto-off da varsa yeni davranış devrede.

    Ölçüm 1: Autoload Verisinin Toplam Boyutu ve Eşik Değerleri#

    Şimdi asıl rakam. phpMyAdmin'in SQL sekmesinde ya da wp db query ile çalıştırın:

    SELECT ROUND(SUM(LENGTH(option_value)) / 1024, 2) AS autoload_kb,
           COUNT(*) AS kayit_sayisi
    FROM wp_options
    WHERE autoload IN ('yes', 'on', 'auto', 'auto-on');
    

    Tablo öneki her kurulumda wp_ olmayabilir; wp-config.php dosyasındaki $table_prefix değerine bakıp sorgudaki tablo adını ona göre düzeltin.

    WP-CLI erişiminiz varsa aynı rakamı tek satırda alırsınız:

    wp option list --autoload=on --format=total_bytes
    

    Çıkan sayıyı şu ölçekle yorumlayın:

    Toplam autoloadDurumYapılacak
    300 KB altıSağlıklıBir şey yapmayın
    300 - 800 KBİzlenmeliEn büyük 5 kayda göz atın
    800 KB - 1 MBSınırdaTemizliği planlayın
    1 - 3 MBSorunluBu rehberi uygulayın
    3 MB üstüAğırÖncelikli müdahale

    Kayıt sayısı da önemlidir. 1.500'ün üzerinde autoload satırı varsa, tek tek küçük olsalar bile her istekte 1.500 elemanlı bir dizinin kurulması ve gezilmesi başlı başına bir maliyettir.

    Ölçüm 2: En Büyük Kayıtları Listeleme ve Sahibini Bulma#

    Toplam rakam sorunu gösterir, ama çözüm tek tek satırlardadır. En ağır 20 kaydı çıkarın:

    SELECT option_name,
           ROUND(LENGTH(option_value) / 1024, 2) AS kb,
           autoload
    FROM wp_options
    WHERE autoload IN ('yes', 'on', 'auto', 'auto-on')
    ORDER BY LENGTH(option_value) DESC
    LIMIT 20;
    

    Çoğu sitede ilk 5 satır toplamın yüzde 70-90'ını oluşturur. Yani 40 kaydı tek tek incelemeniz gerekmez; birkaç dev satırı halletmek yeter.

    Şimdi asıl beceri: kayıt adından sahibini okumak. WordPress'te seçenek isimlendirmesi bir sözleşmedir; eklentiler kendi ön eklerini kullanır.

    Kayıt adı deseniSahibi / anlamıİlk değerlendirme
    rewrite_rulesÇekirdek, kalıcı bağlantı kurallarıBüyükse silin, kendini yeniden üretir
    _transient_...Geçici önbellek kaydıSüresi geçmişse silinir
    _site_transient_...Çok siteli kurulumda geçici kayıtAynı
    wc_..., woocommerce_...WooCommerceDikkatli olun, ayar olabilir
    elementor_...ElementorGenelde off yapılabilir
    wpseo_..., yoast_...Yoast SEOAyar kayıtları, silmeyin
    updraft_...UpdraftPlus yedek günlükleriGenellikle şişer, off yapılabilir
    jetpack_...JetpackSık şişen gruplardan
    wpforms_..., cf7_...Form eklentileriForm gönderim izleri
    theme_mods_TEMAADITema özelleştirici ayarlarıAktif temaninkini silmeyin

    Ön ek tanıdık gelmiyorsa aramayı sunucuda yapın. Kayıt adının bir eklenti dosyasında geçip geçmediğine bakmak, sahibini bulmanın en kesin yoludur:

    cd ~/public_html/wp-content
    grep -rn --include='*.php' "ornek_dev_kayit" plugins/ themes/ mu-plugins/ | head
    

    Hiçbir sonuç çıkmıyorsa üç ihtimal vardır: kayıt adı kod içinde dinamik olarak üretiliyordur, kayıt silinmiş bir eklentiden kalmıştır, ya da bir kod parçacığı eklentisinin veritabanındaki koduna gömülüdür. İkinci ihtimal, yani yetim kayıtlar, bu işin en kârlı hedefidir: sahibi olmayan bir veri her istekte bellek işgal ediyordur ve silinmesi hiçbir şeyi bozmaz.

    Aktif eklenti listenizi çıkarıp ön eklerle karşılaştırın:

    wp plugin list --status=active --field=name
    

    Süresi Geçmiş Transient'ler Neden Kendiliğinden Temizlenmiyor?#

    Transient, WordPress'in "şu veriyi şu kadar süre sakla" mekanizmasıdır. Sürenin bitmesi kaydın silinmesi anlamına gelmez; WordPress transient'i yeniden istendiğinde süresine bakar ve geçmişse o an siler. Kimse istemezse satır orada durur.

    WordPress 4.9'dan beri bir güvenlik ağı vardır: günlük çalışan wp_scheduled_delete cron olayı delete_expired_transients() fonksiyonunu tetikler ve süresi geçmiş kayıtları toplar. Buna rağmen sahada binlerce transient satırı görmenizin üç somut nedeni olur:

    1. WP-Cron gerçekte çalışmıyordur. Sanal cron ziyaretçi trafiğine bağlıdır; sayfa önbelleği devredeyse PHP çalışmadığı için tetikleme de olmaz. Bu sorunun kalıcı çözümü için WP-Cron'u kapatıp gerçek cron kurma yazımıza bakın.
    2. Süresiz transient'ler autoload edilir. set_transient() fonksiyonuna süre verilmezse kayıt, süre satırı olmadan yazılır ve varsayılan autoload davranışına tabi olur. Yani "süresi geçmiş" sayılmaz, temizlenmez ve her istekte belleğe yüklenir. Autoload listesinde _transient_ ile başlayan devler görüyorsanız sebebi budur.
    3. Yetim kalmış çiftler. Her süreli transient iki satırdır: veri ve _transient_timeout_ süresi. Süre satırı bir şekilde silinmişse, veri satırı ebediyen kalır; temizlik fonksiyonu onu bulamaz.

    Önce sayın. Alt çizgi karakteri SQL'de joker olduğu için kaçırmayı unutmayın; LIKE '_transient_%' yazarsanız istemediğiniz satırları da yakalarsınız:

    SELECT COUNT(*) AS adet,
           ROUND(SUM(LENGTH(option_value)) / 1024, 2) AS kb
    FROM wp_options
    WHERE option_name LIKE '\_transient\_%'
       OR option_name LIKE '\_site\_transient\_%';
    

    Sonra asıl zararlıyı, yani autoload edilen transient'leri ayıklayın:

    SELECT option_name, ROUND(LENGTH(option_value) / 1024, 2) AS kb
    FROM wp_options
    WHERE option_name LIKE '\_transient\_%'
      AND autoload IN ('yes', 'on', 'auto', 'auto-on')
    ORDER BY LENGTH(option_value) DESC
    LIMIT 20;
    

    Küçük bir kontrol daha: harici object cache aktifse transient'ler wp_options tablosuna hiç yazılmaz, doğrudan Redis/Memcached'e gider. Redis kurulu olduğunu düşündüğünüz bir sitede binlerce _transient_ satırı görüyorsanız, object cache aslında devrede değildir. Bu tek başına araştırmaya değer bir bulgudur.

    Temizlik Sırası: Yedek, Transient, Yetim, autoload=off#

    Sıralama önemlidir. En güvenli işlemden en riskliye doğru ilerleyin ve her adımdan sonra siteyi açıp bakın.

    1. Yedek alın#

    Bu adımı atlamayın. Aşağıdaki DELETE ve UPDATE ifadeleri geri alınamaz.

    wp db export ~/yedek-$(date +%F).sql
    # WP-CLI yoksa:
    mysqldump -u KULLANICI -p VERITABANI > ~/yedek-$(date +%F).sql
    

    Dosyanın gerçekten oluştuğunu ve makul boyutta olduğunu ls -lh ile doğrulayın. Ayrıntılar için mysqldump ile veritabanı yedekleme rehberimize bakabilirsiniz.

    2. Süresi geçmiş transient'leri temizleyin#

    En güvenli ve en hızlı kazanç burada. WP-CLI varsa tek komut:

    wp transient delete --expired
    # Çok siteli kurulumda ağ genelindekiler için:
    wp transient delete --expired --network
    

    WP-CLI yoksa aynı işi SQL ile yapabilirsiniz. Aşağıdaki sorgu süre satırını ve ona bağlı veri satırını birlikte siler:

    DELETE a, b FROM wp_options a
    LEFT JOIN wp_options b
      ON b.option_name = CONCAT('_transient_', SUBSTRING(a.option_name, 20))
    WHERE a.option_name LIKE '\_transient\_timeout\_%'
      AND a.option_value < UNIX_TIMESTAMP();
    

    wp transient delete --all komutuna dikkat: süresi dolmamış olanları da siler. Bu genelde zararsızdır (yeniden üretilirler) ama bir mağazada geçici olarak yavaşlamaya yol açar; yoğun saatte çalıştırmayın.

    3. Yetim kayıtları silin#

    Silinmiş eklentiden kalan kayıtları, sahibini doğruladıktan sonra kaldırın. Önce ne sileceğinizi görün, sonra silin:

    -- Önce görün
    SELECT option_name, ROUND(LENGTH(option_value)/1024, 2) AS kb
    FROM wp_options
    WHERE option_name LIKE 'eskiEklenti\_%';
    
    -- Sonucu inceledikten sonra silin
    DELETE FROM wp_options WHERE option_name LIKE 'eskiEklenti\_%';
    

    rewrite_rules kaydı yüzlerce kilobayta ulaştıysa onu silmek güvenlidir; WordPress kalıcı bağlantıları bir sonraki ihtiyaçta yeniden üretir. İsterseniz wp rewrite flush komutuyla hemen tazeleyin.

    4. Gerekli ama büyük kayıtları autoload dışına alın#

    Bir kaydın büyük olması onun gereksiz olduğu anlamına gelmez. Aktif bir eklentinin gerçekten kullandığı 400 KB'lık bir ayar bloğu silinemez, ama her istekte yüklenmesi gerekmiyor olabilir. Eklenti o değeri get_option() ile istediğinde WordPress ayrı bir sorguyla yine getirir; sadece maliyet, ihtiyaç duyan sayfaya kaydırılmış olur.

    WordPress 6.4 ile gelen özel fonksiyonun WP-CLI karşılığı bu iş için doğru araçtır, çünkü değere dokunmadan yalnız bayrağı değiştirir ve object cache'i tutarlı bırakır:

    wp option get-autoload ornek_dev_kayit
    wp option set-autoload ornek_dev_kayit off
    

    Doğrudan SQL kullanacaksanız önbelleği temizlemeyi unutmayın; alloptions anahtarı eski hâliyle durduğu sürece değişiklik hiçbir şeye yaramaz:

    UPDATE wp_options SET autoload = 'off' WHERE option_name = 'ornek_dev_kayit';
    
    wp cache flush
    

    Değişikliği yaptıktan sonra siteyi bir gün izleyin: ilgili eklentinin ekranları, ön yüzdeki widget'ları ve varsa zamanlanmış görevleri çalışıyor mu? Sorun çıkarsa aynı komutu on ile geri alırsınız — bu, silmeye göre çok daha ucuz bir denemedir. Kural: önce off, sonra test, en son silme.

    Sonucu Ölçün: Önce ve Sonra#

    Temizlik bittiğinde ölçüm sorgusunu aynen tekrar çalıştırın. Somut bir örnek, tipik bir kurumsal sitede şöyle görünür:

    ÖlçümÖnceSonra
    Autoload toplam2.840 KB310 KB
    Autoload kayıt sayısı1.960640
    _transient_ satır sayısı7.40090
    Panel ana sayfa TTFB1,9 sn0,7 sn

    TTFB'yi kendiniz ölçerken önbelleğe takılmayan bir uç nokta seçin. Ana sayfa büyük ihtimalle önbellekten döneceği için hiçbir şey göstermez; wp-login.php her zaman PHP çalıştırır:

    for i in 1 2 3 4 5; do
      curl -o /dev/null -s -w '%{time_starttransfer}\n' https://ornek.com/wp-login.php
    done
    

    Rakam kıpırdamadıysa dürüst sonuç şudur: darboğaz autoload değildi. O zaman aramayı eklenti bazında sürdürün — hangi eklentinin siteyi yavaşlattığını bulma ve TTFB'yi düşürme yazıları bir sonraki adımınız olur.

    Tekrar Şişmemesi İçin Ne Yapmalı?#

    Temizlik kalıcı bir çözüm değil, bir sıfırlamadır. Aynı eklentiler aynı davranışı sürdürecektir. Üç basit alışkanlık işi kalıcı kılar.

    Ayda bir ölçün. Sunucuda cron kurabiliyorsanız rakamı bir dosyaya biriktirin; eğilimi görmek tek seferlik rakamdan çok daha kıymetlidir:

    0 6 * * 1 cd /home/kullanici/public_html && printf '%s %s\n' "$(date +%F)" "$(wp option list --autoload=on --format=total_bytes)" >> /home/kullanici/autoload.log
    

    WP-Cron'u gerçek crona bağlayın. Böylece günlük transient temizliği trafiğe bağlı olmaktan çıkar.

    Eklenti silerken "verileri de kaldır" seçeneğini işaretleyin. Çoğu eklenti bu seçeneği ayar ekranında sunar; işaretlemeden kaldırdığınız her eklenti geride kayıt bırakır. Kendi kodunuzu yazıyorsanız da büyük veriyi add_option( 'ad', $deger, '', false ) şeklinde autoload dışında saklayın.

    Barındırma tarafında dikkat edilecek nokta ise şu: autoload şişmesi CPU değil bellek ve serileştirme maliyetidir, bu yüzden pakete kaynak eklemek genelde beklendiği kadar iyileştirme getirmez. Clou.TR paketlerinde de olduğu gibi, PHP bellek limitini yükseltmek siteyi çökmekten korur ama her istekte 3 MB'lık diziyi kurma işini ortadan kaldırmaz; asıl kazanç veriyi küçültmektedir.

    Sıkça Sorulan Sorular#

    Autoload verisi kaç KB olmalı?#

    Kesin bir üst sınır yoktur ama pratik eşik nettir: 300 KB altı sağlıklı, 800 KB üstü incelenmeli, 1 MB üstü sorunlu kabul edilir. Kayıt sayısı da önemlidir; 1.500'ün üzerinde autoload satırı, tek tek küçük olsalar bile her istekte kurulan dizinin maliyetini yükseltir. Hedefiniz belirli bir rakama ulaşmak değil, ölçümü temizlik öncesi ve sonrası karşılaştırıp gerçek kazanç elde ettiğinizi görmek olmalı.

    wp_options tablosundaki büyük bir kaydı silmek güvenli mi?#

    Kaydın sahibi belirlenmeden silmek risklidir; aktif bir eklentinin ayarını kaldırırsanız o eklenti sıfırlanabilir veya hata verebilir. Güvenli sıra şudur: önce kaydın adını eklenti dosyalarında arayın, sahibi çıkmazsa yetim kabul edin. Emin olamadığınız her kayıtta silmek yerine autoload değerini off yapın, siteyi bir gün izleyin. Sorun çıkmazsa zaten sildiğinizde de çıkmayacaktır.

    WordPress 6.6 sonrası neden eski autoload sorgusu yanlış sonuç veriyor?#

    Çünkü 6.6 ile autoload sütunu yes ve no dışında on, off, auto, auto-on, auto-off değerlerini de alabiliyor. Yalnızca autoload = 'yes' filtreleyen bir sorgu, yeni yazılan on, auto ve auto-on satırlarını hiç saymaz. Doğru filtre bu dört değeri birlikte kapsamalıdır. Eski sorguyu kullanan bir sitede "autoload verim çok küçük" sonucuna varmak, sorunu görmezden gelmenin en kolay yoludur.

    Redis veya Memcached kurarsam autoload sorununu çözer miyim?#

    Hayır. Object cache, autoload verisini alloptions adlı tek bir anahtarda tutar; bu anahtar her istekte çekilir ve PHP tarafında yeniden açılır. Büyük bir yük, önbellekte de büyük bir yüktür. Memcached'de varsayılan 1 MB öğe sınırı aşılırsa anahtar hiç yazılamaz ve her istek veritabanına düşer; yani sorun aynen devam eder, üstüne bir de boşuna deneme maliyeti eklenir.

    Transient temizliği neden kendiliğinden yapılmıyor?#

    Aslında yapılır: WordPress günlük bir cron olayıyla süresi geçmiş transient'leri siler. Ancak bu mekanizma üç durumda çalışmaz. WP-Cron ziyaretçi trafiğine bağlıdır ve sayfa önbelleği devredeyse tetiklenmeyebilir; süresiz olarak yazılan transient'ler hiçbir zaman "süresi geçmiş" sayılmaz; süre satırı silinmiş yetim kayıtları ise temizlik fonksiyonu bulamaz. Bu yüzden gerçek cron kurmak ve arada elle temizlik yapmak gerekir.

    Temizlikten sonra hiçbir şey hızlanmadıysa ne yapmalıyım?#

    Bu, ölçümün işe yaradığı anlamına gelir: darboğazın autoload olmadığını kanıtladınız. Sıradaki adaylar sırasıyla ağır eklentiler, yavaş veritabanı sorguları, önbelleğe girmeyen AJAX çağrıları ve yetersiz PHP sürümüdür. Değişiklikleri geri almanıza gerek yok; küçültülmüş autoload verisi zararsızdır ve gelecekteki büyümeye karşı size alan kazandırmıştır. Aramayı eklenti devre dışı bırakma yöntemiyle sürdürün.

    WordPressVeritabanıPerformans

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.