Datenbankoperationen sind heutzutage häufig der größte Engpass für die meisten Webanwendungen. Nicht nur die DBAs (Datenbankadministratoren) müssen sich um diese Leistungsprobleme kümmern. Wir als Programmierer müssen unseren Teil dazu beitragen, Tabellen richtig zu strukturieren, optimierte Abfragen und besseren Code zu schreiben. In diesem Artikel werde ich einige MySQL-Optimierungstechniken für Programmierer auflisten.
Bevor Sie beginnen, sollten Sie wissen, dass Sie auf Envato Market viele nützliche MySQL-Skripts und -Dienstprogramme finden.
MySQL-Skripte und Dienstprogramme auf dem Envato-MarktBei den meisten MySQL-Servern ist die Abfragezwischenspeicherung aktiviert. Dies ist eine der effektivsten Methoden zur Verbesserung der Leistung, die von der Datenbank-Engine leise behandelt wird. Wenn dieselbe Abfrage mehrmals ausgeführt wird, wird das Ergebnis sehr schnell aus dem Cache abgerufen.
Das Hauptproblem ist, dass es so einfach und für den Programmierer verborgen ist, dass die meisten von uns es ignorieren. Einige Dinge können tatsächlich verhindern, dass der Abfrage-Cache seine Aufgabe ausführt.
// Abfrage-Cache funktioniert NICHT $ r = mysql_query ("SELECT Benutzername FROM Benutzer WHERE Signup_date> = CURDATE ()"); // Abfragecache funktioniert! $ today = Datum ("Y-m-d"); $ r = mysql_query ("SELECT username FROM Benutzer WHERE signup_date> = '$ today'"));
Der Grund für den Abfragecache in der ersten Zeile ist die Verwendung der CURDATE () - Funktion. Dies gilt für alle nicht deterministischen Funktionen wie NOW () und RAND () usw. Da sich das Ergebnis der Funktion ändern kann, beschließt MySQL, das Abfrage-Caching für diese Abfrage zu deaktivieren. Alles, was wir tun mussten, war, vor der Abfrage eine zusätzliche PHP-Zeile hinzuzufügen, um dies zu verhindern.
Die Verwendung des EXPLAIN-Schlüsselworts gibt Ihnen Aufschluss darüber, was MySQL zur Ausführung Ihrer Abfrage tut. Auf diese Weise können Sie Engpässe und andere Probleme mit Ihrer Abfrage- oder Tabellenstruktur erkennen.
Die Ergebnisse einer EXPLAIN-Abfrage zeigen Ihnen, welche Indizes verwendet werden, wie die Tabelle durchsucht und sortiert wird usw.
Nehmen Sie eine SELECT-Abfrage (vorzugsweise eine komplexe, mit Verknüpfungen) und fügen Sie das Schlüsselwort EXPLAIN davor hinzu. Sie können dazu einfach phpmyadmin verwenden. Es zeigt Ihnen die Ergebnisse in einer schönen Tabelle. Angenommen, ich habe vergessen, einer Spalte einen Index hinzuzufügen, in dem ich Verknüpfungen durchführe:
Nachdem Sie den Index dem Feld group_id hinzugefügt haben:
Anstatt 7883 Zeilen zu scannen, werden nur 9 und 16 Zeilen aus den beiden Tabellen gescannt. Eine gute Faustregel besteht darin, alle Zahlen in der Spalte "Zeilen" zu multiplizieren, und die Abfrageleistung ist etwas proportional zur resultierenden Zahl.
Manchmal, wenn Sie Ihre Tabellen abfragen, wissen Sie bereits, dass Sie nur eine Zeile suchen. Möglicherweise holen Sie einen eindeutigen Datensatz ab oder prüfen nur, ob eine beliebige Anzahl von Datensätzen vorhanden ist, die Ihre WHERE-Klausel erfüllen.
In solchen Fällen kann das Hinzufügen von LIMIT 1 zu Ihrer Abfrage die Leistung verbessern. Auf diese Weise stoppt das Datenbankmodul die Suche nach Datensätzen, nachdem es nur 1 gefunden hat, anstatt die gesamte Tabelle oder den gesamten Index durchzugehen.
// habe ich irgendwelche Nutzer aus Alabama? // Was NICHT zu tun ist: $ r = mysql_query ("SELECT * FROM user WHERE state = 'Alabama'"); if (mysql_num_rows ($ r)> 0) //… // viel besser: $ r = mysql_query ("SELECT 1 FROM Benutzer WHERE state = 'Alabama' LIMIT 1"); if (mysql_num_rows ($ r)> 0) //…
Indizes beziehen sich nicht nur auf die Primärschlüssel oder die eindeutigen Schlüssel. Wenn in Ihrer Tabelle Spalten enthalten sind, nach denen Sie suchen, sollten Sie sie fast immer indizieren.
Wie Sie sehen, gilt diese Regel auch für eine Teilstringsuche wie "last_name LIKE 'a%" ". Bei der Suche am Anfang des Strings kann MySQL den Index für diese Spalte verwenden.
Sie sollten auch wissen, welche Sucharten die regulären Indizes nicht verwenden können. Wenn Sie beispielsweise nach einem Wort suchen (z. B. "WHERE post_content LIKE '% apple%'")), werden Sie keinen Nutzen aus einem normalen Index erkennen. Mit der mysql-Volltextsuche oder der Erstellung einer eigenen Indizierungslösung können Sie sich besser fühlen.
Wenn Ihre Anwendung viele JOIN-Abfragen enthält, müssen Sie sicherstellen, dass die Spalten, denen Sie beitreten, für beide Tabellen indiziert sind. Dies beeinflusst, wie MySQL den Join-Vorgang intern optimiert.
Außerdem müssen die zusammengefügten Spalten vom selben Typ sein. Wenn Sie beispielsweise eine DECIMAL-Spalte mit einer INT-Spalte aus einer anderen Tabelle verbinden, kann MySQL nicht mindestens einen der Indizes verwenden. Sogar die Zeichenkodierung muss für Zeichenfolgenspalten derselbe Typ sein.
// Suche nach Unternehmen in meinem Bundesland $ r = mysql_query ("SELECT company_name FROM Benutzer LEFT JOIN Unternehmen ON (users.state = companies.state) WHERE users.id = $ user_id"); // Beide Statusspalten sollten indiziert werden // und beide sollten denselben Typ und dieselbe Zeichencodierung haben // oder MySQL führt vollständige Tabellenscans durch
Dies ist einer dieser Tricks, die auf den ersten Blick cool klingen, und viele Neulinge-Programmierer fallen in diese Falle. Sie können nicht erkennen, welche Art von schrecklichen Engpässen Sie erstellen können, wenn Sie dies in Ihren Abfragen verwenden.
Wenn Sie wirklich zufällige Zeilen aus Ihren Ergebnissen benötigen, gibt es viel bessere Möglichkeiten, dies zu tun. Zugegeben, es wird zusätzlicher Code benötigt, aber Sie verhindern einen Engpass, der sich mit zunehmenden Daten exponentiell verschlimmert. Das Problem ist, dass MySQL für jede einzelne Zeile in der Tabelle eine RAND () - Operation durchführen muss (was Rechenleistung erfordert), bevor sie sortiert und nur eine Zeile angezeigt wird.
// was NICHT zu tun ist: $ r = mysql_query ("SELECT username FROM user ORDER BY RAND () LIMIT 1"); // viel besser: $ r = mysql_query ("SELECT count (*) FROM user"); $ d = mysql_fetch_row ($ r); $ rand = mt_rand (0, $ d [0] - 1); $ r = mysql_query ("SELECT Benutzername FROM Benutzer LIMIT $ rand, 1");
Sie wählen also eine Zufallszahl, die kleiner als die Anzahl der Ergebnisse ist, und verwenden diese als Offset in Ihrer LIMIT-Klausel.
Je mehr Daten aus den Tabellen gelesen werden, desto langsamer wird die Abfrage. Dadurch wird die Zeit für die Festplattenvorgänge erhöht. Wenn der Datenbankserver vom Webserver getrennt ist, werden längere Netzwerkverzögerungen auftreten, da die Daten zwischen den Servern übertragen werden müssen.
Es ist eine gute Angewohnheit, immer anzugeben, welche Spalten Sie benötigen, wenn Sie Ihre SELECT-Anweisungen ausführen.
// nicht bevorzugt $ r = mysql_query ("SELECT * FROM user WHERE user_id = 1"); $ d = mysql_fetch_assoc ($ r); echo "Willkommen $ d ['username']"; // besser: $ r = mysql_query ("SELECT Benutzername FROM Benutzer WHERE User_id = 1"); $ d = mysql_fetch_assoc ($ r); echo "Willkommen $ d ['username']"; // Die Unterschiede sind mit größeren Ergebnissätzen signifikanter
In jeder Tabelle gibt es eine ID-Spalte, die aus PRIMARY KEY, AUTO_INCREMENT und einer der Varianten von INT besteht. Vorzugsweise auch UNSIGNED, da der Wert nicht negativ sein kann.
Auch wenn Sie eine Benutzertabelle mit einem eindeutigen Benutzernamenfeld haben, machen Sie das nicht zu Ihrem Primärschlüssel. VARCHAR-Felder als Primärschlüssel sind langsamer. Und Sie werden eine bessere Struktur in Ihrem Code haben, indem Sie sich auf alle Benutzer mit ihrer ID beziehen.
Hinter den Kulissen gibt es auch Operationen, die von der MySQL-Engine selbst ausgeführt werden, die das Primärschlüsselfeld intern verwendet. Was umso wichtiger wird, je komplizierter die Datenbankeinrichtung ist. (Cluster, Partitionierung usw.).
Eine mögliche Ausnahme von der Regel sind die "Assoziationstabellen", die für die Many-to-Many-Art von Assoziationen zwischen 2 Tabellen verwendet werden. Zum Beispiel eine Tabelle "posts_tags", die zwei Spalten enthält: post_id, tag_id, die für die Beziehungen zwischen zwei Tabellen mit den Namen "post" und "tags" verwendet wird. Diese Tabellen können einen Primärschlüssel haben, der beide ID-Felder enthält.
ENUM-Säulen sind sehr schnell und kompakt. Intern werden sie wie TINYINT gespeichert, sie können jedoch Stringwerte enthalten und anzeigen. Dies macht sie zu einem perfekten Kandidaten für bestimmte Bereiche.
Wenn Sie ein Feld haben, das nur einige unterschiedliche Werte enthält, verwenden Sie ENUM anstelle von VARCHAR. Beispielsweise könnte es sich um eine Spalte mit dem Namen "status" handeln, die nur Werte wie "aktiv", "inaktiv", "ausstehend", "abgelaufen" usw. enthält.
Es gibt sogar eine Möglichkeit, einen "Vorschlag" von MySQL selbst zu erhalten, wie Sie Ihre Tabelle umstrukturieren können. Wenn Sie ein VARCHAR-Feld haben, kann es tatsächlich vorschlagen, dass Sie diesen Spaltentyp stattdessen in ENUM ändern. Dies geschieht mit dem Aufruf PROCEDURE ANALYZE (). Was bringt uns zu:
PROCEDURE ANALYZE () lässt MySQL die Spaltenstrukturen und die tatsächlichen Daten in Ihrer Tabelle analysieren, um bestimmte Vorschläge für Sie zu erhalten. Dies ist nur nützlich, wenn in Ihren Tabellen tatsächliche Daten vorhanden sind, da dies eine wichtige Rolle bei der Entscheidungsfindung spielt.
Wenn Sie z. B. ein INT-Feld für Ihren Primärschlüssel erstellt haben, jedoch nicht zu viele Zeilen enthalten, empfiehlt es sich möglicherweise, stattdessen einen MEDIUMINT zu verwenden. Wenn Sie ein VARCHAR-Feld verwenden, erhalten Sie möglicherweise einen Vorschlag, dieses in ENUM zu konvertieren, wenn nur wenige eindeutige Werte vorhanden sind.
Sie können dies auch ausführen, indem Sie in phpmyadmin in einer Ihrer Tabellensichten auf den Link "Tabellenstruktur vorschlagen" klicken.
Denken Sie daran, dass dies nur Vorschläge sind. Und wenn Ihr Tisch größer wird, sind Sie vielleicht nicht einmal die richtigen Vorschläge. Die Entscheidung liegt letztlich bei Ihnen.
Wenn Sie keinen ganz bestimmten Grund für die Verwendung eines NULL-Werts haben, sollten Sie Ihre Spalten immer auf NOT NULL setzen.
Fragen Sie sich zunächst, ob es einen Unterschied gibt zwischen einem leeren String-Wert und einem NULL-Wert (für INT-Felder: 0 vs. NULL). Wenn es keinen Grund gibt, beides zu haben, benötigen Sie kein NULL-Feld. (Wussten Sie, dass Oracle NULL und leere Zeichenfolge als gleich betrachtet?)
NULL-Spalten erfordern zusätzlichen Speicherplatz und können Ihre Vergleichsanweisungen komplexer machen. Vermeiden Sie sie einfach, wenn Sie können. Ich verstehe jedoch, dass einige Leute ganz bestimmte Gründe haben können, NULL-Werte zu haben, was nicht immer eine schlechte Sache ist.
Aus MySQL-Dokumenten:
"NULL-Spalten benötigen zusätzlichen Speicherplatz in der Zeile, um aufzuzeichnen, ob ihre Werte NULL sind. Für MyISAM-Tabellen benötigt jede NULL-Spalte ein Bit, das auf das nächste Byte aufgerundet wird."
Die Verwendung vorbereiteter Anweisungen bietet sowohl aus Leistungs- als auch aus Sicherheitsgründen mehrere Vorteile.
Prepared Statements filtert die Variablen, die Sie standardmäßig an sie binden, so dass Ihre Anwendung vor SQL-Injection-Angriffen geschützt werden kann. Sie können Ihre Variablen natürlich auch manuell filtern, aber diese Methoden sind anfälliger für menschliche Fehler und Vergesslichkeit durch den Programmierer. Dies ist weniger ein Problem, wenn ein Framework oder ORM verwendet wird.
Da wir uns auf Leistung konzentrieren, sollte ich auch die Vorteile in diesem Bereich erwähnen. Diese Vorteile sind bedeutender, wenn dieselbe Abfrage mehrmals in Ihrer Anwendung verwendet wird. Sie können der gleichen vorbereiteten Anweisung unterschiedliche Werte zuweisen, MySQL muss sie jedoch nur einmal analysieren.
Auch die neuesten Versionen von MySQL übertragen vorbereitete Anweisungen in einer nativen binären Form, die effizienter sind und auch dazu beitragen, Netzwerkverzögerungen zu reduzieren.
Es gab eine Zeit, in der viele Programmierer aus einem wichtigen Grund vorsichtige Aussagen absichtlich vermieden haben. Sie wurden nicht vom MySQL-Abfrage-Cache zwischengespeichert. Seit der Version 5.1 wird jedoch auch das Query-Caching unterstützt.
Um vorbereitete Anweisungen in PHP zu verwenden, checken Sie die mysqli -Erweiterung aus oder verwenden eine Datenbank-Abstraktionsschicht wie PDO.
// Eine vorbereitete Anweisung erstellen, wenn ($ stmt = $ mysqli-> prepare ("SELECT Benutzername VON Benutzer WHERE state =?")) // Bindeparameter $ stmt-> bind_param ("s", $ state); // Ausführen von $ stmt-> execute (); // Ergebnisvariablen binden $ stmt-> bind_result ($ username); // Wert abrufen $ stmt-> fetch (); printf ("% s stammt von% s \ n", $ username, $ state); $ stmt-> close ();
Wenn Sie eine Abfrage aus einem Skript ausführen, wird normalerweise gewartet, bis die Ausführung der Abfrage abgeschlossen ist, bevor sie fortgesetzt werden kann. Sie können dies ändern, indem Sie ungepufferte Abfragen verwenden.
In den PHP-Dokumenten gibt es eine großartige Erklärung für die Funktion mysql_unbuffered_query ():
"mysql_unbuffered_query () sendet die SQL-Abfrage an MySQL, ohne die Ergebniszeilen automatisch abzurufen und zwischenzuspeichern, wie dies bei mysql_query () der Fall ist. Dies spart beträchtlichen Speicherplatz bei SQL-Abfragen, die große Ergebnismengen erzeugen, und Sie können mit der Ergebnismenge arbeiten unmittelbar nachdem die erste Zeile abgerufen wurde, da Sie nicht warten müssen, bis die vollständige SQL-Abfrage ausgeführt wurde. "
Es gibt jedoch einige Einschränkungen. Sie müssen entweder alle Zeilen lesen oder mysql_free_result () aufrufen, bevor Sie eine weitere Abfrage ausführen können. Sie dürfen auch keine mysql_num_rows () oder mysql_data_seek () für die Ergebnismenge verwenden.
Viele Programmierer erstellen ein VARCHAR (15) -Feld, ohne zu wissen, dass sie IP-Adressen tatsächlich als Ganzzahlwerte speichern können. Mit einem INT gehen Sie auf nur 4 Byte Speicherplatz zurück und haben stattdessen ein Feld mit fester Größe.
Sie müssen sicherstellen, dass Ihre Spalte ein UNSIGNED INT ist, da IP-Adressen den gesamten Bereich einer 32-Bit-Ganzzahl ohne Vorzeichen verwenden.
In Ihren Abfragen können Sie INET_ATON () zum Konvertieren von und IP in eine Ganzzahl und INET_NTOA () für umgekehrt verwenden. Es gibt auch ähnliche Funktionen in PHP namens ip2long () und long2ip ()..
$ r = "UPDATE Benutzer SET ip = INET_ATON ('$ _ SERVER [' REMOTE_ADDR ']') WHERE user_id = $ user_id";
Wenn jede einzelne Spalte in einer Tabelle "feste Länge" ist, wird die Tabelle auch als "statisch" oder "feste Länge" betrachtet. Beispiele für Spaltentypen, die NICHT mit fester Länge sind, sind: VARCHAR, TEXT, BLOB. Wenn Sie nur eine dieser Spaltenarten angeben, hat die Tabelle keine feste Länge mehr und muss von der MySQL-Engine anders behandelt werden.
Tabellen mit fester Länge können die Leistung verbessern, da die MySQL-Engine die Datensätze schneller durchsuchen kann. Wenn eine bestimmte Zeile in einer Tabelle gelesen werden soll, kann sie die Position der Tabelle schnell berechnen. Wenn die Zeilengröße nicht festgelegt ist, muss bei jeder Suche der Primärschlüsselindex abgefragt werden.
Sie sind auch einfacher zwischenzuspeichern und nach einem Absturz leichter zu rekonstruieren. Sie können aber auch mehr Platz beanspruchen. Wenn Sie beispielsweise ein VARCHAR (20) -Feld in ein CHAR (20) -Feld konvertieren, benötigt es immer 20 Byte Speicherplatz, unabhängig davon, in welchem Feld es sich befindet.
Mit den Techniken der "vertikalen Partitionierung" können Sie die Spalten mit variabler Länge in einer separaten Tabelle aufteilen. Was bringt uns zu:
Vertikale Partitionierung ist der Akt der vertikalen Unterteilung Ihrer Tabellenstruktur aus Optimierungsgründen.
Beispiel 1: Möglicherweise haben Sie eine Benutzertabelle, die Heimatadressen enthält, die nicht oft gelesen werden. Sie können Ihre Tabelle aufteilen und die Adressinformationen in einer separaten Tabelle speichern. Auf diese Weise wird Ihre Hauptbenutzertabelle verkleinert. Wie Sie wissen, sind kleinere Tische schneller.
Beispiel 2: Sie haben ein Feld "last_login" in Ihrer Tabelle. Sie wird jedes Mal aktualisiert, wenn sich ein Benutzer bei der Website anmeldet. Bei jeder Aktualisierung einer Tabelle wird jedoch der Abfrage-Cache für diese Tabelle geleert. Sie können dieses Feld in eine andere Tabelle einfügen, um die Aktualisierungen Ihrer Benutzertabelle auf ein Minimum zu beschränken.
Sie müssen jedoch auch sicherstellen, dass Sie diese beiden Tabellen nach der Partitionierung nicht ständig verknüpfen müssen.
Wenn Sie eine große DELETE- oder INSERT-Abfrage auf einer Live-Website durchführen müssen, müssen Sie darauf achten, dass der Webverkehr nicht gestört wird. Wenn eine solche große Abfrage ausgeführt wird, kann dies Ihre Tabellen sperren und Ihre Webanwendung zum Stillstand bringen.
Apache führt viele parallele Prozesse / Threads aus. Daher funktioniert es am effizientesten, wenn die Ausführung von Skripts so schnell wie möglich abgeschlossen ist, so dass auf den Servern nicht zu viele offene Verbindungen und Prozesse vorhanden sind, die Ressourcen verbrauchen, insbesondere den Arbeitsspeicher.
Wenn Sie Ihre Tabellen für einen längeren Zeitraum (z. B. 30 Sekunden oder länger) sperren, wird auf einer Website mit hohem Datenaufkommen ein Prozess- und Abfragestapel ausgelöst. Dies kann lange dauern, um das Web zu löschen oder sogar zum Absturz zu bringen Server.
Wenn Sie über ein Wartungsskript verfügen, das eine große Anzahl von Zeilen löschen muss, verwenden Sie einfach die LIMIT-Klausel, um dies in kleineren Batches zu tun, um diese Überlastung zu vermeiden.
while (1) mysql_query ("DELETE FROM protokolliert WHERE log_date <= '2009-10-01' LIMIT 10000"); if (mysql_affected_rows() == 0) // done deleting break; // you can even pause a bit usleep(50000);
Bei Datenbank-Engines ist die Festplatte möglicherweise der größte Engpass. Kleinere und kompaktere Dinge sind normalerweise in Bezug auf die Leistung hilfreich, um den Datentransfer zu reduzieren.
MySQL-Dokumente enthalten eine Liste der Speicheranforderungen für alle Datentypen.
Wenn erwartet wird, dass eine Tabelle sehr wenige Zeilen hat, gibt es keinen Grund, aus dem Primärschlüssel einen INT zu machen, anstelle von MEDIUMINT, SMALLINT oder sogar in einigen Fällen TINYINT. Wenn Sie die Zeitkomponente nicht benötigen, verwenden Sie DATE anstelle von DATETIME.
Stellen Sie nur sicher, dass Sie einen vernünftigen Raum zum Wachsen lassen, sonst könnten Sie wie Slashdot enden.
Die zwei Hauptspeicher-Engines in MySQL sind MyISAM und InnoDB. Jeder hat seine eigenen Vor- und Nachteile.
MyISAM eignet sich gut für Anwendungen, bei denen das Lesen stark ist, aber es lässt sich nicht gut skalieren, wenn es viele Schreibvorgänge gibt. Selbst wenn Sie ein Feld einer Zeile aktualisieren, wird die gesamte Tabelle gesperrt und kein anderer Prozess kann sogar aus ihm lesen, bis diese Abfrage abgeschlossen ist. MyISAM berechnet sehr schnell SELECT COUNT (*) Abfragetypen.
InnoDB ist in der Regel eine kompliziertere Speicher-Engine und kann für die meisten kleinen Anwendungen langsamer sein als MyISAM. Es unterstützt jedoch zeilenbasiertes Sperren, was besser skaliert. Es werden auch einige erweiterte Funktionen wie Transaktionen unterstützt.
Durch die Verwendung eines ORM (Object Relational Mapper) können Sie bestimmte Leistungsvorteile erzielen. Alles, was ein ORM leisten kann, kann auch manuell codiert werden. Dies kann jedoch zu viel zusätzliche Arbeit bedeuten und ein hohes Maß an Fachwissen erfordern.
ORMs eignen sich hervorragend für "Lazy Loading". Das bedeutet, dass sie Werte nur dann abrufen können, wenn sie benötigt werden. Sie müssen jedoch vorsichtig mit ihnen sein, oder Sie können am Ende viele Mini-Abfragen erstellen, die die Leistung reduzieren können.
ORMs können Ihre Abfragen auch in Transaktionen stapeln, die viel schneller arbeiten als das Senden einzelner Abfragen an die Datenbank.
Derzeit ist mein Lieblings-ORM für PHP Doctrine. Ich habe einen Artikel über die Installation von Doctrine mit CodeIgniter geschrieben.
Persistente Verbindungen sollen den Aufwand für das Wiederherstellen von Verbindungen zu MySQL reduzieren. Wenn eine dauerhafte Verbindung erstellt wird, bleibt sie auch nach der Ausführung des Skripts geöffnet. Da Apache seine untergeordneten Prozesse wiederverwendet, wird beim nächsten Ausführen des Prozesses für ein neues Skript dieselbe MySQL-Verbindung wiederverwendet.
Das klingt großartig in der Theorie. Aber aus meiner persönlichen Erfahrung (und vielen anderen) erweist sich diese Funktion als die Mühe nicht wert. Sie können ernsthafte Probleme mit Verbindungsbeschränkungen, Speicherproblemen usw. haben.
Apache läuft extrem parallel und erstellt viele untergeordnete Prozesse. Dies ist der Hauptgrund dafür, dass permanente Verbindungen in dieser Umgebung nicht sehr gut funktionieren. Wenden Sie sich an Ihren Systemadministrator, bevor Sie die Verwendung der Funktion mysql_pconnect () in Betracht ziehen.