Web Hosting & cPanel

    Maximum Execution Time Exceeded Hatası Nasıl Çözülür?

    PHP süre aşımı hatasında limiti doğru katmandan artırmayı ve uzun işlemleri parçalayarak kalıcı çözüm üretme rehberi.

    12 dk okuma Güncellendi: 11 Ağustos 2026

    Bir veritabanı yedeğini geri yüklüyorsunuz, ekran otuz saniye donuyor ve sonra tek satır düşüyor: Fatal error: Maximum execution time of 30 seconds exceeded. PHP süre aşımı hatası, çalışan betiğin kendisine tanınan azami süreyi doldurduğunu ve PHP tarafından öldürüldüğünü söyler. Yedekleme, veritabanı içe aktarma, toplu ürün güncelleme, site taşıma — bu hatayı üreten işler hep aynı ailedendir: uzun sürer, tarayıcı üzerinden çalıştırılır ve yarıda kesildiğinde geride yarım kalmış veri bırakır.

    Bu yazının çözmeye çalıştığı asıl mesele şu: Türkçe kaynakların neredeyse tamamı "php.ini'de max_execution_time değerini artırın" deyip bitiriyor. Oysa modern bir sunucuda o değer zincirin yalnızca ilk halkasıdır. PHP-FPM'in request_terminate_timeout ayarı ve Nginx'in fastcgi_read_timeout ayarı üstüne ayarlanmadıkça süre pratikte uzamaz; kullanıcı max_execution_time = 300 yazar, sonra 60. saniyede 504 hatası alır ve neyi yanlış yaptığını anlayamaz. Aşağıda üç katmanın hangisinin önce dolduğunu, belirtiye bakarak hangi katmanda olduğunuzu nasıl anlayacağınızı ve süreyi uzatmanın ne zaman doğru, ne zaman erteleme olduğunu anlatıyoruz.

    Maximum Execution Time Exceeded Hatası Ne Anlama Geliyor#

    max_execution_time, tek bir PHP betiğinin çalışabileceği azami saniye sayısıdır. Varsayılan değer web ortamında genelde 30 saniyedir. Süre dolduğunda PHP betiği ölümcül hatayla sonlandırır; o ana kadar yapılan iş yarım kalır. Hata metni şöyledir:

    PHP Fatal error:  Maximum execution time of 30 seconds exceeded
    in /home/kullanici/public_html/wp-admin/includes/class-wp-upgrader.php on line 412
    

    İki detay önemlidir. Birincisi, sayaç yalnızca PHP'nin kendi işlem süresini sayar. Bir sleep() çağrısı, veritabanı sorgusunun beklediği süre ya da dış bir API'den yanıt bekleme süresi Linux'ta bu sayaca dahil edilmez. Bu yüzden 40 saniye bekleyen bir cURL isteği max_execution_time hatası vermez, ama zincirin üst katmanları onu yine de öldürebilir. İkincisi, hata satırında görünen dosya suçlu olmak zorunda değildir — sayaç dolduğunda hangi satır çalışıyorsa orası bildirilir.

    Aynı işlemde bazen bu hatayı, bazen allowed memory size exhausted hatası mesajını alıyorsanız şaşırmayın: kontrolsüz büyüyen bir döngüde hangi limitin önce dolacağı verinin yoğunluğuna bağlıdır ve ikisi aynı kök nedenin iki yüzüdür.

    Üç Katmanlı Zincir: Hangi Zamanlayıcı Önce Doluyor#

    Modern bir LEMP yığınında bir isteğin ölmesine karar verebilecek en az üç bağımsız sayaç vardır. En küçük değer kazanır. Zinciri anlamadan yapılan her ayar değişikliği kör atıştır.

    KatmanAyarTipik varsayılanSüre dolunca ne olur
    PHPmax_execution_time30 snFatal error: Maximum execution time ... exceeded, HTTP 200 gövdesinde
    PHP-FPM havuzurequest_terminate_timeout0 (kapalı) veya 60 snSüreç SIGTERM ile öldürülür, istemciye boş yanıt / 502
    Nginxfastcgi_read_timeout60 snNginx beklemeyi bırakır, 504 Gateway Time-out
    Apache (proxy)ProxyTimeout / proxy_read_timeout60 sn502 veya 504
    Apache (mod_fcgid)FcgidIOTimeout45 sn500 Internal Server Error
    Cloudflare / ön uçsabit istek zaman aşımı~100 sn524 hata sayfası

    Zinciri şöyle okuyun: max_execution_time = 300 yaptınız ama fastcgi_read_timeout 60 saniyede duruyorsa, betik arka planda çalışmaya devam ederken Nginx 60. saniyede pes eder ve tarayıcıya 504 basar. Kullanıcı için sonuç "hata devam ediyor"dur; gerçekte hata değişmiştir. Bu ayrımı yapmak, teşhisin yarısıdır.

    Tersi de olur: fastcgi_read_timeout 600; yazıp max_execution_time değerine dokunmazsanız hiçbir şey kazanmazsınız, çünkü PHP zaten 30. saniyede kendini öldürür.

    Belirtiye Bakarak Hangi Katmanda Olduğunuzu Anlayın#

    Ekranda ne gördüğünüz, hangi sayacın dolduğunu neredeyse kesin söyler:

    1. Ekranda Fatal error: Maximum execution time of N seconds exceeded yazıyor. Zincirin ilk halkasındasınız. Sadece PHP tarafını ayarlamanız yeterli olabilir.
    2. Sayfa uzun süre bekliyor, sonra Nginx'in "504 Gateway Time-out" sayfası geliyor. Nginx pes etmiştir. PHP hâlâ çalışıyor olabilir. Ayrıntılar için 504 gateway timeout hatası yazısına bakın.
    3. 502 Bad Gateway geliyor. Genelde FPM süreci request_terminate_timeout ile öldürülmüştür; Nginx bekleyen bağlantının koptuğunu görür. 502 bad gateway hatası çözümü bu senaryoyu ayrıntılandırıyor.
    4. Beyaz ekran ya da yarım HTML. Çıktı arabelleği kısmen gönderilmişken süreç ölmüştür; display_errors kapalıdır. Hata log dosyasındadır.
    5. Cloudflare 524 sayfası. Origin 100 saniyeden uzun süre yanıt vermemiştir; alt katmanların hepsini uzatsanız bile bu duvar durur.

    Kanıtı log'dan alın:

    # Nginx: upstream timed out satırını arayın
    grep -i "upstream timed out" /var/log/nginx/error.log | tail -20
    
    # PHP-FPM: yavaş ve öldürülen istekler
    grep -iE "execution timed out|terminating" /var/log/php-fpm/error.log | tail -20
    journalctl -u php8.2-fpm --since "30 minutes ago" | grep -i timeout
    
    # cPanel hesabında PHP tarafı
    tail -n 100 ~/public_html/error_log
    

    upstream timed out (110: Connection timed out) while reading response header from upstream satırını görüyorsanız suçlu kesin olarak Nginx'in fastcgi_read_timeout değeridir.

    max_execution_time Değeri Nereden Değiştirilir#

    Katman sırası bellek limitiyle aynıdır; en üstteki php_admin_value alttakileri kilitler.

    cPanel kullanıyorsanız. cPanel → Software → MultiPHP INI Editor → Basic Mode → alan adını seçin → max_execution_time alanına 300 yazın. CloudLinux'lu bir sunucuda aynı değer Select PHP Version → Options altında yer alır ve listedeki tavan paket sınırınızdır.

    .user.ini ile (PHP-FPM / CGI). Web kökünde:

    max_execution_time = 300
    max_input_time = 300
    memory_limit = 256M
    

    ⚠️ .user.ini değişiklikleri anında geçerli olmaz; PHP dosyayı user_ini.cache_ttl süresi kadar (varsayılan 300 saniye) önbellekte tutar.

    .htaccess ile (yalnızca mod_php). Sunucu PHP'yi Apache modülü olarak çalıştırıyorsa:

    php_value max_execution_time 300
    

    PHP-FPM'de bu satır ya etkisizdir ya da doğrudan 500 hatası üretir. Hangi modda olduğunuzu tek satırla ölçün:

    <?php
    echo php_sapi_name() . ' | ' . ini_get('max_execution_time') . ' | ' . php_ini_loaded_file();
    

    Betiğin içinden. Uzun süren tek bir işlem için en temiz yol budur, çünkü diğer istekleri etkilemez:

    // Yalnızca bu betik için
    set_time_limit( 300 );   // sayacı 0'dan yeniden başlatır
    ignore_user_abort( true ); // tarayıcı kapansa bile devam etsin
    

    set_time_limit() her çağrıldığında sayacı sıfırlar. Bir döngünün içinde her turda çağırmak, işi bitene kadar sınırsız çalıştırma anlamına gelir — bunu bilinçli yapın, unutulmuş bir döngüyü ölümsüzleştirmeyin. Ayrıca safe_mode benzeri kısıtlı ortamlarda ve disable_functions listesinde yer aldığında bu fonksiyon çalışmaz.

    Kendi sunucunuzda php.ini. Değeri ana yapılandırmadan verecekseniz doğru dosyayı düzenlediğinizden emin olun; FPM ve CLI için ayrı dosyalar vardır:

    php --ini                      # CLI'nin okuduğu dosya
    php-fpm8.2 -i | grep "Loaded Configuration"   # FPM'in okuduğu dosya
    

    Genel PHP yapılandırmasının hangi değerlerinin hangi ortamı etkilediğini toplu görmek isterseniz php ini ayarları yazısı iyi bir referans.

    PHP-FPM Katmanı: request_terminate_timeout#

    Bu ayar, FPM'in bir işçi sürecini "artık yeter" deyip öldürdüğü süredir ve PHP'nin kendi sayacından bağımsızdır. Havuz dosyasında bulunur:

    ; /etc/php/8.2/fpm/pool.d/www.conf
    request_terminate_timeout = 300
    request_slowlog_timeout = 10
    slowlog = /var/log/php-fpm/www-slow.log
    

    request_terminate_timeout değeri max_execution_time değerinden küçükse, PHP hatasını hiç göremezsiniz; süreç önce öldürülür ve tarayıcı 502 alır. Kural: FPM değeri, PHP değerine eşit ya da biraz büyük olmalıdır.

    request_slowlog_timeout ise altın değerindedir ve neredeyse hiç kullanılmaz. 10 saniyeden uzun süren her isteğin PHP yığın izini ayrı bir dosyaya yazar; yani hangi fonksiyonun asıldığını tahmin etmeden görürsünüz:

    sudo systemctl reload php8.2-fpm
    tail -f /var/log/php-fpm/www-slow.log
    

    Çıktıda [0x00007f...] curl_exec() /home/site/wp-content/plugins/xyz/api.php:88 gibi bir satır görürseniz teşhis bitmiştir: bir eklenti dış API'den yanıt bekliyordur. Bu senaryonun WordPress'teki klasik biçimi curl error 28 hatası mesajıyla birlikte gelir.

    Web Sunucusu Katmanı: Nginx ve Apache#

    Nginx tarafında ilgili ayar fastcgi_read_timeout değeridir ve location bloğunda tanımlanır:

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    
        fastcgi_read_timeout 300s;   # FPM'den yanıt beklenecek süre
        fastcgi_send_timeout 300s;
        fastcgi_connect_timeout 60s;
    }
    

    Sadece uzun süren yönetim işlemleri için süreyi uzatmak, tüm siteyi savunmasız bırakmamanın makul yoludur:

    location = /wp-admin/admin-ajax.php {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        fastcgi_read_timeout 600s;
    }
    

    Değişiklikten sonra mutlaka sözdizimini test edip yeniden yükleyin:

    sudo nginx -t && sudo systemctl reload nginx
    

    Nginx ile FPM arasındaki bağlantı ayarlarının tamamı için nginx php-fpm yapılandırma yazısına bakabilirsiniz.

    Apache tarafında karşılıklar şunlardır: mod_proxy_fcgi kullanıyorsanız ProxyTimeout 300 ya da SetHandler satırındaki proxy:unix:...|fcgi://localhost/" timeout=300; mod_fcgid kullanıyorsanız FcgidIOTimeout 300 ve FcgidBusyTimeout 300. Genel TimeOut direktifi de sunucu geneli için geçerlidir. Reverse proxy varsa (Nginx önde, Apache arkada) her ikisini de ayarlamak zorundasınız — yoksa öndeki katman arkadakini beklemeden pes eder.

    Süreyi Uzatmak Yerine İşi Bölmek#

    Yıllardır gördüğüm en sağlıklı yaklaşım: süreyi geçici olarak uzatın, işi bitirin, sonra kalıcı çözümü işi parçalamakta arayın. 300 saniye çalışan bir web isteği, ölçek büyüdüğünde 600 saniye olur ve o gün de aynı hatayı alırsınız.

    1. Toplu işleri gruplara bölün. Kuyruk mantığı en basit hâliyle şöyle kurulur:

    $grup     = 200;
    $baslangic = (int) get_option( 'aktarim_offset', 0 );
    
    $satirlar = $wpdb->get_results( $wpdb->prepare(
        "SELECT id FROM {$wpdb->prefix}urunler ORDER BY id LIMIT %d OFFSET %d",
        $grup, $baslangic
    ) );
    
    foreach ( $satirlar as $satir ) {
        urun_isle( $satir->id );
    }
    
    update_option( 'aktarim_offset', $baslangic + $grup );
    
    if ( count( $satirlar ) === $grup ) {
        // Tarayıcıyı yeniden yönlendir veya bir sonraki turu zamanla
        wp_schedule_single_event( time() + 30, 'aktarim_devam' );
    }
    

    Her tur otuz saniyenin altında biter, hiçbir limite dokunmanız gerekmez ve işlem yarıda kalırsa kaldığı yerden devam eder.

    2. Tarayıcıyı devreden çıkarın. En uzun işler komut satırından çalıştırılmalıdır; CLI ortamında max_execution_time çoğu sunucuda zaten 0 yani sınırsızdır ve web katmanının hiçbir zamanlayıcısı devrede değildir:

    # WordPress toplu işlemleri
    wp db import yedek.sql
    wp media regenerate --yes
    wp search-replace 'http://eski.com' 'https://yeni.com' --all-tables
    
    # Doğrudan MySQL içe aktarma
    mysql -u kullanici -p veritabani < yedek.sql
    

    Büyük bir SQL dosyasını phpMyAdmin üzerinden yüklemeye çalışmak bu hatanın en yaygın üreticisidir; aynı dosya komut satırında saniyeler içinde biter. WP-CLI kullanımına yeniyseniz wp-cli kullanımı yazısı giriş için yeterli.

    3. Zamanlanmış görevi gerçek cron'a taşıyın. WordPress'in kendi wp-cron mekanizması ziyaretçi isteğiyle tetiklenir; yani ağır bir görev, o an siteye giren ziyaretçinin isteğinde çalışır ve web zaman aşımına takılır. Doğrusu:

    // wp-config.php
    define( 'DISABLE_WP_CRON', true );
    
    # sunucu cron tanımı — beş dakikada bir
    */5 * * * * /usr/bin/php /home/kullanici/public_html/wp-cron.php >/dev/null 2>&1
    

    4. Dış servisleri zaman aşımıyla çağırın. Bir eklenti yanıt vermeyen bir API'yi süresiz beklerse tüm istek asılır. Kendi kodunuzda her zaman sınır koyun:

    $yanit = wp_remote_get( $url, array( 'timeout' => 8 ) );
    if ( is_wp_error( $yanit ) ) {
        error_log( 'API yanit vermedi: ' . $yanit->get_error_message() );
        return false; // sayfayı bekletme
    }
    

    Süre Aşımının En Sık Görüldüğü Beş Senaryo#

    SenaryoGerçek darboğazDoğru çözüm
    phpMyAdmin ile büyük SQL yüklemekWeb katmanımysql komutu ya da WP-CLI ile içe aktarma
    Site taşıma eklentisiyle paket oluşturmakDisk ve PHP süresiDosyaları rsync/SFTP, veritabanını dump ile taşımak
    Toplu görsel yeniden boyutlandırmaGD/ImageMagick CPUGruplara bölmek, CLI'den çalıştırmak
    Ödeme veya kargo API'si yanıt vermiyorDış servisİstek zaman aşımı ve önbellek koymak
    Yedek eklentisi tam yedek alıyorDisk okuma + sıkıştırmaSunucu tarafı yedek veya artımlı yedek

    Taşıma senaryosunun tamamı için web sitesi taşıma yazısındaki adım adım yöntem, süre aşımına takılmadan ilerlemenin standart yoludur.

    Sıkça Sorulan Sorular#

    max_execution_time değerini kaç yapmalıyım#

    Web istekleri için 60-120 saniye çoğu site için yeterlidir, yönetim tarafındaki toplu işlemler için 300 saniye makul bir tavandır. Bunun üzerine çıkmak, uzun işlemi tarayıcıya bağımlı bırakmaya devam etmek anlamına gelir ve ölçek büyüdüğünde aynı duvara daha yüksek bir değerde çarparsınız. Ziyaretçiye açık sayfalarda süreyi yükseltmek ayrıca risk yaratır: yavaş bir sayfa, tüm PHP-FPM işçilerinin dolmasına ve sitenin tamamen yanıt vermemesine yol açabilir.

    Değeri artırdım ama hâlâ 504 hatası alıyorum#

    Nginx'in fastcgi_read_timeout ayarı hâlâ düşüktür ve PHP bitmeden önce beklemeyi bırakmaktadır. PHP'nin süresini uzatmak, önündeki web sunucusunun sabrını uzatmaz; ikisi bağımsız sayaçlardır ve küçük olan kazanır. Nginx yapılandırmasında ilgili location ~ \.php$ bloğuna fastcgi_read_timeout 300s; ekleyip nginx -t && systemctl reload nginx ile uygulayın. Apache arkada çalışıyorsa ProxyTimeout ya da FcgidIOTimeout değerini de aynı seviyeye çekmeniz gerekir.

    set_time_limit fonksiyonu neden hiçbir şey yapmıyor#

    Büyük ihtimalle sunucuda disable_functions listesindedir ya da PHP kısıtlı bir modda çalışmaktadır. Bunu var_dump( ini_get('disable_functions') ); çıktısıyla doğrulayabilirsiniz. İkinci olasılık, fonksiyonun çalıştığı ama üst katmanların devrede olmasıdır: set_time_limit(600) PHP'yi uzatır, ancak PHP-FPM'in request_terminate_timeout değeri 60 saniyeyse süreç yine öldürülür. Bu durumda tarayıcı 502 alır ve PHP hatası hiç görünmez.

    Süre aşımı hatası verisi bozar mı#

    Evet, yarıda kesilen işlemler tutarsız veri bırakabilir. Özellikle içe aktarma ve toplu güncelleme işlerinde bazı satırlar yazılmış, bazıları yazılmamış olur; sipariş ya da stok tablolarında bu ciddi sonuç doğurur. Bu yüzden uzun işlemleri, kesilse bile kaldığı yerden devam edebilecek biçimde kurmak (işlenen son kaydın id'sini saklamak) süreyi uzatmaktan daha değerlidir. Kritik tablolarda işlemi veritabanı transaction'ı içinde çalıştırmak da yarım yazımı önler.

    CLI'de çalışan komut neden zaman aşımına uğramıyor#

    Çünkü PHP komut satırı arayüzünde max_execution_time varsayılan olarak sınırsızdır ve önünde ne web sunucusu ne de FPM havuzu vardır. Web isteği üç bağımsız sayacın kesişiminde çalışırken CLI komutu doğrudan çalışır ve yalnızca siz durdurursunuz. Bu yüzden büyük içe aktarma, arama-değiştirme ve yedek geri yükleme işleri her zaman komut satırından yapılmalıdır. Sunucuya SSH erişiminiz varsa bu, hata almadan iş bitirmenin en kısa yoludur.

    Cloudflare 524 hatası ile bu hata aynı şey mi#

    Değil, ama aynı zincirin en dış halkasıdır. Cloudflare origin sunucudan yanıt için yaklaşık 100 saniye bekler ve bu süre plan bazında sabittir; sunucudaki hiçbir ayar onu uzatmaz. Yani PHP, FPM ve Nginx değerlerini 600 saniyeye çıkarsanız bile Cloudflare üzerinden gelen istek 100. saniyede 524 ile kesilir. Uzun işlemleri Cloudflare'ın arkasında tarayıcıdan çalıştırmak yerine komut satırına ya da arka plan kuyruğuna taşımak tek kalıcı çözümdür.

    Hangi isteklerin uzun sürdüğünü nasıl görebilirim#

    PHP-FPM havuzunda request_slowlog_timeout ve slowlog ayarlarını açın; belirlediğiniz süreyi aşan her isteğin fonksiyon yığını dosyaya yazılır. Böylece hangi eklentinin, hangi fonksiyonun ve hangi satırın asıldığını tahmin etmeden görürsünüz. Ek olarak MySQL tarafında slow_query_log açılırsa yavaşlığın veritabanından mı geldiği hemen anlaşılır. Bu iki günlük birlikte, süre aşımı teşhisinin neredeyse tamamını kapsar.

    Paylaşımlı hostingte bu değerleri değiştirebilir miyim#

    PHP tarafındaki max_execution_time değerini çoğu paylaşımlı pakette cPanel'in PHP seçici ekranından paket tavanına kadar artırabilirsiniz. Ancak PHP-FPM havuzu ve web sunucusu zaman aşımları sunucu genelindedir ve müşteri tarafından değiştirilemez; bu sınırlar tüm sunucudaki siteleri korumak için vardır. Sürekli uzun süren işleriniz varsa doğru hamle limitle boğuşmak değil, bu ayarları kendiniz yönetebildiğiniz bir sunucuya geçmek ya da işi komut satırına taşımaktır.

    Kapanış#

    Maximum execution time exceeded hatasını çözmenin anahtarı, tek bir ayar değil bir zincir olduğunu kabul etmektir. Önce belirtiye bakıp hangi katmanın pes ettiğini belirleyin: ekranda PHP'nin ölümcül hatası varsa max_execution_time, 504 varsa Nginx'in fastcgi_read_timeout ayarı, 502 varsa FPM'in request_terminate_timeout ayarı konuşuyordur. Ardından üçünü birbiriyle tutarlı hâle getirin — en küçük değer daima kazanır. Son olarak, süreyi uzatmayı geçici bir önlem sayın: işi 200'lük gruplara bölmek, tarayıcı yerine komut satırından çalıştırmak ve dış API çağrılarına zaman aşımı koymak, aynı hatanın bir yıl sonra daha büyük veriyle geri gelmesini engelleyen asıl çözümdür.

    Bu ayarların hepsine dokunabildiğiniz bir ortam istiyorsanız — FPM havuzu, Nginx zaman aşımları, kendi cron tanımlarınız — VDS sunucu paketleri doğru zemindir. Büyük içe aktarma ve taşıma işlerini kendiniz üstlenmek istemiyorsanız site taşıma hizmeti veritabanını ve dosyaları zaman aşımına takılmadan aktarır, sunucu yönetimi ise bu limitlerin ve yavaş sorgu günlüklerinin sürekli takibini üstlenir. Yükü henüz orta ölçekte olan siteler için PHP sürümünü ve süre limitlerini panelden yönetebildiğiniz web hosting paketleri çoğu zaman fazlasıyla yeterlidir.

    hata kodlarıphpperformans

    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.