Jakie są wady korzystania z trwałego połączenia w PDO

W PDO połączenie może być wykonane za pomocą atrybutu PDO::ATTR_PERSISTENT. Zgodnie z podręcznikiem php -

Trwałe połączenia nie są zamykane na końcu skryptu, ale są buforowane i ponownie używane, gdy inny skrypt żąda połączenia za pomocą te same referencje. Pamięć podręczna stałego połączenia pozwala na unikaj kosztów związanych z nawiązywaniem nowego połączenia za każdym razem, gdy skrypt musi rozmawiać z bazą danych, co skutkuje szybszą siecią podanie.

Podręcznik zaleca również, aby nie używać stałego połączenia podczas korzystania ze sterownika PDO ODBC, ponieważ może to utrudnić proces łączenia połączeń ODBC.

Więc najwyraźniej nie ma żadnych wad używania trwałego połączenia w PDO, z wyjątkiem ostatniego przypadku. Jednak., Chciałbym wiedzieć, czy są jakieś inne wady stosowania tego mechanizmu, tj. sytuacja, w której mechanizm ten powoduje degradację wydajności czy coś w tym stylu.

 161
Author: MD Sayem Ahmed, 2010-07-26

8 answers

Koniecznie przeczytaj tę odpowiedź poniżej, w której opisano sposoby łagodzenia opisanych tutaj problemów.


Te same wady istnieją przy użyciu PDO, jak w przypadku każdego innego interfejsu bazy danych PHP, który wykonuje trwałe połączenia: jeśli twój skrypt nieoczekiwanie zakończy się w środku operacji na bazie danych, następne żądanie, które uzyska Pozostałe połączenie, zostanie odebrane tam, gdzie martwy skrypt został przerwany. Połączenie jest otwarte na poziomie menedżera procesów (Apache for mod_php, bieżący proces FastCGI, jeśli używasz FastCGI, itp.), nie na poziomie PHP, A PHP nie mówi procesowi macierzystemu, aby pozwolił na śmierć połączenia, gdy skrypt zakończy się nieprawidłowo.

Jeśli martwy skrypt zablokuje tabele, te tabele pozostaną zablokowane aż do śmierci połączenia lub następnego skryptu, który uzyska połączenie, odblokuje same tabele.

Jeśli martwy skrypt był w środku transakcji, może to zablokować wiele tabel, dopóki nie uruchomi się zegar impasu, i nawet wtedy, deadlock timer może zabić nowsze żądanie zamiast starszego żądania, które powoduje problem.

Jeśli martwy skrypt był w środku transakcji, następny skrypt, który otrzyma to połączenie, również otrzyma stan transakcji. Jest bardzo możliwe (w zależności od projektu aplikacji), że następny skrypt może w rzeczywistości nigdy nie próbować zatwierdzić istniejącej transakcji lub zatwierdzić, gdy nie powinna mieć, lub cofnąć, gdy nie powinna mieć.

To to tylko wierzchołek góry lodowej. Wszystko to może być złagodzone do pewnego stopnia, zawsze próbując oczyścić po brudnym połączeniu na każdym pojedynczym żądaniu skryptu, ale może to być ból w zależności od bazy danych. Jeśli nie zidentyfikowałeś tworzenia połączeń do bazy danych jako jedyną rzeczą, która jest wąskim gardłem w Twoim skrypcie( oznacza to, że wykonałeś profilowanie kodu za pomocą xdebugi/lub xhprof), powinieneś Nie traktować trwałe połączenia jako rozwiązanie do cokolwiek.

Ponadto, większość nowoczesnych baz danych (w tym PostgreSQL) ma swoje własne preferowane sposoby wykonywania poolingu połączeń, które nie mają natychmiastowych wad, jakie mają trwałe połączenia oparte na PHP plain vanilla.


Aby wyjaśnić sprawę, używamy trwałych kontaktów w moim miejscu pracy, ale nie z wyboru. Napotkaliśmy dziwne zachowanie połączenia, w którym początkowe połączenie z naszego serwera aplikacji do naszego serwera bazy danych trwało dokładnie trzy sekundy, kiedy to powinno zająć ułamek sekundy. Uważamy, że to błąd jądra. Zrezygnowaliśmy z prób rozwiązywania problemów, ponieważ stało się to przypadkowo i nie można go odtworzyć na żądanie, a nasz zlecony Na Zewnątrz nie miał konkretnej możliwości wyśledzenia go.

Niezależnie od tego, kiedy ludzie w magazynie przetwarzają kilkaset przychodzących części, a każda część zajmuje trzy i pół sekundy zamiast pół sekundy, musieliśmy wziąć akcja zanim porwali nas wszystkich i kazali im pomóc. Tak więc, rzuciliśmy kilka bitów na naszej domowej potworności ERP / CRM/CMS i doświadczyliśmy wszystkich okropności trwałych połączeń z pierwszej ręki. Zajęło nam to tygodnie, aby znaleźć wszystkie subtelne problemy i dziwne zachowania, które wydarzyły się pozornie przypadkowo. Okazało się, że te raz w tygodniu fatalne błędy, które nasi użytkownicy pilnie wyciskali z naszej aplikacji, opuszczały zablokowane stoły, porzucone transakcje i inne niefortunne Stany wonky.

Ta szlochająca historia ma rację: złamała rzeczy, których nie spodziewaliśmy się złamać, wszystko w imię performance. kompromis nie był tego wart, a my niecierpliwie czekamy na dzień, w którym możemy powrócić do normalnych połączeń bez zamieszek ze strony naszych użytkowników.

 257
Author: Charles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:23

W odpowiedzi na powyższy problem Karola,

From: http://www.php.net/manual/en/mysqli.quickstart.connections.php -

Powszechnym narzekaniem na trwałe połączenia jest to, że ich stan nie jest resetowany przed ponownym użyciem. Na przykład otwarte i niedokończone transakcje nie są automatycznie wycofywane. Ale również zmiany autoryzacji, które miały miejsce w czasie między wprowadzeniem połączenia do puli a jego ponownym użyciem, nie są odzwierciedlane. Może to być postrzegane jako niepożądane efekt uboczny. Wręcz przeciwnie, nazwa persistent może być rozumiana jako obietnica, że państwo jest wytrwałe.

Rozszerzenie mysqli obsługuje zarówno interpretacje trwałego połączenia: stan utrzymany, jak i reset stanu przed ponownym użyciem. Domyślną wartością jest reset. Przed ponownym użyciem trwałego połączenia, rozszerzenie mysqli domyślnie wywołuje mysqli_change_user(), aby zresetować stan. Trwałe połączenie wydaje się użytkownikowi tak, jakby zostało właśnie otwarte. Nie ma artefaktów z poprzednich zastosowań widoczne.

Funkcja mysqli_change_user() jest kosztowną operacją. Aby uzyskać najlepszą wydajność, użytkownicy mogą chcieć przekompilować rozszerzenie z ustawioną flagą compile MYSQLI_NO_CHANGE_USER_ON_PCONNECT.

Użytkownikowi pozostaje wybór pomiędzy bezpiecznym zachowaniem a najlepszą wydajnością. Oba są ważnymi celami optymalizacji. Dla ułatwienia użytkowania, bezpieczne zachowanie zostało ustawione jako domyślne kosztem maksymalnej wydajności.

 41
Author: Prashant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-26 14:37:57

W moich testach miałem czas połączenia ponad sekundę do mojego localhost, więc zakładając, że powinienem użyć stałego połączenia. Kolejne testy wykazały, że był to problem z "localhost":

Wyniki testu w sekundach (mierzone przez PHP microtime):

  • hosted web: connectDB: 0.0038912296295166
  • localhost: connectDB: 1.0214691162109 (w ciągu jednej sekundy: nie używaj localhost!)
  • 127.0.0.1: connectDB: 0.00097203254699707

Co ciekawe: następujące kod jest tak samo szybki jak użycie 127.0.0.1:

$host = gethostbyname('localhost');
// echo "<p>$host</p>";
$db = new PDO("mysql:host=$host;dbname=" . DATABASE . ';charset=utf8', $username, $password,
    array(PDO::ATTR_EMULATE_PREPARES => false,
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
 11
Author: Gunnar Bernstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-26 09:58:18

Trwałe połączenia są dobrym pomysłem tylko wtedy, gdy połączenie z bazą danych zajmuje (stosunkowo) dużo czasu. W dzisiejszych czasach prawie nigdy tak nie jest. Największą wadą trwałych połączeń jest to, że ogranicza liczbę użytkowników, których możesz przeglądać witrynę: jeśli MySQL jest skonfigurowany tak, aby zezwalał tylko na równoczesne połączenia 10 naraz, to gdy 11 osoba próbuje przeglądać witrynę, nie będzie dla nich działać.

PDO nie zarządza trwałością. Sterownik MySQL tak. Informatyka ponownie wykorzystuje połączenia, gdy a) są one dostępne I host/użytkownik/hasło/baza danych pasują. Jeśli jakakolwiek zmiana nie spowoduje ponownego użycia połączenia. Najlepszym efektem sieciowym jest to, że te połączenia, które masz, będą uruchamiane i zatrzymywane tak często, ponieważ masz różnych użytkowników na stronie, a ich trwałe działanie nie robi nic dobrego.

Kluczową rzeczą do zrozumienia na temat trwałych połączeń jest to, że nie należy ich używać w większości aplikacji internetowych. Brzmią kusząco, ale są niebezpieczne i bezużyteczne.

Jestem pewien, że są inne wątki na ten temat, ale trwałe połączenie jest niebezpieczne, ponieważ utrzymuje się między żądaniami. Jeśli na przykład zablokujesz stół podczas żądania, a następnie nie uda Ci się go odblokować, stół pozostanie zablokowany na czas nieokreślony. Trwałe połączenia są również praktycznie bezużyteczne w 99% Twoich aplikacji, ponieważ nie masz możliwości sprawdzenia, czy to samo połączenie będzie używane między różnymi żądaniami. Każdy wątek www będzie miał to własny zestaw trwałych połączeń i nie masz możliwości kontrolowania, który wątek będzie obsługiwał które żądania.

Proceduralna biblioteka mysql PHP, posiada funkcję, dzięki której kolejne wywołania do mysql_connect zwrócą ten sam link, zamiast otworzyć inne połączenie (jak można się spodziewać). Nie ma to nic wspólnego z trwałymi połączeniami i jest specyficzne dla biblioteki mysql. PDO nie wykazuje takiego zachowania


Resource Link: link

In Ogólne możesz użyć tego jako szorstki "zestaw reguł"::

tak , użyj trwałych połączeń, Jeśli:

  • do bazy danych ma dostęp tylko kilka aplikacji/użytkowników, tj. nie spowoduje to 200 otwartych (ale prawdopodobnie bezczynnych) połączeń, ponieważ na tym samym hoście jest 200 różnych użytkowników.
  • Baza danych działa na innym serwerze, do którego uzyskujesz dostęp sieć

  • (jedna) aplikacja uzyskuje dostęp do bazy danych bardzo często

nie, nie używaj trwałych połączeń, Jeśli:

  • Twoja aplikacja musi uzyskać dostęp do bazy danych tylko 100 razy na godzinę.

  • Masz wiele, wiele webserverów, którzy mają dostęp do jednego serwera bazy danych

Używanie trwałych połączeń jest znacznie szybsze, zwłaszcza jeśli uzyskujesz dostęp do bazy danych przez sieć. To nie ma tak wielkiej różnicy, czy baza danych jest uruchomiona na tym samym komputerze, ale nadal jest trochę szybciej. Jednak - jak sama nazwa mówi-połączenie jest trwałe, tzn. pozostaje otwarte, nawet jeśli nie jest używane.

Problem polega na tym, że w" domyślnej konfiguracji "MySQL zezwala tylko na 1000 równoległych "otwartych kanałów". Po tym, nowe połączenia są odrzucane(można dostosować to ustawienie). Więc jeśli masz-powiedzmy-20 Webserverów z każdym klientem 100, a każdy z nich ma tylko jeden dostęp do strony na godzinę, prosta matematyka pokaże ci, że będziesz potrzebował 2000 równoległych połączenia z bazą danych. To nie zadziała.

Ergo: używaj go tylko do aplikacji z dużą ilością zapytań.

 9
Author: Jhonathan H.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:28

Trwałe połączenia powinny zwiększyć wydajność. Nie zgadzam się z twierdzeniem, że należy "unikać" uporu..

Wygląda na to, że powyższe skargi są napędzane przez kogoś, kto używa tabel MyIASM i hakuje we własnych wersjach transakcji poprzez chwytanie blokad tabel.. Oczywiście, że tak! Użyj metody beginTransaction () PDO i przenieś swoje tabele do InnoDB..

 6
Author: Stephen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-04 16:01:48

Wydaje mi się, że stałe połączenie zjadłoby więcej zasobów systemowych. Może trywialna kwota, ale i tak...

 2
Author: Crayon Violent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-26 03:50:28

Wyjaśnieniem używania trwałych połączeń jest oczywiście zmniejszenie ilości połączeń, które są dość kosztowne, pomimo faktu, że są one znacznie szybsze z MySQL w porównaniu do innych baz danych.

Pierwszy problem z trwałymi połączeniami...

Jeśli tworzysz 1000 połączeń na sekundę, zwykle nie upewniasz się, że pozostają otwarte przez bardzo długi czas, ale system operacyjny tak. Oparte na protokole TCP / IP porty nie mogą być natychmiast przetwarzane i również trzeba zainwestować chwilę w" FIN " etapie czekając, zanim mogą być poddane recyklingowi.

Drugi problem... korzystanie z wielu połączeń serwera MySQL.

Wiele osób po prostu nie zdaje sobie sprawy, że jesteś w stanie zwiększyć zmienną *max_connections* i uzyskać ponad 100 jednoczesnych połączeń z MySQL inni zostali pokonani przez starsze problemy z Linuksem z niemożnością przekazania więcej niż 1024 połączeń z MySQL.

Pozwala teraz rozmawiać o tym, dlaczego trwałe połączenia zostały wyłączone w mysqli przedłużenie. Pomimo faktu, że można nadużywać trwałych połączeń i uzyskać słabą wydajność, co nie było głównym powodem. Faktycznym powodem jest-można uzyskać o wiele więcej problemów z nim.

Trwałe połączenia były wprowadzane do PHP przez cały czas MySQL 3.22/3.23, gdy MySQL nie był tak trudny, co oznacza, że można było łatwo przetwarzać połączenia bez żadnych problemów. W późniejszych wersjach pojawiało się jednak wiele problemów – w przypadku recyclingu połączenia, które nie transakcje, które wpadasz w kłopoty. Jeśli odzyskasz połączenia z niestandardowymi konfiguracjami zestawów znaków, ponownie jesteś w niebezpieczeństwie, a także prawdopodobnie zmienisz zmienne w danej sesji.

Problem z używaniem trwałych połączeń polega na tym, że nie skaluje się tak dobrze. Dla tych, którzy mają podłączonych 5000 osób, potrzebujesz 5000 trwałych połączeń. Aby uzyskać wymóg wytrwałości, możesz mieć możliwość obsługi 10000 osób z podobną ilością połączeń ponieważ są w stanie dzielić się indywidualnymi połączeniami, gdy nie są z nimi.

 1
Author: Tony Stark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-03 09:01:13

Zastanawiałem się tylko, czy rozwiązaniem częściowym byłoby mieć pulę zastosowań - raz połączenia. Możesz poświęcić czas na tworzenie puli połączeń, gdy system jest w niskim zużyciu, do limitu, rozdać je i zabić, gdy ukończą lub przekroczą limit czasu. W tle tworzysz nowe połączenia, gdy są one podejmowane. W najgorszym przypadku powinno to być tak powolne, jak tworzenie połączenia bez puli, zakładając, że ustanowienie połączenia jest czynnikiem ograniczającym?

 0
Author: James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-03 09:21:31