Werden transiente Abfälle gesammelt?

61

Diese Frage brachte mich auf den Gedanken, dass vorübergehende RSS-Feeds in wp_options nicht automatisch entfernt werden?

Transienten sollen ablaufen und gelöscht werden. Die einzige Möglichkeit, wie ich dies sehe, besteht darin, dass ein Transient abgelaufen und angefordert ist und dann während der Anforderung gelöscht wird.

Was passiert, wenn der Transient abgelaufen ist, danach aber nie mehr angefordert wird? Aufgrund der Beschreibung im Codex dachte ich, dass eine Art Müllabfuhr impliziert ist. Jetzt bin ich mir nicht so sicher und kann keinen Code finden, der so etwas ausführt.

Wird es also für immer in der Datenbank bleiben?

Rarst
quelle
Theoretisch sollten sie entfernt werden, wenn cron ausgeführt wird (wenn sie abgelaufen sind)
onetrickpony
1
@Ambitious Amoeba Ja, ich habe das in Frage gestellt. Ich gehe davon aus, dass das Erstellen von Transienten nicht davon ausgeht oder garantiert, dass sie jemals angefordert werden. Betonen Sie die ursprüngliche Frage - wann und ob abgelaufene Transienten gelöscht werden, wenn ich sie nie bekomme ?
Rarst
1
Es wird davon ausgegangen, dass Sie die abgelaufenen Daten bereinigen, aber ja, Sie haben Recht, es gibt Situationen, in denen sie niemals gelöscht werden würden. Wie das Entfernen eines Widgets, das Transienten verwendet. Sie sollten ein Ticket auf dem Trac für diese einreichen :)
onetrickpony
1
@Rarst - Klingt nach einer perfekten Sache, um einen Patch für Trac zu schreiben und ihn einzureichen?
MikeSchinkel
1
Zugehöriges Trac-Ticket: core.trac.wordpress.org/ticket/20316
Stephen Harris

Antworten:

45

Sie sind es jetzt

Ab WordPress 3.7 werden abgelaufene Transienten bei Datenbank-Upgrades gelöscht, siehe # 20316


Alte Antwort

Wenn mir jemand nichts anderes zeigen kann, scheinen Transienten doch kein Müll zu sein. Was es noch schlimmer macht, ist, dass im Gegensatz zu Optionen nicht garantiert wird, dass sie in der Datenbank gespeichert werden. Es gibt also keine zuverlässige Möglichkeit, eine Liste aller Transienten abzurufen, um sie auf Ablauf zu überprüfen.

Behelfsmäßiger Code für die Speicherbereinigung, wenn die Datenbank zum Speichern verwendet wird:

add_action( 'wp_scheduled_delete', 'delete_expired_db_transients' );

function delete_expired_db_transients() {

    global $wpdb, $_wp_using_ext_object_cache;

    if( $_wp_using_ext_object_cache )
        return;

    $time = isset ( $_SERVER['REQUEST_TIME'] ) ? (int)$_SERVER['REQUEST_TIME'] : time() ;
    $expired = $wpdb->get_col( "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout%' AND option_value < {$time};" );

    foreach( $expired as $transient ) {

        $key = str_replace('_transient_timeout_', '', $transient);
        delete_transient($key);
    }
}
Rarst
quelle
$ time = $ _SERVER ['REQUEST_TIME']; und dann $ time in der SQL-Abfrage verwenden - tun Sie das nicht. Gehen Sie sorgfältiger mit $ _SERVER-Variablen / -Werten um, um SQL-Injektionen zu verhindern.
Hakre
@hakre hm ... Ich habe das aus der Präsentation über die PHP-Leistung ausgewählt, die es über die Verwendung empfohlen hat, time()was zu Fehlern führen kann (die Ausführung erfolgt von Natur aus nicht sofort). Die Anforderungszeit wird von PHP selbst festgelegt und stammt nicht aus von Benutzern bereitgestellten Daten. Warum ist diese Sicherheitsanfälligkeit?
Rarst
@Rarst: Ich habe nicht gesagt, dass Sie es nicht verwenden sollten, Sie sollten nur sicherstellen, dass es sicher codiert ist, um in der SQL-Abfrage verwendet zu werden. Sie sollten dies mit jeder Variablen aus einer externen Quelle tun. $ _SERVER-Variablen werden möglicherweise nicht wie erwartet festgelegt, sondern vom anfordernden Benutzer selbst festgelegt. Ich wollte nur eine gute Codierungspraxis verbreiten. Informationen zum tatsächlichen Verfügbarkeitsstatus finden Sie wie immer in den Dokumenten. Für PHP 4 zum Beispiel existiert eine solche Variable nicht und kann durch einen benutzerdefinierten Header oder eine Umgebungsvariable überschrieben werden - php.net/manual/en/reserved.variables.server.php
hakre
@hakre behoben (ich denke), danke für die PHP4-Erinnerung, übrigens (ich kann es kaum erwarten, dass WordPress die Unterstützung
aufgibt
Das sieht in meinen Augen viel besser aus;). Hoffen wir, dass es kein Problem mit time () und negativen Ganzzahlen gibt, die alle oder keine Transienten versehentlich löschen könnten. Traue niemals einem laufenden System: P
hakre
20

Verschieben einiger Kommentare aus der Diskussion in eine Antwort mit Neuformulierung und Neuformatierung.

Grundsätzlich kommt es darauf an, dass sie nicht wirklich "Müll gesammelt" werden müssen, es sei denn, Sie haben einen Super-Extremfall. Wenn Sie sie nie abholen, spielt es keine Rolle, ob sie dort sind oder nicht.

Siehe, Transienten werden standardmäßig in der Optionstabelle gespeichert. In einer Basisinstallation enthält die Optionstabelle möglicherweise 100 Einträge. Jeder Übergang fügt zwei weitere Einträge hinzu. Auch wenn Sie Tausende Einträge haben, wirken sich diese nicht auf die Site-Geschwindigkeit aus, da sie nicht automatisch geladen werden.

Beim Start lädt WordPress die Optionen in den Speicher, lädt jedoch nur Optionen, deren Autoload-Flag aktiviert ist. Transienten erhalten dies nicht und werden daher nicht in den Speicher geladen. Nur Transienten, die später tatsächlich verwendet werden, verursachen Kosten.

Aus Sicht der Datenbank enthält die Optionstabelle Indizes sowohl für die Options-ID als auch für den Optionsnamen. Transienten werden immer auf der Grundlage des Namens (Schlüssels) geladen, und die Suche nach ihnen ist immer eine einfache Auswahl für einen einzelnen eindeutigen Schlüsselwert. Die Suche lautet also O (log (n)) und ist superschnell. Mit einem Big-O von log (n) müssten Sie in die Millionen und Abermillionen von Zeilen vordringen, bevor es auffällt. Ehrlich gesagt ist der Aufwand für das Einrichten und Herunterfahren der Abfrage sowie für die eigentliche Datenübertragung viel länger. Die Abfrage selbst wird im Vergleich im Wesentlichen null-mal ausgeführt. Das bloße Vorhandensein zusätzlicher nicht verwendeter Zeilen wirkt sich also nur auf die Verwendung von zusätzlichem Speicherplatz aus.

Das Indizieren in Datenbanken ist eine dieser tief gelesenen Ideen, die für Leute, die nicht wirklich verstanden haben, was sich hinter den Kulissen abspielt, keinen Sinn ergibt. Datenbanken sind für den schnellen Abruf von Daten von Grund auf ausgelegt und können solche Aufgaben problemlos ausführen. Dies ist eine ziemlich gute Lektüre: http://en.wikipedia.org/wiki/Index_(database )

Jetzt werden sie bei einer Bereinigung auf offensichtlichste Weise (durch Aufrufen von SQL DELETE) nicht mehr aus der Datenbank gelöscht. Sie werden einfach aus dem Index entfernt und die Zeile als "gelöscht" markiert. Wiederum funktionieren Datenbanken genau so. Um den Speicherplatz tatsächlich freizugeben, müssen Sie fortfahren und anschließend eine OPTIMIZE TABLE ausführen. Dies ist keine schnelle Operation. Es braucht Zeit. Wahrscheinlich mehr Zeit als es wert ist. Es reicht wahrscheinlich nicht aus, um insgesamt CPU-Zeit einzusparen.

Wenn in einem bestimmten Fall ständig neue Transienten eingefügt werden, die nicht verwendet werden, müssen Sie stattdessen das zugrunde liegende Problem suchen. Was ist das Einfügen dieser Transienten? Verwenden sie einen sich ändernden oder mutierenden Schlüssel? Wenn ja, dann sollte das Plugin oder der Code, der dies verursacht, im Grunde genommen nicht so sein. Das ist hilfreicher, da der Code, der sie nicht richtig erstellt, sie wahrscheinlich auch nicht abruft und damit mehr Arbeit leistet, als er tun muss.

Andererseits kann es vorkommen, dass für so etwas wie jeden Post Transienten erstellt werden. Dies kann in der Tat durchaus akzeptabel sein. Ich mache das selbst in SFC, um eingehende Kommentare von Facebook zu speichern. Mit jedem Post ist ein potenzieller Transient verbunden, dh zwei zusätzliche Zeilen pro Post. Wenn Sie 10.000 Posts haben, haben Sie (eventuell) 20.000 Zeilen in der Optionstabelle. Dies ist weder schlecht noch langsam, da es, soweit es die Datenbanken wirklich betrifft, kaum Unterschiede zwischen 100 Zeilen und 20.000 Zeilen gibt. Es ist alles indiziert. Es ist verdammt schnell. Sub-Sub-Millisekunden.

Wenn Sie anfangen, in Millionen von Reihen zu geraten, wäre ich besorgt. Wenn die Größe der Optionstabelle über Hunderte von Megabyte steigt, würde ich mir genug Sorgen machen, um genauer hinzuschauen. Im Allgemeinen ist dies jedoch kein Problem, mit Ausnahme von Extremfällen. Es ist mit Sicherheit kein Problem für etwas Kleineres als eine große Nachrichtenseite mit Hunderttausenden von Posts. Und für jede Site, die groß genug ist, um ein Problem zu verursachen, sollten Sie einen externen Objektcache verwenden. In diesem Fall werden die Transienten dort automatisch gespeichert und nicht in der Datenbank.

Otto
quelle
1
NB: Transienten ohne Ablauf do autloaded bekommen, und kein Ablaufdatum ist der Standard , also wo eine Anwendung / Plugin viele Transienten und nicht die Erstellung eines Ablauf Einstellung werden sie Stücke von Speicher auf jeder Seite / Post Last werden.
WebAware
Es gibt keinen Grund, einen "Transienten ohne Ablauf" zu verwenden, da dies im Grunde mit einer normalen "Option" identisch ist.
Otto
1
Sicher, aber es ist die Standardeinstellung . Daher fügen viele Plugin-Autoren nicht ablaufende Transienten hinzu.
webaware
1
Nun, die Lösung hier ist einfach: Verwenden Sie diese Plugins nicht. Sie machen es falsch. Transienten dürfen nicht als Sitzungen verwendet werden, Sie sollten sie nicht ohne einen sinnvollen Ablauf verwenden und sie dürfen keine mutierenden oder wechselnden Schlüssel haben.
Otto
2
Sagen wir, 7 Tage. Wenn ein Plugin / Theme-Autor etwas Größeres oder Kleineres haben möchte, gibt er es an. Wenn sie ein automatisches Laden wünschen, sollten sie keine 0 für das Ablaufen (= unendlich) angeben müssen, aber das ist das, was sie derzeit haben, wenn der Ablaufparameter die doppelte Aufgabe als Ja / Nein-Parameter für das automatische Laden ausführt. In beiden Fällen sollte der Standardablauf nicht auch zu automatischem Laden = yes als Standard führen. das bittet nur um Ärger.
webaware
18

Otto - ich könnte dir nicht mehr widersprechen. Das Problem ist, dass mit all diesen Übergängen die Größe der Tabelle lächerlich wird. Es braucht nicht Millionen von Reihen, um sich zu verzetteln. Derzeit habe ich es mit einer Optionstabelle zu tun, die mehr als 130.000 Zeilen enthält und regelmäßig hängt. Da es sich bei dem Wertefeld um einen großen Texttyp handelt, wird selbst das Suchen nach "Autoload" -Zeilen zu einem Albtraum der Leistung. Diese Wertfelder werden getrennt von den übrigen Zeilendaten gespeichert. Obwohl es logischerweise Teil derselben Tabelle ist, müssen Verknüpfungen stattfinden, um die gewünschten Zeilen abzurufen. Beitritte, die jetzt für immer dauern, weil die von Ihnen benötigten Daten auf der Festplatte verteilt sind. Das Profiling (mit Jet Profiler für MySQL) hat dies bewiesen.

Das Hinzufügen des automatischen Ladevorgangs zum Clustered Key kann zur Lösung dieses Problems beitragen. Durch Clustering in Autoload Desc, z. B. ID ASC, können alle Autoload-Zeilen zuerst auf der Festplatte zusammengefasst werden. Trotzdem denke ich, dass Sie eine enorme Belastung aus Sicht der DB sehen.

Persönlich denke ich, dass das Design dieses Systems verrückt ist. Die Optionstabelle scheint zu einem allgemeinen Sammelbegriff für viele Dinge geworden zu sein. Das ist in Ordnung, wenn das Wertefeld klein genug ist, um auf derselben Seite wie die übrigen Zeilendaten enthalten zu sein, und effektiv indiziert werden kann. Leider ist das nicht der Fall. Wer auch immer dies entworfen hat, muss in die Klasse DB101 zurückkehren.

myke
quelle
5
Stimmt, aber wenn man bedenkt, dass zu Beginn der WordPress-Entwicklung niemand damit
gerechnet hat
@onetrickpony, deshalb ist es wichtig, sich immer Zeit zu nehmen und die Dinge richtig zu machen, egal ob Sie eines Tages damit rechnen, dass es riesig wird oder nicht :)
Mahmoud Al-Qudsi