PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

Magento 2 cron zawieszony – 50 000 pending jobów i deadlock w cron_schedule

by Henryk Tews / niedziela, 09 sierpnia 2026 / Opublikowano w Magento / Adobe Commerce

Cron Magento 2 przestał działać – zalegało ponad 50 000 niezrealizowanych jobów w tabeli cron_schedule. Emaile transakcyjne nie wychodziły, indeksery nie aktualizowały się, reguły cenowe nie odświeżały. Sklep działał normalnie dla klientów ale „od środka” był zamrożony. Czas naprawy: 3 godziny.

Objawy

  • Emaile potwierdzenia zamówień przestały dochodzić
  • Ceny z reguł katalogowych nieaktualne
  • W var/log/cron.log brak wpisów od kilku dni
  • SELECT COUNT(*) FROM cron_schedule WHERE status = 'pending' zwraca 52 000
  • System cron entry dla Magento działa (crontab -l pokazuje wpisy)

Diagnoza

# Sprawdź status tabeli cron_schedule
bin/magento cron:status

# Sprawdź ile jobów zalega
SELECT status, COUNT(*) as cnt
FROM cron_schedule
GROUP BY status
ORDER BY cnt DESC;

# Sprawdź ostatnie uruchomienie crona
SELECT job_code, status, scheduled_at, executed_at, finished_at, messages
FROM cron_schedule
WHERE status != 'pending'
ORDER BY finished_at DESC
LIMIT 20;

# Sprawdź czy proces crona PHP działa
ps aux | grep "magento cron"

# Sprawdź logi systemowego crona
grep "magento" /var/log/syslog | tail -50

Przyczyna

Jeden z jobów crona (catalog_product_alert) wchodził w nieskończoną pętlę przy produkcie z uszkodzonymi danymi EAV. Proces PHP zajmował 100% CPU przez kilkadziesiąt minut, a następnie był killowany przez OOM killer. Magento nie oznaczało go jako „failed” – job zostawał w statusie „running” na zawsze. Kolejne uruchomienia crona widziały „running” job i nie uruchamiały nowych instancji.

Rozwiązanie

# Krok 1: Wyczyść zalegające joby
bin/magento cron:unlock --all
# lub ręcznie SQL:
-- Oznacz stuck "running" joby jako failed
UPDATE cron_schedule
SET status = 'error', messages = 'Manually unlocked - was stuck in running state'
WHERE status = 'running'
  AND executed_at < DATE_SUB(NOW(), INTERVAL 2 HOUR);

-- Usuń zalegające pending joby (zostanie tylko kilka ostatnich)
DELETE FROM cron_schedule
WHERE status = 'pending'
  AND scheduled_at < DATE_SUB(NOW(), INTERVAL 1 DAY);

-- Usuń stare zakonczone joby (czyść regularnie)
DELETE FROM cron_schedule
WHERE status IN ('success', 'error', 'missed')
  AND finished_at < DATE_SUB(NOW(), INTERVAL 7 DAY);
# Krok 2: Znajdź problematyczny job
grep -A 5 "catalog_product_alert" var/log/cron.log | tail -30

# Krok 3: Uruchom cron ręcznie i obserwuj
bin/magento cron:run --group=default 2>&1 | tail -20

# Krok 4: Dodaj timeout do crona
# app/etc/config.php lub przez di.xml:
# Każdy job powinien mieć max_retry_count i timeout
<?php
// Własna implementacja crona z timeout
class SafeCronJob
{
    public function execute(): void
    {
        // Ustaw limit czasu wykonania
        set_time_limit(300); // 5 minut max

        // Przetwarzaj w batchach z checkpoint
        $lastId = $this->getCheckpoint();
        $processed = 0;

        while (true) {
            $batch = $this->getBatch($lastId, 100);
            if (empty($batch)) break;

            foreach ($batch as $item) {
                $this->processItem($item);
                $lastId = $item->getId();
                $processed++;
            }

            $this->saveCheckpoint($lastId);

            // Pozwól innym procesom na CPU
            if ($processed % 1000 === 0) {
                sleep(1);
            }
        }
    }
}

Prewencja

# Dodaj do crontaba regularne czyszczenie
# */5 * * * * /usr/bin/php /var/www/html/bin/magento cron:run --group=default
# 0 2 * * * /usr/bin/php /var/www/html/bin/magento cron:run --group=cleanup

# Monitoring: alert jeśli pending > 1000 lub running > 30 minut
# Skrypt sprawdzający:
PENDING=$(mysql -u magento -p magento -se "SELECT COUNT(*) FROM cron_schedule WHERE status='pending'")
if [ "$PENDING" -gt 1000 ]; then
    echo "ALERT: Cron backlog: $PENDING pending jobs" | mail -s "Magento Cron Alert" admin@sklep.pl
fi

Wnioski

Tabela cron_schedule wymaga regularnego czyszczenia - bez tego rośnie do milionów rekordów i sama w sobie spowalnia crona. Jeden zawieszony job może zablokować wszystkie pozostałe. Monitoring liczby pending jobów to podstawa - próg alertu: powyżej 500 pending to sygnał do zbadania.

About Henryk Tews

Co możesz przeczytać następne

Redis Streams – Consumer Groups, pending messages, dead letter, integracja z Magento queue
Optymalizacja wydajności – OPcache, Redis, N+1 queries, Blackfire, tabela priorytetów
Extension Attributes – pełna implementacja z batch loadingiem, REST API, testy
  • Publikacje
  • O autorze
  • Kontakt

© 2026 Created by

GÓRA
Zarządzaj zgodą
Aby zapewnić jak najlepsze wrażenia, korzystamy z technologii, takich jak pliki cookie, do przechowywania i/lub uzyskiwania dostępu do informacji o urządzeniu. Zgoda na te technologie pozwoli nam przetwarzać dane, takie jak zachowanie podczas przeglądania lub unikalne identyfikatory na tej stronie. Brak wyrażenia zgody lub wycofanie zgody może niekorzystnie wpłynąć na niektóre cechy i funkcje.
Funkcjonalne Zawsze aktywne
Przechowywanie lub dostęp do danych technicznych jest ściśle konieczny do uzasadnionego celu umożliwienia korzystania z konkretnej usługi wyraźnie żądanej przez subskrybenta lub użytkownika, lub wyłącznie w celu przeprowadzenia transmisji komunikatu przez sieć łączności elektronicznej.
Preferencje
Przechowywanie lub dostęp techniczny jest niezbędny do uzasadnionego celu przechowywania preferencji, o które nie prosi subskrybent lub użytkownik.
Statystyka
Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do celów statystycznych. Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do anonimowych celów statystycznych. Bez wezwania do sądu, dobrowolnego podporządkowania się dostawcy usług internetowych lub dodatkowych zapisów od strony trzeciej, informacje przechowywane lub pobierane wyłącznie w tym celu zwykle nie mogą być wykorzystywane do identyfikacji użytkownika.
Marketing
Przechowywanie lub dostęp techniczny jest wymagany do tworzenia profili użytkowników w celu wysyłania reklam lub śledzenia użytkownika na stronie internetowej lub na kilku stronach internetowych w podobnych celach marketingowych.
  • Zarządzaj opcjami
  • Zarządzaj serwisami
  • Zarządzaj {vendor_count} dostawcami
  • Przeczytaj więcej o tych celach
Zobacz preferencje
  • {title}
  • {title}
  • {title}