W PDO połączenie można ustawić na stałe za pomocą tego PDO::ATTR_PERSISTENT
atrybutu. Zgodnie z instrukcją 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 przy użyciu tych samych poświadczeń. Trwała pamięć podręczna połączeń pozwala uniknąć narzutów związanych z nawiązywaniem nowego połączenia za każdym razem, gdy skrypt musi rozmawiać z bazą danych, co powoduje szybszą aplikację internetową.
Podręcznik zaleca również, aby nie używać trwałego połączenia podczas korzystania ze sterownika ODBC PDO, ponieważ może to utrudnić proces tworzenia puli połączeń ODBC.
Wygląda więc na to, że nie ma żadnych wad używania trwałego połączenia w PDO, z wyjątkiem ostatniego przypadku. Chciałbym jednak wiedzieć, czy istnieją inne wady korzystania z tego mechanizmu, tj. Sytuacja, w której ten mechanizm powoduje pogorszenie wydajności lub coś w tym rodzaju.
Odpowiedzi:
Przeczytaj tę odpowiedź poniżej , która szczegółowo opisuje sposoby złagodzenia opisanych tutaj problemów.
Przy użyciu PDO występują te same wady, co w przypadku każdego innego interfejsu bazy danych PHP, który wykonuje trwałe połączenia: jeśli skrypt nieoczekiwanie zakończy się w trakcie operacji na bazie danych, następne żądanie, które spowoduje przerwanie połączenia, odbierze miejsce, w którym przerwany został martwy skrypt. Połączenie jest utrzymywane otwarte na poziomie menedżera procesów (Apache dla mod_php, bieżący proces FastCGI, jeśli używasz FastCGI itp.), A nie na poziomie PHP, a PHP nie mówi procesowi nadrzędnemu, aby pozwolił umrzeć połączeniu, gdy skrypt kończy się nienormalnie.
Jeśli martwe skrypty zablokowały tabele, tabele te pozostaną zablokowane, dopóki połączenie nie zostanie przerwane lub następny skrypt, który uzyska połączenie, odblokuje same tabele.
Jeśli martwy skrypt znajdował się w środku transakcji, może blokować wiele tabel, dopóki nie uruchomi się licznik zakleszczenia, a nawet wtedy zegar zakleszczenia może zabić nowsze żądanie zamiast starszego żądania, które powoduje problem.
Jeśli martwy skrypt znajdował się w środku transakcji, następny skrypt, który pobierze 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 nigdy nie próbować zatwierdzić istniejącej transakcji, lub zatwierdzi, gdy nie powinien, lub wycofa się, gdy nie powinien.
To tylko wierzchołek góry lodowej. Można to wszystko złagodzić do pewnego stopnia, zawsze próbując wyczyścić po brudnym połączeniu przy każdym żądaniu skryptu, ale może to być uciążliwe w zależności od bazy danych. Chyba, że zidentyfikowali tworzenia połączeń bazie danych jako jedna rzecz, która jest wąskim gardłem w skrypcie (oznacza to zrobiłeś kod profilowania za pomocą Xdebug i / lub xhprof ), należy nie rozważyć stałe połączenia w postaci roztworu do niczego.
Co więcej, większość współczesnych baz danych (w tym PostgreSQL) ma swoje preferowane sposoby wykonywania pul połączeń, które nie mają bezpośrednich wad, jak zwykłe trwałe połączenia oparte na PHP.
Aby wyjaśnić tę kwestię, używamy trwałych połączeń w moim miejscu pracy, ale nie z wyboru. Napotkaliśmy dziwne zachowanie połączenia, gdy początkowe połączenie z naszego serwera aplikacji do naszego serwera bazy danych trwało dokładnie trzy sekundy, kiedy powinno to zająć ułamek sekundy. Uważamy, że to błąd jądra. Zrezygnowaliśmy z próby rozwiązania tego problemu, ponieważ zdarzyło się to losowo i nie można go było odtworzyć na żądanie, a nasze outsourcingowe informatyki nie miały konkretnej możliwości wyśledzenia.
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 podjąć działania, zanim nas porwali i zmusili do pomocy. Więc włączyliśmy kilka bitów w naszą domową potworność ERP / CRM / CMS i doświadczyliśmy wszystkich okropności trwałych połączeń z pierwszej ręki. Wyszukanie wszystkich subtelnych drobnych problemów i dziwnych zachowań, które wydawały się przypadkowe, zajęło nam tygodnie . Okazało się, że te fatalne błędy raz w tygodniu, które pilnie wycisnęli nasi użytkownicy z naszej aplikacji, pozostawiały zablokowane tabele, porzucone transakcje i inne niefortunne kłopotliwe stany.
Ta szlochająca historia ma sens: zepsuła rzeczy, których nigdy się nie spodziewaliśmy, wszystko w imię występu. Kompromis nie był tego warty iz niecierpliwością czekamy na dzień, w którym możemy wrócić do normalnych połączeń bez zamieszek ze strony naszych użytkowników.
źródło
SELECT orders.* FROM orders LEFT JOIN items USING(item_id)
register_shutdown_function()
. Jeśli proces umrze, połączenie również umrze. Jeśli nie, połączenie jest resetowane do stanu czystego (np. Otwarte transakcje są wycofywane). Jeśli to się nie powiedzie, połączenie zostanie zamknięte, a nowe zostanie otwarte przy kolejnym żądaniu tego samego procesu. Nie ma potrzeby demonizacji trwałych połączeń.mysqli_change_user
jest prawdopodobnie najlepszym rozwiązaniem dla osób, które muszą utrzymywać trwałe połączenia w aplikacji nieprzeznaczonej do rozwiązywania problemów ze stanem.W odpowiedzi na powyższy problem Charlesa,
Od: http://www.php.net/manual/en/mysqli.quickstart.connections.php -
Częstą skargą 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 nastąpiły w czasie między umieszczeniem połączenia w puli a ponownym użyciem go, nie są odzwierciedlane. Może to być postrzegane jako niepożądany efekt uboczny. Wręcz przeciwnie, nazwa uparta może być rozumiana jako obietnica, że państwo będzie trwać.
Rozszerzenie mysqli obsługuje obie interpretacje trwałego połączenia: stan trwał i reset stanu przed ponownym użyciem. Domyślnie jest resetowany. Przed ponownym użyciem trwałego połączenia rozszerzenie mysqli domyślnie wywołuje
mysqli_change_user()
resetowanie stanu. Trwałe połączenie wydaje się użytkownikowi tak, jakby właśnie zostało otwarte. Żadne artefakty z poprzednich zastosowań nie są widoczne.Ta
mysqli_change_user()
funkcja jest kosztowną operacją. Aby uzyskać najlepszą wydajność, użytkownicy mogą chcieć ponownie skompilować rozszerzenie z ustawioną flagą kompilacjiMYSQLI_NO_CHANGE_USER_ON_PCONNECT
.Użytkownik może wybrać bezpieczne zachowanie i najlepszą wydajność. Oba są ważnymi celami optymalizacji. Dla łatwości użytkowania bezpieczne zachowanie stało się domyślnym kosztem maksymalnej wydajności.
źródło
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órzy mogą przeglądać twoją stronę: jeśli MySQL jest skonfigurowany tak, aby zezwalał tylko na 10 równoczesnych połączeń na raz, to kiedy 11. osoba próbuje przeglądać twoją stronę, nie będzie dla nich działać .
PDO nie zarządza trwałością. Sterownik MySQL działa. Ponownie wykorzystuje połączenia, gdy a) są dostępne, a host / użytkownik / hasło / baza danych są zgodne. W przypadku jakichkolwiek zmian połączenie nie zostanie ponownie użyte. Najlepszym efektem netto jest to, że te połączenia, które masz, będą tak często uruchamiane i zatrzymywane, ponieważ masz różnych użytkowników w witrynie, a ich utrzymywanie nie przyniesie nic dobrego.
Kluczową rzeczą do zrozumienia na temat trwałych połączeń jest to, że NIE powinieneś ich używać w większości aplikacji internetowych. Brzmią kusząco, ale są niebezpieczne i prawie bezużyteczne.
Jestem pewien, że są w tym inne wątki, ale trwałe połączenie jest niebezpieczne, ponieważ utrzymuje się między żądaniami. Jeśli na przykład zablokujesz tabelę podczas żądania, a następnie nie odblokujesz, wówczas ta tabela pozostanie zablokowana na czas nieokreślony. Trwałe połączenia są również prawie bezużyteczne dla 99% twoich aplikacji, ponieważ nie masz możliwości dowiedzenia się, czy to samo połączenie będzie używane między różnymi żądaniami. Każdy wątek internetowy będzie miał swój własny zestaw trwałych połączeń i nie będziesz mieć możliwości kontrolowania, który wątek obsłuży które żądania.
Proceduralna biblioteka mysql PHP ma funkcję, dzięki której kolejne wywołania mysql_connect zwrócą to samo łącze, zamiast otwierać 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. ChNP nie wykazuje takiego zachowania
Link do zasobu: link
Ogólnie możesz użyć tego jako szorstkiego „zestawu reguł”:
TAK , użyj trwałych połączeń, jeśli:
Baza danych działa na innym serwerze, do którego uzyskujesz dostęp przez sieć
(Jedna) aplikacja bardzo często uzyskuje dostęp do bazy danych
NIE , nie używaj trwałych połączeń, jeśli:
Twoja aplikacja musi mieć dostęp do bazy danych tylko 100 razy na godzinę.
Masz wiele serwerów dostępu do jednego serwera bazy danych
Korzystanie z trwałych połączeń jest znacznie szybsze, szczególnie jeśli uzyskujesz dostęp do bazy danych przez sieć. Nie ma znaczenia, czy baza danych działa na tym samym komputerze, ale wciąż jest nieco szybsza. Jednak - jak sama nazwa wskazuje - 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 dopuszcza tylko 1000 równoległych „otwartych kanałów”. Następnie nowe połączenia są odrzucane (możesz dostosować to ustawienie). Jeśli więc masz, powiedzmy, 20 serwerów WWW ze 100 klientami, a każdy z nich ma dostęp tylko do jednej strony na godzinę, prosta matematyka pokaże, że potrzebujesz 2000 równoległych połączeń z bazą danych. To nie zadziała.
Ergo: używaj go tylko do aplikacji z dużą ilością żądań.
źródło
Podczas moich testów miałem ponad sekundowy czas połączenia z moim lokalnym hostem, zakładając, że powinienem używać stałego połączenia. Dalsze testy wykazały, że był to problem z „localhost”:
Wyniki testu w sekundach (mierzone mikrotimem php):
Co ciekawe: poniższy kod jest tak samo szybki jak przy użyciu 127.0.0.1:
źródło
localhost
używa połączenia z gniazdem, połączenie z gniazdem słynie z tego, że jest złe przy dużej ilości połączeńTrwałe połączenia powinny znacznie zwiększyć wydajność. Nie zgadzam się z twierdzeniem, że powinieneś „Unikać” wytrwałości.
Wygląda na to, że powyższe skargi są kierowane przez kogoś, kto korzysta z tabel MyIASM i włamuje się do własnych wersji transakcji, chwytając blokady tabel. Cóż, oczywiście, że jesteś w impasie! Użyj PDT beginTransaction () i przenieś swoje tabele do InnoDB ..
źródło
Wydaje mi się, że trwałe połączenie zjadłoby więcej zasobów systemowych. Może trywialna kwota, ale wciąż ...
źródło
Wyjaśnienie używania trwałych połączeń w oczywisty sposób zmniejsza liczbę połączeń, które są dość kosztowne, pomimo faktu, że są one znacznie szybsze w 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 pozostaje ono otwarte przez bardzo długi czas, ale robi to System operacyjny. Oparty na protokole TCP / IP Porty nie mogą być natychmiast poddane recyklingowi, a także muszą zainwestować chwilę na etapie „FIN”, zanim będą mogły zostać poddane recyklingowi.
Drugi problem ... przy użyciu wielu połączeń z serwerem MySQL.
Wiele osób po prostu nie zdaje sobie sprawy, że jesteś w stanie zwiększyć zmienną * max_connections * i uzyskać ponad 100 równoczesnych połączeń z MySQL, inni zostali pobici przez starsze problemy Linuksa z niemożnością przekazania więcej niż 1024 połączeń z MySQL.
Pozwala teraz mówić o tym, dlaczego trwałe połączenia zostały wyłączone w rozszerzeniu mysqli. Pomimo tego, że możesz niewłaściwie używać trwałych połączeń i uzyskiwać słabą wydajność, co nie było głównym powodem. Rzeczywisty powód jest taki - możesz mieć z tym o wiele więcej problemów.
Trwałe połączenia były umieszczane w PHP przy różnych okazjach MySQL 3.22 / 3.23, kiedy MySQL nie był tak trudny, co oznacza, że można łatwo przetwarzać połączenia bez żadnych problemów. W późniejszych wersjach pojawiło się jednak wiele problemów - w przypadku recyklingu połączenia z niezatwierdzonymi transakcjami masz problemy. Jeśli przetwarzasz połączenia z niestandardowymi konfiguracjami zestawów znaków, ponownie jesteś w niebezpieczeństwie, a także o możliwości przekształcenia zmiennych sesji.
Jednym z problemów z korzystaniem z trwałych połączeń jest to, że tak naprawdę nie skaluje się tak dobrze. Dla tych, którzy mają 5000 podłączonych osób, potrzebujesz 5000 trwałych połączeń. Aby uniknąć wymogu wytrwałości, możesz mieć możliwość obsługi 10000 osób o podobnej liczbie połączeń, ponieważ są one w stanie dzielić się indywidualnymi połączeniami, gdy ich nie ma.
źródło
Zastanawiałem się tylko, czy częściowym rozwiązaniem byłoby posiadanie puli jednorazowych połączeń. Możesz poświęcić czas na tworzenie puli połączeń, gdy system jest w niskim zużyciu, do limitu, rozdawać je i zabijać, gdy zostaną ukończone lub przekroczą limit czasu. W tle tworzysz nowe połączenia podczas ich pobierania. W najgorszym przypadku powinno to być tak powolne jak tworzenie połączenia bez puli, zakładając, że ustanowienie łącza jest czynnikiem ograniczającym?
źródło