Kürzlich (ich weiß nicht mal genau, was ich gemacht habe) hat meine WordPress-Installation plötzlich nicht mehr funktioniert. Es kam beim Laden der Seite nur noch eine leere Antwort, die der Browser als weiße Seite darstellte. Nach einer Recherche im Error-Log von Apache stellte sich heraus, dass das Speicherlimit von PHP überschritten wurde.
Bei der Nutzung von ISPConfig findet man das Log hier:
/var/log/ispconfig/httpd/[Name der Seite]/error.log
Das äußert sich dann beispielsweise so:
Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 652360 bytes) in [...]
Um das zu beheben, kann man PHP mehr Speicher zuweisen. Also ändert man in der php.ini die entsprechende Konfigurationsvariable. Nutzt man PHP über fast-cgi, dann befindet sich die Datei hier:
/etc/php5/cgi/php.ini
Den Wert für memory_limit musste ich tatsächlich auf 256 MB ändern:
memory_limit = 256M
Das kam mir komisch vor. Und tatsächlich: Die Seite war zwar wieder erreichbar, aber unglaublich langsam. Alleine das Ausliefern der HTML-Seite (kann man bspw. über die Netzwerk-Ansicht von Firebug messen) dauerte 4 Sekunden! Das genügt meinen Performance-Ansprüchen nicht mal ansatzweise. Die Recherche hat mich jetzt einige Abende gekostet, aber ich habe herausgefunden, was die Ursache war. Ich benutze WordPress 3.6.1, da ergab eine Google-Suche keine nennenswerten Probleme. Auch die üblichen Tipps haben mir nicht weitergeholfen, jeder sollte das aber vorher ausprobieren:
- Alle Plugins deaktivieren und schrittweise wieder aktivieren
- Datenbank aufräumen (also beispielsweise alle Revisionen von Posts löschen, dafür gibt es Plugins)
- Das Standard-Theme aktivieren
Ich habe auch die Server-Einstellungen überprüft und ein frisches WordPress installiert, welches dieses Verhalten nicht zeigte. Dann habe ich sogar angefangen, den PHP-Code meiner Installation zu tracen (xdebug+webgrind, kann ich empfehlen!), aber auch das hat mich nicht weitergebracht. Schließlich kam mir die Größe des SQL-Backups meiner Datenbank verdächtig vor: satte 351 MB! Ich habe mal alle Tabellen analysiert und dabei ergab sich ein Ausreißer:
mysql> select count(*) from wp_options; +----------+ | count(*) | +----------+ | 473572 | +----------+ 1 row in set (0.00 sec)
Über 400.000 Einträge! Da kann doch was nicht stimmen! In dieser Tabelle werden alle Konfigurationen von WordPress und seinen Plugins gespeichert. Es gibt sogar die Spalte „autoload“, wenn diese auf „yes“ gesetzt ist, werden die Konfigurationsparameter im Speicher gehalten, um bei den Seitenaufrufen Zeit zu sparen. Und tatsächlich:
mysql> select count(*) from wp_options where autoload="yes"; +----------+ | count(*) | +----------+ | 158002 | +----------+
Es gibt hunderttausende Konfigurationsparameter, welche auch noch immer im Speicher gehalten werden! Und das für jeden Web-Request! Das kann nur in die Hose gehen. Folgende Konfigurationsschlüssel sind mir dabei zu abertausenden aufgefallen:
displayed_galleries_54f8cd9e661e55e3620e921b2f2892c9
Immer wieder mit anderem Hash-Wert am Ende. Diese habe ich alle gelöscht:
mysql> delete from wp_options where option_name like "displayed%"; Query OK, 157408 rows affected (6.82 sec)
Es hilft, danach die Tabelle nochmal aufzuräumen:
mysql> optimize table wp_options; +------------------+----------+----------+----------+ | Table | Op | Msg_type | Msg_text | +------------------+----------+----------+----------+ | blog.wp_options | optimize | status | OK | +------------------+----------+----------+----------+ 1 row in set (6.26 sec)
Und so habe ich die Ladezeit des Blogs von > 10 Sekunden insgesamt auf <2 Sekunden verringert! Ich wüsste nur gerne, welches Plugin dafür verantwortlich war. Höchstwarscheinlich eine alte Version der NextGEN Gallery, die ich für Fotos einsetze. Ich muss mal beobachten, ob auch die aktuelle Version diese Probleme hat.