In PDO kann eine Verbindung mithilfe des PDO::ATTR_PERSISTENT
Attributs dauerhaft hergestellt werden . Laut PHP-Handbuch -
Permanente Verbindungen werden nicht am Ende des Skripts geschlossen, sondern zwischengespeichert und wiederverwendet, wenn ein anderes Skript eine Verbindung mit denselben Anmeldeinformationen anfordert. Mit dem permanenten Verbindungscache können Sie den Aufwand vermeiden, jedes Mal eine neue Verbindung herzustellen, wenn ein Skript mit einer Datenbank kommunizieren muss, was zu einer schnelleren Webanwendung führt.
In diesem Handbuch wird außerdem empfohlen, während der Verwendung des PDO-ODBC-Treibers keine dauerhafte Verbindung zu verwenden, da dies den ODBC-Verbindungspooling-Prozess behindern kann.
Anscheinend scheint es keine Nachteile bei der Verwendung einer dauerhaften Verbindung in PDO zu geben, außer im letzten Fall. Ich würde jedoch gerne wissen, ob es andere Nachteile bei der Verwendung dieses Mechanismus gibt, dh eine Situation, in der dieser Mechanismus zu Leistungseinbußen oder Ähnlichem führt.
Antworten:
Bitte lesen Sie diese Antwort weiter unten , in der die Möglichkeiten zur Minderung der hier beschriebenen Probleme aufgeführt sind.
Bei der Verwendung von PDO bestehen dieselben Nachteile wie bei jeder anderen PHP-Datenbankschnittstelle, die dauerhafte Verbindungen herstellt: Wenn Ihr Skript während eines Datenbankvorgangs unerwartet beendet wird, wird die nächste Anforderung, die die verbleibende Verbindung erhält, dort fortgesetzt, wo das tote Skript aufgehört hat. Die Verbindung wird auf Prozessmanagerebene offen gehalten (Apache für mod_php, der aktuelle FastCGI-Prozess, wenn Sie FastCGI verwenden usw.), nicht auf PHP-Ebene, und PHP weist den übergeordneten Prozess nicht an, die Verbindung zu beenden, wenn Das Skript wird abnormal beendet.
Wenn das tote Skript Tabellen gesperrt hat, bleiben diese Tabellen gesperrt, bis die Verbindung unterbrochen wird oder das nächste Skript, das die Verbindung erhält, die Tabellen selbst entsperrt.
Wenn sich das Dead-Skript mitten in einer Transaktion befand, kann dies eine Vielzahl von Tabellen blockieren, bis der Deadlock-Timer aktiviert wird, und selbst dann kann der Deadlock-Timer die neuere Anforderung anstelle der älteren Anforderung, die das Problem verursacht, beenden.
Wenn sich das tote Skript mitten in einer Transaktion befand, erhält das nächste Skript, das diese Verbindung erhält, auch den Transaktionsstatus. Es ist sehr wahrscheinlich (abhängig von Ihrem Anwendungsdesign), dass das nächste Skript möglicherweise nie versucht, die vorhandene Transaktion festzuschreiben, oder festschreibt, wenn dies nicht der Fall sein sollte, oder ein Rollback, wenn dies nicht der Fall sein sollte.
Dies ist nur die Spitze des Eisbergs. Dies kann bis zu einem gewissen Grad gemildert werden, indem bei jeder einzelnen Skriptanforderung immer versucht wird, nach einer fehlerhaften Verbindung aufzuräumen. Dies kann jedoch je nach Datenbank problematisch sein. Es sei denn , Sie identifiziert haben Datenbankverbindungen wie das Erstellen der eine Sache , die ein Engpass in Ihrem Skript (das heißt , Sie done Code haben Profilierungs mit xdebug und / oder xhprof ), sollten Sie nicht persistente Verbindungen als Lösung für alles in Betracht ziehen.
Darüber hinaus haben die meisten modernen Datenbanken (einschließlich PostgreSQL) ihre eigenen bevorzugten Methoden zum Durchführen von Verbindungspools, die nicht die unmittelbaren Nachteile aufweisen, die einfache Vanilla-PHP-basierte persistente Verbindungen haben.
Um einen Punkt zu verdeutlichen, verwenden wir an meinem Arbeitsplatz dauerhafte Verbindungen, jedoch nicht nach Wahl. Wir hatten ein seltsames Verbindungsverhalten, bei dem die anfängliche Verbindung von unserem App-Server zu unserem Datenbankserver genau drei Sekunden dauerte, wenn sie einen Bruchteil einer Sekunde hätte dauern sollen. Wir denken, es ist ein Kernel-Bug. Wir haben es aufgegeben, Fehler zu beheben, da dies zufällig geschah und nicht bei Bedarf reproduziert werden konnte und unsere ausgelagerte IT nicht die konkrete Fähigkeit hatte, es aufzuspüren.
Unabhängig davon, wann die Leute im Lager ein paar hundert eingehende Teile bearbeiten und jedes Teil dreieinhalb Sekunden statt einer halben Sekunde dauert, mussten wir Maßnahmen ergreifen, bevor sie uns alle entführten und uns dazu brachten, ihnen zu helfen. Wir haben also ein paar Kleinigkeiten in unserer selbst entwickelten ERP / CRM / CMS-Monstrosität auf den Kopf gestellt und alle Schrecken dauerhafter Verbindungen aus erster Hand erlebt. Wir haben Wochen gebraucht, um all die subtilen kleinen Probleme und bizarren Verhaltensweisen aufzuspüren, die scheinbar zufällig passiert sind. Es stellte sich heraus, dass diese einmal pro Woche schwerwiegenden Fehler, die unsere Benutzer fleißig aus unserer App herausgedrückt hatten, gesperrte Tabellen, abgebrochene Transaktionen und andere unglückliche Wonky-Zustände hinterließen.
Diese Schluchzergeschichte hat einen Punkt: Sie hat Dinge gebrochen, von denen wir nie erwartet hatten, dass sie brechen, alles im Namen der Aufführung. Der Kompromiss hat sich nicht gelohnt und wir warten gespannt auf den Tag, an dem wir ohne Aufruhr unserer Benutzer zu normalen Verbindungen zurückkehren können.
quelle
SELECT orders.* FROM orders LEFT JOIN items USING(item_id)
register_shutdown_function()
. Wenn der Prozess abbricht, stirbt auch die Verbindung. Ist dies nicht der Fall, wird die Verbindung auf ihren sauberen Zustand zurückgesetzt (z. B. werden offene Transaktionen zurückgesetzt). Wenn dies fehlschlägt, wird die Verbindung geschlossen und bei der nächsten Anforderung an denselben Prozess wird eine neue geöffnet. Es besteht keine Notwendigkeit, dauerhafte Verbindungen zu dämonisieren.mysqli_change_user
ist wahrscheinlich immer noch die beste Problemumgehung für Personen, die dauerhafte Verbindungen in einer Anwendung herstellen müssen, die nicht für die Behandlung staatlicher Probleme ausgelegt ist.Als Antwort auf Charles 'Problem oben,
Von: http://www.php.net/manual/en/mysqli.quickstart.connections.php -
Eine häufige Beschwerde über dauerhafte Verbindungen ist, dass ihr Status vor der Wiederverwendung nicht zurückgesetzt wird. Beispielsweise werden offene und nicht abgeschlossene Transaktionen nicht automatisch zurückgesetzt. Aber auch Autorisierungsänderungen, die in der Zeit zwischen dem Einfügen der Verbindung in den Pool und der Wiederverwendung aufgetreten sind, werden nicht berücksichtigt. Dies kann als unerwünschte Nebenwirkung angesehen werden. Im Gegenteil, der Name persistent kann als Versprechen verstanden werden, dass der Staat bestehen bleibt.
Die mysqli-Erweiterung unterstützt beide Interpretationen einer dauerhaften Verbindung: Status bleibt bestehen und Status wird vor der Wiederverwendung zurückgesetzt. Der Standardwert wird zurückgesetzt. Bevor eine dauerhafte Verbindung wiederverwendet wird, ruft die mysqli-Erweiterung implizit
mysqli_change_user()
auf, um den Status zurückzusetzen. Die dauerhafte Verbindung erscheint dem Benutzer so, als wäre sie gerade geöffnet worden. Es sind keine Artefakte aus früheren Verwendungen sichtbar.Die
mysqli_change_user()
Funktion ist eine teure Operation. Um eine optimale Leistung zu erzielen, möchten Benutzer die Erweiterung möglicherweise neu kompilieren, wobei das KompilierungsflagMYSQLI_NO_CHANGE_USER_ON_PCONNECT
gesetzt ist.Es bleibt dem Benutzer überlassen, zwischen sicherem Verhalten und bester Leistung zu wählen. Beides sind gültige Optimierungsziele. Aus Gründen der Benutzerfreundlichkeit wurde das sichere Verhalten auf Kosten maximaler Leistung zum Standard gemacht.
quelle
Permanente Verbindungen sind nur dann eine gute Idee, wenn die Verbindung zu Ihrer Datenbank (relativ) lange dauert. Heutzutage ist das fast nie der Fall. Der größte Nachteil bei dauerhaften Verbindungen besteht darin, dass die Anzahl der Benutzer, die Ihre Website durchsuchen können, begrenzt ist: Wenn MySQL so konfiguriert ist, dass nur 10 gleichzeitige Verbindungen gleichzeitig zulässig sind, funktioniert dies nicht für sie, wenn eine elfte Person versucht, Ihre Website zu durchsuchen .
PDO verwaltet die Persistenz nicht. Der MySQL-Treiber tut dies. Verbindungen werden wiederverwendet, wenn a) sie verfügbar sind und Host / Benutzer / Kennwort / Datenbank übereinstimmen. Wenn sich etwas ändert, wird eine Verbindung nicht wiederverwendet. Der beste Nettoeffekt ist, dass diese Verbindungen so oft gestartet und gestoppt werden, weil Sie verschiedene Benutzer auf der Site haben und es nicht gut tut, sie dauerhaft zu machen.
Das Wichtigste, was Sie über dauerhafte Verbindungen wissen sollten, ist, dass Sie sie in den meisten Webanwendungen NICHT verwenden sollten. Sie klingen verlockend, sind aber gefährlich und ziemlich nutzlos.
Ich bin sicher, dass es andere Threads gibt, aber eine dauerhafte Verbindung ist gefährlich, da sie zwischen Anforderungen bestehen bleibt. Wenn Sie beispielsweise eine Tabelle während einer Anforderung sperren und dann nicht entsperren können, bleibt diese Tabelle auf unbestimmte Zeit gesperrt. Permanente Verbindungen sind für 99% Ihrer Apps praktisch nutzlos, da Sie nicht wissen können, ob dieselbe Verbindung zwischen verschiedenen Anforderungen verwendet wird. Jeder Web-Thread verfügt über einen eigenen Satz dauerhafter Verbindungen, und Sie können nicht steuern, welcher Thread welche Anforderungen verarbeitet.
Die prozedurale MySQL-Bibliothek von PHP verfügt über eine Funktion, mit der nachfolgende Aufrufe von MySQL_connect denselben Link zurückgeben, anstatt eine andere Verbindung zu öffnen (wie zu erwarten). Dies hat nichts mit dauerhaften Verbindungen zu tun und ist spezifisch für die MySQL-Bibliothek. PDO zeigt kein solches Verhalten
Ressourcenlink: Link
Im Allgemeinen können Sie dies als groben "Regelsatz" verwenden ::
JA , verwenden Sie dauerhafte Verbindungen, wenn:
Die Datenbank wird auf einem anderen Server ausgeführt, auf den Sie über das Netzwerk zugreifen
Eine (eine) Anwendung greift sehr oft auf die Datenbank zu
NEIN , verwenden Sie keine dauerhaften Verbindungen, wenn:
Ihre Anwendung muss nur 100 Mal pro Stunde auf die Datenbank zugreifen.
Sie haben viele, viele Webserver, die auf einen Datenbankserver zugreifen
Die Verwendung dauerhafter Verbindungen ist erheblich schneller, insbesondere wenn Sie über ein Netzwerk auf die Datenbank zugreifen. Es macht keinen großen Unterschied, ob die Datenbank auf demselben Computer ausgeführt wird, aber sie ist immer noch etwas schneller. Wie der Name schon sagt, bleibt die Verbindung jedoch bestehen, dh sie bleibt offen, auch wenn sie nicht verwendet wird.
Das Problem dabei ist, dass MySQL in der "Standardkonfiguration" nur 1000 parallele "offene Kanäle" zulässt. Danach werden neue Verbindungen abgelehnt (Sie können diese Einstellung anpassen). Wenn Sie also beispielsweise 20 Webserver mit jeweils 100 Clients haben und jeder von ihnen nur einen Seitenzugriff pro Stunde hat, zeigt Ihnen eine einfache Mathematik, dass Sie 2000 parallele Verbindungen zur Datenbank benötigen. Das wird nicht funktionieren.
Ergo: Verwenden Sie es nur für Anwendungen mit vielen Anfragen.
quelle
Bei meinen Tests hatte ich eine Verbindungszeit von mehr als einer Sekunde zu meinem lokalen Host, daher wurde davon ausgegangen, dass ich eine dauerhafte Verbindung verwenden sollte. Weitere Tests zeigten, dass es sich um ein Problem mit 'localhost' handelt:
Testergebnisse in Sekunden (gemessen durch PHP-Mikrozeit):
Interessanterweise: Der folgende Code ist genauso schnell wie die Verwendung von 127.0.0.1:
quelle
localhost
verwendet Socket-Verbindung, Socket-Verbindung ist bekannt dafür, dass sie bei einer großen Anzahl von Verbindungen schlecht istDauerhafte Verbindungen sollten eine beträchtliche Leistungssteigerung bewirken. Ich bin nicht einverstanden mit der Behauptung, dass Sie Beharrlichkeit "vermeiden" sollten.
Es hört sich so an, als würden die oben genannten Beschwerden von jemandem verursacht, der MyIASM-Tabellen verwendet und seine eigenen Transaktionsversionen hackt, indem er sich Tabellensperren schnappt. Natürlich werden Sie zum Stillstand kommen! Verwenden Sie beginTransaction () von PDO und verschieben Sie Ihre Tabellen in InnoDB.
quelle
Eine dauerhafte Verbindung scheint mir mehr Systemressourcen zu verbrauchen. Vielleicht eine unbedeutende Menge, aber immer noch ...
quelle
Die Erklärung für die Verwendung dauerhafter Verbindungen ist offensichtlich die Reduzierung der Anzahl der Verbindungen, die ziemlich kostspielig sind, obwohl sie mit MySQL im Vergleich zu anderen Datenbanken erheblich schneller sind.
Das allererste Problem mit dauerhaften Verbindungen ...
Wenn Sie Tausende von Verbindungen pro Sekunde erstellen, stellen Sie normalerweise nicht sicher, dass diese sehr lange geöffnet bleiben, das Betriebssystem jedoch. Basierend auf dem TCP / IP-Protokoll können Ports nicht sofort recycelt werden und müssen auch eine Weile in die Phase „FIN“ investieren, bevor sie möglicherweise recycelt werden.
Das zweite Problem ... mit vielen MySQL-Serververbindungen.
Viele Leute wissen einfach nicht, dass Sie in der Lage sind, die Variable * max_connections * zu erhöhen und über 100 gleichzeitige Verbindungen mit MySQL zu erhalten. Andere wurden von älteren Linux-Problemen geschlagen, weil sie nicht mehr als 1024 Verbindungen mit MySQL übertragen konnten.
Ermöglicht jetzt die Diskussion darüber, warum dauerhafte Verbindungen in der mysqli-Erweiterung deaktiviert wurden. Trotz der Tatsache, dass Sie dauerhafte Verbindungen missbrauchen und eine schlechte Leistung erzielen können, war dies nicht der Hauptgrund. Der eigentliche Grund ist - Sie können viel mehr Probleme damit bekommen.
In MySQL 3.22 / 3.23 wurden dauerhafte Verbindungen in PHP hergestellt, wenn MySQL nicht so schwierig war, was bedeutet, dass Sie Verbindungen problemlos recyceln konnten. In späteren Versionen kam es jedoch zu einer Reihe von Problemen. - Wenn Sie eine Verbindung mit nicht festgeschriebenen Transaktionen recyceln, treten Probleme auf. Wenn Sie Verbindungen mit benutzerdefinierten Zeichensatzkonfigurationen recyceln, sind Sie erneut in Gefahr und möglicherweise pro Sitzung transformierte Variablen.
Ein Problem bei der Verwendung dauerhafter Verbindungen ist, dass sie nicht wirklich so gut skaliert werden können. Für diejenigen, die 5000 Personen verbunden haben, benötigen Sie 5000 dauerhafte Verbindungen. Um das Erfordernis der Persistenz zu beseitigen, haben Sie möglicherweise die Möglichkeit, 10000 Personen mit einer ähnlichen Anzahl von Verbindungen zu bedienen, da sie in der Lage sind, einzelne Verbindungen zu teilen, wenn sie nicht mit ihnen verbunden sind.
quelle
Ich habe mich nur gefragt, ob eine Teillösung darin bestehen würde, einen Pool von einmaligen Verbindungen zu haben. Sie können Zeit damit verbringen, einen Verbindungspool zu erstellen, wenn das System bis zu einem gewissen Grad nur wenig ausgelastet ist, diese zu verteilen und zu beenden, wenn sie entweder abgeschlossen sind oder eine Zeitüberschreitung aufweisen. Im Hintergrund erstellen Sie neue Verbindungen, während sie aufgenommen werden. Im schlimmsten Fall sollte dies nur so langsam sein wie das Herstellen der Verbindung ohne den Pool, vorausgesetzt, dass das Herstellen der Verbindung der begrenzende Faktor ist?
quelle