Nimmer Ärger mit den Persistenten Verbindungen von MySQL? (Teil 2/2)
Was bislang geschah: Persistente Verbindungen sind ein berühmt-berüchtigtes Mittel zur Beschleunigung von Datenbankverbindungen. In PHP 5.3 führt MySQL Persistente Verbindungen in ext/mysqli ein. ext/mysql und PDO unterstützen sie bereits lange, doch mysqli zieht erst jetzt nach. Der Nachzügler verwendet eine andere Strategie beim Pooling und behauptet sicherer zu sein.
Der Rausch der Geschwindigkeit zu Lasten der Sicherheit?
Persistente Verbindung bergen nicht nur das Risiko einer Überlastung des Webservers durch eine Fehlkonfiguration. Es gibt weitere Nebenwirkungen, weil eine Persistente Verbindung von verschiedenen PHP-Anwendungen nacheinander benutzt.
Harry denkt an seine letzte Zugfahrt. “Bitte verlassen Sie diesen Raum so, wie Sie ihn vorfinden möchten”. Besteht keine Übereinkunft zwischen den Benutzern einer gemeinsamen Ressource über die Nutzung und Pflege derselben, sind Überraschungen vorprogrammiert. Negative Erfahrungen sind nicht immer dem Vorbenutzer anzulasten. Wie könnte ein verstorbener Vorbenutzer, ein ungewollt beendetes PHP-Skript, die geteilte Ressource aufräumen?
Die Kritik am Fehlen einer automatischen Bereinigung einer Persistenten Verbindung der PHP-Erweiterung ext/mysql hat dazu geführt, daß der Nachfolger, die PHP-Erweiterung ext/mysqli (“i” für “improved”), zunächst keine Persistenten Verbindungen erlaubte. Zu viele PHP-Anwender waren sich der Nebenwirkungen nicht bewusst. Persistente Verbindungen erhielten einen negativen Ruf. Entsprechend bot ext/mysqli bis zur PHP Version 5.3 keine Persistenten Verbindungen an.
Die neuerliche Umsetzung in ext/mysqli unterscheidet sich von derjenigen in ext/mysql. Die neue Implementierung legt mehr Wert auf Komfort und Sicherheit. Persistente Verbindungen von ext/mysqli werden automatisch bereinigt, bevor sie wiederverwendet werden.
Der “Reinigungsplan” für Persistente Verbindungen fällt je nach Datenbanksystem unterschiedlich lang aus. Im Falle von MySQL schreibt der Plan folgende Arbeiten vor:
- ROLLBACK aller offenen Transaktionen
- Freigabe alle temporären Tabellen
- Freigabe aller Tabellensperren
- Freigabe aller Sperren, die mit GET_LOCK() eingerichtet wurden
- Rücksetzung aller Session-Variablen auf die globalen Standardwerte
- Freigabe aller Prepared Statements
- Schließen aller HANDLER
Bei Verwendung der Persistenten Verbindungen von ext/mysql wird keine der aufgelisteten Aktionen automatisch ausgeführt. Erhält ein PHP-Skript eine wiederverwendete Verbindung, so muß es damit rechnen, daß eine offene Transaktion vorliegt. Dies ist leicht innerhalb der Applikation zu lösen. Weitaus schwieriger ist es Tabellensperren zu erkennen, die nicht freigegeben wurden, bevor eine persistente Verbindung wiederverwendet wird.
Mit PHP 5.3 sind diese Probleme Vergangenheit, sofern ext/mysqli eingesetzt wird. Das “Flaggschiff” der PHP-MySQL-Erweiterungen für das Kommando COM_CHANGE_USER aus dem MySQL Client-Server Protokoll aus, bevor eine wiederverwendete Persistente Verbindung an eine PHP-Anwendung übergeben wird. COM_CHANGE_USER führt alle obigen “Reinigungsarbeiten” durch. Es versetzt die Verbindung in einen Zustand als sei sie neu eröffnet worden.
Alle Nebenwirkungen sind behoben. Wirklich alle, da COM_CHANGE_USER den Datenbankbenutzer neu authentifiziert und seine Autorisierung überprüft. Rechteänderungen werden von der Persistenten Verbindung erkannt.
Sicherheit drückt aufs Tempo
Soviel Komfort und Sicherheit haben ihren Preis. Aufräumen kostet ist. COM_CHANGE_USER, mysqli_change_user(), ist ein vergleichsweise langsames Kommando. Die zu Beginn des Artikels präsentierten Benchmark-Skripte werden um den Faktor 2-3 verlangsamt. Das “SELECT 1”-Beispiel erreicht ohne Persistente Verbindung 1522 Schleifendurchläufe. Mit Persistenten Verbindungen im Stile von ext/mysql steigt der Wert auf 11056. Beim Einsatz von sicheren Persistenten Verbindungen im Stile von ext/mysqli sinkt er jedoch auf 3584 Schleifendurchläufe. Wie groß die Auswirkungen auf reale Applikationen sind, muss die Praxis zeigen.
Wer seit Jahren erfolgreich die Persistenten Verbindungen von ext/mysql verwendet und diese mit all ihren Nebenwirkungen auch in ext/mysqli nutzen möchte, der sollte PHP mit -DMYSQLI_NO_CHANGE_USER_ON_PCONNECT kompilieren.
Fazit
Die mit PHP 5.3 in ext/mysqli eingeführten Persistenten Verbindungen sind komfortabler und sicherer als ihre Pendants in ext/mysql. Einfache Benchmarks lassen Performanzverluste erwarten. Die im Artikel gezeigten Benchmarks nähern sich dem “Worst-Case” an. Aufgrund der extrem einfachen Anfrage übt der Verbindungsoverhead einen großen Einfluss auf die Gesamtlaufzeit aus. Unter diesen wenig praxisrelevanten Vorraussetzungen zeigen sich Persistente Verbindungen von ext/mysqli etwa doppelt so schnell wie normale Verbindungen, wenngleich gegenüber ext/mysql ein Performanzeinbruch um den Faktor drei zu verzeichnen ist.
Da keine realitätsnahen Benchmarks vorliegen sind alle Werte mit größter Vorsicht zu interpretieren. Rückmeldung aus der Praxis ist notwendig, um zu entscheiden ob die in der Beta-Version von PHP 5.3 gewählte Implementierung auf ein positives Echo trifft. Nichts ist in Stein gemeißelt. Schon dar nicht ein -DMYSQLI_NO_CHANGE_USER_ON_PCONNECT für den Compiler.
PS: Auch Neu in PHP 5.3 – mysqlnd
Die PHP-Erweiterung ext/mysqli ist das “Flaggschiff” der kleinen Flotte von PHP-MySQL-Erweiterungen zu der weiterhin ext/mysql und PDO_MYSQL gehören. Das Flaggschiff beherrscht alle Manöver der kleineren Schwesterschiffe und kann als einziges den vollen Funktionsumfang der MySQL Datenbank ansprechen.
Alle drei Erweiterungen können in PHP 5.3 entweder den MySQL native driver for PHP (mysqlnd) oder die MySQL Client Library (libmysql) verwenden, um mit der MySQL Datenbank zu kommunizieren. Die Verwendung der einen oder anderen C-Blibliothek ist transparent für den PHP-Programmierer. Egal welche C-Bibliothek zum Einsatz kommt, bestehende PHP-MySQL-Anwendungen funktionieren wie gewohnt. Die einzige Einschränkung ist, daß mysqlnd einen MySQL Server der Version 5.0 oder neuer voraussetzt, da MySQL ältere Versionen nicht mehr unterstützt. Wer sich trotzdem für mysqlnd entscheidet, darf auf eine mindestens gleichwertige Performanz und potentielle Speichereinsparungen hoffen. Bestes Beispiel sind die obigen Benchmarks.
Mehr hierzu in der Präsentation und im PHP-Handbuch.
Dort finden sich auch ein paar Hinweise auf die neuen mysqlnd-Statistiken, mit vielversprechenden Feldern wie “connect_success”, “connect_failure”, “connection_reused ”, “reconnect “, “pconnect_success “ und, und, und. Johannes testet auf seiner Website eine PHP-Erweiterung, welche die Daten über mehrere PHP-Aufrufe hinweg aggregiert: http://schlueters.de/~johannes/mysqlnd_stat.php
Klingt ja echt nicht verkehrt, aber wann wird denn PHP 5.3 endlich kommen? So viele schöne Neuerungen, aber „kein“ Release in Sicht.
Wenn ich das gefühl habe, dass es genug getestet ist -> http://snaps.php.net bzw. htp://windows.php.net/snaps
Und nein, ne genauere Aussage gibt es nicht 🙂
Dann werde ich wohl am WE mal ein wenig mittesten. Solltet ihr auch alle machen 😉
Also dass ich ausgerechnet in einem Programmier-Blog das schlimme (Amateur-Journalisten-)Wort „vorprogrammiert“ lesen muss! *staun*
Ansonsten schau ich absolut gern hier rein, wenn ich auch manchem nicht ganz folgen kann. Naja, in einem Jahr vielleicht.. Ich lerne..
Gruß
Annie
PS. Warum wird meine echte E-Mail-Adresse „vorname.nachname@web.de“ hier nicht akzeptiert?