Przejdź do treści
DedicatedPHP Kontakt

Gdy PHP wyczerpuje połączenia z bazą danych: diagnostyka i odzyskiwanie sprawności

Dowiedz się, jak odróżnić wyczerpanie połączeń od wolnych zapytań, mierzyć współbieżność PHP i odzyskać przepustowość bez bezrefleksyjnego zwiększania limitów.

Schemat techniczny procesów PHP, jednoczesnych połączeń i limitu połączeń bazy danych

Wyczerpanie połączeń z bazą danych w PHP zwykle objawia się sporadycznymi błędami: część żądań kończy się niepowodzeniem, inne czekają, a problem nasila się w godzinach dużego obciążenia. Zwiększenie limitu połączeń może przynieść ulgę, ale może też przenieść przeciążenie na serwer bazy danych. Rozwiązanie zaczyna się od ustalenia, jaki zasób jest wyczerpany i co utrzymuje połączenia zajęte.

Rozpoznaj objawy i określ zakres awarii

Rozpoznaj objawy i określ zakres awarii — guía visual de DedicatedPHP

Szukaj błędów takich jak „too many connections”, nieudane próby otwarcia połączenia, przekroczenia limitu czasu oczekiwania lub żądania przekraczające maksymalny czas wykonania. Porównaj ich częstotliwość z ruchem oraz innymi wskaźnikami: opóźnieniami aplikacji, użyciem CPU i pamięci, błędami bazy danych oraz czasem obsługi żądań.

Różnica między dużym a małym obciążeniem daje pierwszą wskazówkę. Jeśli błędy pojawiają się w szczytach ruchu i znikają po jego spadku, przyczyną może być limit współbieżności. Jeśli utrzymują się przy niewielkiej liczbie żądań, zbadaj przetrzymywane połączenia, zablokowane procesy, długotrwałe zapytania lub niedostępność bazy danych. Sprawdź też, czy ten sam limit obowiązuje inne usługi: PHP nie musi być jedynym użytkownikiem połączeń.

Odróżnij wyczerpanie połączeń od wolnych zapytań i blokad

To problemy powiązane, ale nie tożsame. Wyczerpanie połączeń występuje, gdy nie ma wolnego miejsca na otwarcie kolejnego połączenia. Wolne zapytanie zajmuje połączenie dłużej i może doprowadzić do wyczerpania puli, gdy takie zapytania się kumulują. Blokada powoduje, że zapytanie czeka, aż inna transakcja zwolni zasoby. Niedostępność oznacza, że z szerszej przyczyny baza danych nie może przyjmować połączeń lub ich obsługiwać.

Przeanalizuj komunikat i miejsce wystąpienia błędu. Jeśli żądanie kończy się niepowodzeniem przed wykonaniem zapytania, sprawdź nawiązywanie połączeń i osiągnięty limit. Jeśli połączenie zostaje nawiązane, ale dalsze działanie trwa długo, zbadaj wykonywane zapytania, ich czas, oczekiwanie i otwarte transakcje. Nie zakładaj, że „brakuje połączeń” tylko dlatego, że aplikacja odpowiada wolno: zwiększenie limitu nie rozwiąże problemu kosztownego zapytania ani blokady.

Powiąż współbieżność PHP z limitem bazy danych

W typowym modelu PHP, w którym procesy obsługują żądania, każdy proces może potrzebować połączenia podczas wykonywania operacji na bazie danych. Potencjalne zapotrzebowanie zależy od liczby procesów mogących działać jednocześnie, liczby połączeń otwieranych przez każdy proces oraz czasu ich utrzymywania. Należy też uwzględnić połączenia używane przez zadania w tle, polecenia konsoli i inne usługi.

Oszacuj zachowawczo najgorszy przypadek: pomnóż maksymalną efektywną współbieżność każdej grupy procesów przez liczbę połączeń, z których każdy proces może korzystać jednocześnie, a następnie dodaj użytkowników współdzielących bazę danych. Porównaj wynik z skonfigurowanym limitem i pozostaw zapas na operacje administracyjne oraz wahania obciążenia. Nie zakładaj, że każde żądanie zawsze oznacza jedno połączenie: cykl życia połączenia zależy od klienta bazy danych, konfiguracji i sposobu użycia.

Sprawdź także rozkład obciążenia. Wiele instancji PHP może przestrzegać własnych limitów, a mimo to łącznie przekroczyć limit bazy danych. Skalowanie poziome zwiększa potencjalną współbieżność; nie jest bezpiecznym sposobem ograniczania problemu, jeśli wcześniej nie przeliczy się łącznej liczby połączeń.

Mierz z obu stron

Skoreluj metryki aplikacji i bazy danych, używając znaczników czasu. W PHP rejestruj czas obsługi żądań, błędy nawiązywania połączeń, czasy oczekiwania i liczbę zajętych procesów. W bazie danych sprawdzaj aktywne i maksymalne połączenia, odrzucenia, wykonywane zapytania, wiek sesji oraz informacje o oczekiwaniu dostępne w danym silniku.

Unikaj rejestrowania danych uwierzytelniających, pełnych ciągów połączenia ani wrażliwych danych z zapytań. Jeśli silnik pozwala identyfikować sesje i ich stany, wykorzystaj tę możliwość, aby odróżnić nieaktywną sesję od aktywnego zapytania lub oczekującej transakcji. Porównaj logi z obu stron: jednoczesny wzrost liczby połączeń i zajętych procesów PHP wskazuje na współbieżność; wiele starych sesji lub nieaktywnych procesów sugeruje przetrzymywanie połączeń; kilka długotrwałych zapytań może wyjaśniać stopniowe wyczerpywanie limitu.

Instrumentacja powinna pozwalać odpowiedzieć na trzy pytania: ile połączeń jest używanych, jak długo trwają i jakie zadania utrzymują je zajęte. Bez takiej osi czasu zmiana limitów lub włączenie połączeń trwałych wprowadza dodatkowe zmienne i utrudnia znalezienie przyczyny.

Oceń połączenia trwałe i długotrwałe

Połączenie trwałe może ograniczyć koszt wielokrotnego otwierania połączeń, zwłaszcza gdy środowisko zachowuje procesy między żądaniami. Jednak połączenie przypisane do procesu może nadal zajmować dostępny limit, nawet gdy nie wykonuje zapytań. Jeśli procesów lub instancji jest wiele, łączna liczba przetrzymywanych połączeń może osiągnąć limit bazy danych.

Zanim włączysz lub wyłączysz tę funkcję, sprawdź rzeczywisty cykl życia procesu i sterownika. Ustal, jak sesja jest ponownie wykorzystywana i czy aplikacja przywraca oczekiwany stan między żądaniami, na przykład transakcje, zmienne sesji lub ustawienia specyficzne dla połączenia. Połączenia trwałe nie są uniwersalną pulą ani gwarancją mniejszego zużycia; testuj je przy reprezentatywnym obciążeniu i obserwuj maksymalną liczbę połączeń, opóźnienia oraz pozostawiony stan.

Wprowadzaj środki zaradcze po kolei i na podstawie danych

  1. Ogranicz współbieżność. Dostosuj liczbę procesów PHP lub równoległość pracowników tak, aby jednoczesne zapotrzebowanie mieściło się we wspólnym limicie. Zmniejszy to presję, choć może wydłużyć kolejkę i zwiększyć opóźnienia, jeśli dostępna przepustowość będzie niższa od utrzymującego się zapotrzebowania.
  2. Zwalniaj zasoby, gdy nie są już potrzebne. Zamykaj połączenia jawnie, jeśli pozwalają na to biblioteka i sposób wykonywania, oraz unikaj ich utrzymywania podczas pracy niezwiązanej z bazą danych. Pamiętaj, że zamknięcie połączenia trwałego niekoniecznie zwalnia fizyczne połączenie na serwerze: zależy to od sterownika i cyklu życia procesu. Sprawdź, czy transakcje nie pozostają otwarte i czy ścieżki obsługi błędów poprawnie wykonują sprzątanie.
  3. Skróć czas zajmowania połączeń. Przeanalizuj wolne zapytania, indeksy, wielkość wyników i transakcje. Optymalizacja operacji, która długo utrzymuje połączenie, może zmniejszyć jednoczesne zapotrzebowanie bez podnoszenia limitu.
  4. Zmieniaj limity dopiero po pomiarach. Zwiększenie maksimum może być uzasadnione, jeśli bazie danych pozostaje odpowiedni zapas CPU i pamięci, a nowy najgorszy przypadek jest możliwy do obsłużenia. W przeciwnym razie pozwoli to na kumulowanie większej liczby zadań i pogłębi przeciążenie.

Wprowadzaj jedną zmianę naraz, zapisuj poprzedni stan i określ warunek wycofania. Jeśli system już ma problemy, tymczasowe ograniczenie współbieżności może być bezpieczniejsze niż jednoczesne ponowne uruchomienie wszystkich procesów, które mogłoby wywołać nowy szczyt liczby połączeń.

Kiedy rozważyć pulę lub proxy połączeń

Pula lub proxy może ponownie wykorzystywać fizyczne połączenia i kontrolować ich liczbę docierającą do silnika, co jest przydatne, gdy wiele procesów aplikacji używa połączeń o krótkim czasie życia. Nie eliminuje to równoczesnej pracy ani nie przyspiesza zapytań; dodaje kolejną warstwę z własną przepustowością, kolejkami, limitami i trybami działania.

Przed wdrożeniem sprawdź zgodność z silnikiem, sterownikiem PHP, uwierzytelnianiem, użyciem transakcji i stanem sesji. Zbadaj, jak rozwiązanie obsługuje długotrwałe połączenia, ponowne łączenie i awarie proxy, oraz określ metryki i procedury operacyjne. Przeprowadź testy odzwierciedlające rzeczywistą współbieżność: konfiguracja działająca w środowisku programistycznym może zachowywać się inaczej pod dużym obciążeniem.

Przygotuj się na przywrócenie sprawności i zapobiegaj nawrotom

Przygotuj się na przywrócenie sprawności i zapobiegaj nawrotom — guía visual de DedicatedPHP

Skonfiguruj alerty dotyczące liczby połączeń zbliżającej się do limitu, odrzuceń, czasu wykonywania zapytań i przeciążenia procesów PHP. Dodaj reprezentatywny test obciążeniowy uwzględniający instancje, zadania w tle i innych użytkowników; sprawdź najgorszy przypadek, a nie tylko średnią. Przygotuj procedurę operacyjną opisującą, co mierzyć, jak ograniczać współbieżność, kto może zmienić limit i kiedy wycofać zmianę.

Po przywróceniu działania przeanalizuj sekwencję zdarzeń poprzedzających incydent: zmiany ruchu, wdrożenia, nowe zapytania, wzrost liczby procesów lub błędy sprzątania. Celem jest powiązanie przyczyny ze skutkiem na podstawie danych. Jeśli metryki wskazują na przetrzymywane połączenia, popraw ich cykl życia; jeśli problemem jest czas wykonywania zapytań, zoptymalizuj je; jeśli uzasadniona współbieżność przekracza możliwości systemu, dobierz zasoby i wprowadź limity na podstawie jawnego budżetu połączeń.

Chcesz zastosować te pomysły w swoim projekcie?Omówmy Twoją platformę PHP.
Zobacz powiązaną usługę