Przekroczenie limitu pamięci w PrestaShop: Przyczyny i rozwiązania
Zrozumienie PHP memory_limit
Dyrektywa memory_limit w PHP kontroluje, ile pamięci RAM może zużyć pojedynczy proces PHP, zanim silnik zakończy go błędem krytycznym. Gdy widzisz komunikat \"Allowed memory size of X bytes exhausted\" w PrestaShop, oznacza to, że konkretne żądanie PHP próbowało zużyć więcej pamięci, niż pozwala skonfigurowany limit.
Każde załadowanie strony w PrestaShop uruchamia kod PHP, który ładuje framework, łączy się z bazą danych, przetwarza dane, renderuje szablony i wysyła HTML do przeglądarki. Każdy z tych kroków zużywa pamięć. memory_limit działa jako siatka bezpieczeństwa: zapobiega sytuacji, w której jeden wymykający się spod kontroli proces pochłonie całą dostępną pamięć RAM serwera, co spowodowałoby awarię innych procesów i potencjalnie wyłączenie całego serwera.
Domyślna wartość memory_limit w PHP to zazwyczaj 128M (128 megabajtów). PrestaShop oficjalnie zaleca co najmniej 256M, a wiele sklepów wymaga 512M lub więcej w zależności od rozmiaru katalogu, zainstalowanych modułów i ruchu. Zrozumienie, co napędza zużycie pamięci, pomaga określić właściwą wartość dla Twojego sklepu, zamiast ślepo zwiększać limit.
Jak sprawdzić aktualny limit pamięci
Istnieje kilka sposobów na weryfikację, jaki limit pamięci aktualnie używa Twoja instalacja PrestaShop.
Z poziomu panelu administracyjnego PrestaShop
Przejdź do Zaawansowane > Informacje. Ta strona wyświetla konfigurację PHP Twojego serwera, w tym aktualną wartość memory_limit. PrestaShop pokaże również ostrzeżenia, jeśli wartość jest poniżej zalecanego minimum.
Używając phpinfo()
Utwórz tymczasowy plik o nazwie info.php w głównym katalogu PrestaShop z następującą zawartością:
<?php phpinfo(); ?>Przejdź do niego przez przeglądarkę pod adresem twojadomena.com/info.php. Wyszukaj na stronie „memory_limit", aby zobaczyć zarówno Local Value (co jest faktycznie aktywne), jak i Master Value (co jest ustawione w php.ini). Wartość lokalna może różnić się od wartości głównej, jeśli .htaccess, .user.ini lub sama aplikacja ją nadpisuje.
Ważne: Usuń ten plik natychmiast po sprawdzeniu. Strona phpinfo() ujawnia szczegółową konfigurację serwera, którą atakujący mogą wykorzystać.
Przez wiersz poleceń
Jeśli masz dostęp SSH, uruchom:
php -i | grep memory_limitPamiętaj, że konfiguracja PHP w trybie CLI może różnić się od konfiguracji serwera WWW. Aby sprawdzić wartość widoczną po stronie serwera WWW, użyj metody phpinfo() lub panelu administracyjnego PrestaShop.
Typowe przyczyny błędów limitu pamięci
Duże importy produktów
Importowanie produktów przez CSV jest jedną z najbardziej wymagających pamięciowo operacji w PrestaShop. Każdy wiersz w pliku importu jest ładowany do pamięci, przetwarzany, walidowany i wstawiany do bazy danych. Plik CSV z 10 000 produktów, każdy z wieloma kombinacjami, zdjęciami i opisami, może łatwo wymagać 512 MB lub więcej pamięci.
Narzędzie importu PrestaShop przetwarza produkty partiami, ale rozmiar partii i ilość danych na produkt determinują całkowite zużycie pamięci. Duże pola tekstowe (opisy z HTML), wiele kolumn i pliki zakodowane w UTF-8 ze znakami specjalnymi zwiększają zużycie pamięci na wiersz.
Aby zmniejszyć zużycie pamięci podczas importów:
- Podziel duże pliki CSV na mniejsze porcje (1000-2000 wierszy każda)
- Importuj produkty bez zdjęć najpierw, a następnie importuj zdjęcia osobno
- Wyłącz nieistotne moduły podczas importu (statystyki, indeksowanie wyszukiwania)
- Użyj importu z wiersza poleceń, jeśli jest dostępny, co pozwala uniknąć limitów czasu serwera WWW
Produkty z wieloma kombinacjami
Produkty z wieloma atrybutami (rozmiar, kolor, materiał) generują kombinacje wykładniczo. Produkt z 5 rozmiarami, 10 kolorami i 3 materiałami tworzy 150 kombinacji. Każda kombinacja to osobny rekord w bazie danych z własną ceną, referencją, stanem magazynowym i powiązaniami ze zdjęciami. Gdy PrestaShop ładuje stronę produktu do edycji w back office, ładuje wszystkie kombinacje do pamięci naraz.
Produkty z ponad 500 kombinacjami to znany problem. Przy ponad 1000 kombinacji prawie na pewno przekroczysz limity pamięci przy domyślnej konfiguracji. Rozwiązania obejmują:
- Zwiększenie
memory_limitdo 512M lub 1G dla back office - Restrukturyzację produktów w celu zmniejszenia liczby kombinacji (oddzielne produkty zamiast mega-kombinacji)
- Używanie modułów, które obsługują kombinacje wydajniej poprzez paginację
Rozdęte lub źle napisane moduły
Moduły zewnętrzne (third-party) są częstym źródłem problemów z pamięcią. Typowe problemy to:
- Ładowanie całych tabel bazy danych do tablic PHP: Moduł, który uruchamia
SELECT * FROM ps_ordersbez klauzuli LIMIT, ładuje każde kiedykolwiek złożone zamówienie do pamięci. Dla sklepu ze 100 000 zamówień może to pochłonąć setki megabajtów. - Wycieki pamięci w pętlach: Moduły, które przetwarzają elementy w pętli, ale akumulują obiekty bez ich zwalniania. Garbage collector PHP radzi sobie z prostymi przypadkami, ale cykliczne referencje i przechowywane referencje mogą uniemożliwić oczyszczanie.
- Nadmierne logowanie: Logowanie debugowe, które zapisuje duże tablice lub obiekty do plików logów, używając
var_export()lubprint_r()na złożonych obiektach PrestaShop, może pochłaniać ogromne ilości pamięci. - Niezoptymalizowane przetwarzanie obrazów: Moduły, które zmieniają rozmiar lub dodają znaki wodne na obrazach za pomocą GD lub ImageMagick, ładują cały nieskompresowany obraz do pamięci. Obraz 5000x5000 pikseli przy 24-bitowej głębi koloru wymaga około 75 MB RAM-u tylko na dane pikseli.
Aby zidentyfikować, który moduł powoduje problemy z pamięcią, uważnie przeczytaj komunikat o błędzie. Zazwyczaj zawiera ścieżkę do pliku wskazującą na odpowiedzialny moduł. Możesz również włączyć tryb debugowania PrestaShop, aby uzyskać bardziej szczegółowe ślady stosu (stack traces).
Duże katalogi i złożone zapytania
Sklepy z dziesiątkami tysięcy produktów, wieloma kategoriami i złożonymi strukturami atrybutów wywierają większą presję na pamięć podczas normalnej pracy. Strony kategorii z nawigacją warstwową (wyszukiwanie fasetowe) są szczególnie wymagające, ponieważ silnik filtrów musi obliczać dostępne wartości atrybutów wśród tysięcy produktów.
Strony z listą produktów, zamówień i klientów w back office ładują dane do pamięci w celu wyświetlenia. Przy bardzo dużych zbiorach danych nawet podstawowy widok listy może przekroczyć limity pamięci, szczególnie gdy moduły dodają dodatkowe kolumny lub obliczenia do tych list.
Kompilacja szablonów Smarty
PrestaShop używa silnika szablonów Smarty, który kompiluje szablony do plików PHP dla szybszego renderowania. Sam proces kompilacji zużywa pamięć, a złożone szablony z wieloma dołączeniami (includes), pętlami i blokami warunkowymi wymagają więcej pamięci do kompilacji. Po pierwszej kompilacji używane są wersje z cache, więc jest to głównie problem przy czyszczeniu cache lub podczas programowania.
Jak zwiększyć limit pamięci
Metoda 1: php.ini
Najbardziej niezawodną metodą jest bezpośrednia edycja pliku konfiguracyjnego PHP. Lokalizacja zależy od konfiguracji:
- Debian/Ubuntu:
/etc/php/8.x/fpm/php.ini(PHP-FPM) lub/etc/php/8.x/apache2/php.ini(mod_php) - CentOS/RHEL:
/etc/php.inilub/etc/php.d/ - cPanel: MultiPHP INI Editor w WHM lub cPanelu
Znajdź linię memory_limit i zmień ją:
memory_limit = 512MPo zapisaniu zrestartuj PHP-FPM lub Apache:
# PHP-FPM\nsudo systemctl restart php8.2-fpm\n\n# Apache z mod_php\nsudo systemctl restart apache2Metoda 2: .htaccess (tylko Apache z mod_php)
Dodaj tę linię do pliku .htaccess w głównym katalogu PrestaShop:
php_value memory_limit 512MTa metoda działa tylko z Apache używającym mod_php. Jeśli korzystasz z PHP-FPM (co jest częstsze w nowoczesnych konfiguracjach), ta dyrektywa jest cicho ignorowana lub może spowodować błąd 500. Aby sprawdzić, którego handlera PHP używasz, zobacz linię Server API w wynikach phpinfo().
Metoda 3: .user.ini (PHP-FPM)
Utwórz lub edytuj plik o nazwie .user.ini w głównym katalogu PrestaShop:
memory_limit = 512MPHP-FPM odczytuje pliki .user.ini z katalogu dokumentów (document root). Pamiętaj, że zmiany wchodzą w życie po upływie okresu user_ini.cache_ttl (domyślnie 300 sekund / 5 minut), więc może być konieczne poczekanie lub restart PHP-FPM, aby zmiana zadziałała natychmiast.
Metoda 4: W kodzie PrestaShop
PrestaShop ustawia własny limit pamięci w pliku config/defines.inc.php. Szukaj linii w stylu:
@ini_set('memory_limit', '256M');Możesz zwiększyć tę wartość bezpośrednio w kodzie. Jednak to podejście ma ograniczenie: funkcja ini_set() może jedynie zwiększyć limit pamięci do wartości ustawionej w php.ini. Jeśli php.ini ustawia memory_limit = 128M, a Twój kod próbuje ustawić 512M, rzeczywisty limit pozostanie 128M (chyba że wartość główna pozwala na nadpisywanie, co zależy od klasyfikacji PHP_INI_ALL vs PHP_INI_SYSTEM).
Metoda 5: Konfiguracja per pula (PHP-FPM)
Jeśli zarządzasz własnym serwerem, możesz ustawić limity pamięci per pula PHP-FPM. Edytuj plik konfiguracyjny puli (np. /etc/php/8.2/fpm/pool.d/www.conf) i dodaj:
php_admin_value[memory_limit] = 512MUżycie php_admin_value sprawia, że to ustawienie jest niezmienne — nie może być nadpisane przez .user.ini ani ini_set(). Jest to przydatne do wymuszania limitów w środowiskach wielodostępowych (multi-tenant).
Pamięć per proces vs pamięć współdzielona
Ważne jest, aby zrozumieć, że memory_limit dotyczy każdego indywidualnego procesu PHP, a nie PHP jako całości. Jeśli ustawisz memory_limit = 512M, a Twój serwer uruchomi 20 współbieżnych procesów PHP, teoretyczne maksymalne zużycie pamięci przez PHP to 10 GB (20 x 512 MB).
Dlatego ślepe zwiększanie limitu pamięci może powodować problemy. Na serwerze z 4 GB RAM, ustawienie memory_limit = 1G przy 10 workerach PHP-FPM oznacza, że sam PHP mógłby próbować użyć 10 GB, powodując intensywne korzystanie ze swap lub uruchomienie Linux OOM killera, który siłowo kończy procesy, aby zwolnić pamięć.
Prawidłowe podejście to zrównoważenie limitu pamięci z liczbą workerów PHP:
- Dostępna RAM dla PHP = Całkowita RAM - narzut systemu operacyjnego - pamięć MySQL - pamięć serwera WWW - inne usługi
- Maks. workerów PHP = Dostępna RAM dla PHP / memory_limit
Na przykład na VPS z 4 GB: 4 GB łącznie - 0,5 GB OS - 1 GB MySQL - 0,25 GB Nginx = 2,25 GB dla PHP. Przy memory_limit = 256M możesz bezpiecznie uruchomić 8-9 workerów PHP-FPM. Przy memory_limit = 512M możesz uruchomić tylko 4 workery, co oznacza, że mniej współbieżnych żądań może być obsłużonych.
Skonfiguruj pulę PHP-FPM odpowiednio:
pm = dynamic\npm.max_children = 8\npm.start_servers = 3\npm.min_spare_servers = 2\npm.max_spare_servers = 5Diagnostyka wycieków pamięci i nadmiernego zużycia
Jeśli zwiększenie limitu pamięci jedynie opóźnia błąd zamiast go naprawiać, prawdopodobnie masz wyciek pamięci lub nieefektywny proces. Oto jak zdiagnozować przyczynę źródłową.
Włącz tryb debugowania PrestaShop
Edytuj config/defines.inc.php i ustaw:
define('_PS_MODE_DEV_', true);To włącza szczegółowe raportowanie błędów, w tym dokładny plik i numer linii, w której limit pamięci został przekroczony. Ślad stosu (stack trace) pokazuje łańcuch wywołań funkcji, które doprowadziły do błędu, pomagając zidentyfikować odpowiedzialny moduł lub funkcję rdzenia.
Monitoruj zużycie pamięci w kodzie
Możesz dodać monitorowanie pamięci do konkretnych sekcji kodu, aby precyzyjnie zlokalizować, gdzie występują skoki pamięci:
error_log('Pamięć przed operacją: ' . memory_get_usage(true) / 1024 / 1024 . ' MB');\n// ... operacja ...\nerror_log('Pamięć po operacji: ' . memory_get_usage(true) / 1024 / 1024 . ' MB');\nerror_log('Szczytowe zużycie pamięci: ' . memory_get_peak_usage(true) / 1024 / 1024 . ' MB');Funkcja memory_get_usage(true) zwraca faktyczną ilość pamięci przydzielonej PHP przez system operacyjny, natomiast memory_get_peak_usage(true) zwraca maksymalną ilość przydzieloną w dowolnym momencie podczas żądania.
Użyj profilowania Xdebug
Profiler Xdebug generuje szczegółowe raporty wywołań funkcji, czasu wykonania i zużycia pamięci. Włącz go tymczasowo w konfiguracji PHP:
xdebug.mode = profile\nxdebug.output_dir = /tmp/xdebugOtwórz wygenerowane pliki cachegrind w narzędziu takim jak KCacheGrind lub Webgrind, aby zwizualizować, które funkcje zużywają najwięcej pamięci. Jest to najbardziej dokładne podejście diagnostyczne, ale powinno być używane tylko na serwerach deweloperskich ze względu na znaczny narzut wydajnościowy.
Sprawdź wolne zapytania i MySQL
Czasami to, co wygląda na problem z pamięcią PHP, jest w rzeczywistości problemem MySQL. Wolne zapytanie, które zwraca miliony wierszy, spowoduje przydzielenie pamięci przez PHP na cały zbiór wyników. Sprawdź log wolnych zapytań MySQL:
sudo tail -100 /var/log/mysql/slow-query.logJeśli widzisz zapytania z dużymi zbiorami wyników, dodaj odpowiednie klauzule LIMIT lub zaimplementuj paginację w odpowiedzialnym module.
Pamięć OPcache
OPcache to rozszerzenie PHP, które cachuje skompilowany bajtkod PHP we współdzielonej pamięci, eliminując potrzebę parsowania i kompilowania plików PHP przy każdym żądaniu. OPcache ma własną alokację pamięci, oddzielną od memory_limit.
Domyślna pamięć OPcache (opcache.memory_consumption) wynosi 128 MB. PrestaShop z kilkoma zainstalowanymi modułami może łatwo przekroczyć tę wartość. Gdy OPcache wyczerpie pamięć, zaczyna usuwać zapisane wpisy i rekompilować pliki przy każdym żądaniu, powodując znaczącą degradację wydajności.
Sprawdź status OPcache z wiersza poleceń:
php -r \"print_r(opcache_get_status());\"Lub sprawdź sekcję opcache w wynikach phpinfo(). Kluczowe wartości do monitorowania:
- opcache.memory_consumption: Całkowita pamięć przydzielona dla OPcache (zwiększ do 256M dla PrestaShop)
- opcache.max_accelerated_files: Maksymalna liczba plików, które OPcache może cachować (zwiększ do 20000 dla PrestaShop)
- Użyta pamięć vs Wolna pamięć: Jeśli wolna pamięć jest bliska zeru, zwiększ
memory_consumption - Współczynnik trafień cache (cache hit rate): Powinien być powyżej 99%. Poniżej 95% wskazuje na presję pamięciową lub częste unieważnianie cache
Zalecana konfiguracja OPcache dla PrestaShop:
opcache.enable = 1\nopcache.memory_consumption = 256\nopcache.max_accelerated_files = 20000\nopcache.validate_timestamps = 1\nopcache.revalidate_freq = 0\nopcache.interned_strings_buffer = 16Pamiętaj, że pamięć OPcache jest współdzielona między wszystkimi procesami PHP, w przeciwieństwie do memory_limit, który jest per-procesowy. Zwiększenie pamięci OPcache nie mnoży się przez liczbę workerów.
Konfiguracja pamięci MySQL
MySQL ma własną konfigurację pamięci, która pośrednio wpływa na wydajność PrestaShop i może przyczyniać się do ogólnej presji pamięciowej serwera. Kluczowe ustawienia pamięci MySQL obejmują:
- innodb_buffer_pool_size: Główny bufor pamięci dla tabel InnoDB. Ustaw na 50-70% dostępnej RAM na dedykowanym serwerze bazy danych lub 25-50% na serwerze współdzielonym, na którym działają zarówno PHP, jak i MySQL. To najważniejsze ustawienie wydajności MySQL.
- sort_buffer_size i join_buffer_size: Bufory per połączenie do sortowania i łączenia. Zachowaj domyślne wartości, chyba że masz konkretne wolne zapytania, które korzystają z większych buforów. Ustawienie ich zbyt wysoko marnuje pamięć, ponieważ są alokowane per połączenie.
- query_cache_size: Przestarzały w MySQL 8.0 i całkowicie usunięty. Jeśli nadal używasz MySQL 5.7, mały cache zapytań (64M) może pomóc, ale duże cache zapytań powodują rywalizację o zasoby i obniżają wydajność.
Jeśli MySQL zużywa zbyt dużo pamięci, pozostawia mniej dla PHP, potencjalnie zmuszając do zmniejszenia liczby workerów PHP-FPM lub limitu pamięci. Użyj mysqladmin status lub SHOW GLOBAL STATUS do monitorowania zużycia pamięci przez MySQL.
Kiedy zaktualizować hosting
Czasami zwiększenie limitu pamięci i optymalizacja kodu nie wystarczą. Oto oznaki, że potrzebujesz mocniejszego serwera:
- Stale działasz na maksymalnym limicie pamięci: Jeśli Twoje procesy regularnie używają 90%+ przydzielonej pamięci, nawet po optymalizacji, potrzebujesz więcej RAM.
- Serwer intensywnie korzysta ze swap: Sprawdź poleceniem
free -hlubvmstat 1. Jeśli użycie swap jest konsekwentnie wysokie, nie masz wystarczająco dużo fizycznego RAM-u. - Zmniejszenie workerów PHP szkodzi wydajności: Jeśli musiałeś zmniejszyć liczbę workerów PHP-FPM do 3-4, aby zmieścić się w limicie pamięci, Twoja strona nie może efektywnie obsługiwać współbieżnych odwiedzających.
- Twój katalog stale rośnie: Sklep, który działał dobrze z 1000 produktów, może mieć problemy z 10 000. Zapotrzebowanie na pamięć rośnie wraz z rozmiarem katalogu, szczególnie przy indeksowaniu wyszukiwania, listowaniu kategorii i operacjach w back office.
- Potrzebujesz memory_limit powyżej 1G: Jeśli pojedynczy proces PHP potrzebuje więcej niż 1 GB pamięci do normalnych operacji (nie importów), coś jest fundamentalnie nie tak z Twoim kodem lub wydajnością hostingu. Zbadaj przyczynę źródłową przed dalszym zwiększaniem limitu.
Przy aktualizacji priorytetyzuj więcej RAM-u nad większą liczbę rdzeni CPU dla PrestaShop. Serwer z 8 GB RAM i 2 rdzeniami będzie lepiej obsługiwał PrestaShop niż serwer z 4 GB RAM i 4 rdzeniami. Rozważ również przeniesienie MySQL na oddzielny serwer lub użycie zarządzanej usługi bazodanowej, co zwalnia całą pamięć RAM serwera aplikacji wyłącznie dla PHP.
Szybka referencyjna tabela: Zalecane ustawienia według rozmiaru sklepu
Poniższe zalecenia stanowią punkt wyjścia. Monitoruj faktyczne zużycie i dostosowuj odpowiednio.
- Mały sklep (poniżej 1000 produktów, kilka modułów):
memory_limit = 256M, 2 GB RAM, 4-6 workerów PHP - Średni sklep (1000-10 000 produktów, 20+ modułów):
memory_limit = 512M, 4 GB RAM, 6-8 workerów PHP - Duży sklep (10 000+ produktów, wiele kombinacji):
memory_limit = 512M-1G, 8 GB+ RAM, 8-16 workerów PHP, oddzielny serwer bazy danych - Podczas importów: Tymczasowo zwiększ do
1Glub2G, następnie przywróć normalną wartość
Pamiętaj, że limit pamięci to pułap bezpieczeństwa, a nie cel. Dobrze zoptymalizowany sklep PrestaShop powinien rzadko zużywać więcej niż 128-256 MB na żądanie przy normalnym ładowaniu stron. Jeśli normalne operacje konsekwentnie wymagają 512 MB lub więcej, zbadaj i napraw przyczynę źródłową, zamiast ciągle zwiększać limit.
Czy ta odpowiedź była pomocna?
Masz jeszcze pytania?
Can't find what you're looking for? Send us your question and we'll get back to you quickly.