Les passagers sont-ils ramassés?

61

Cette question m'a fait penser que les flux RSS transitoires dans wp_options ne sont pas supprimés automatiquement?

Les transitoires sont supposés expirer et être supprimés. Cependant, la seule façon de voir cela traité est lorsque le transitoire est expiré et demandé, puis il est supprimé lors de la demande.

Que se passe-t-il si le transitoire a expiré mais n'est jamais demandé après cela? D'après la description du Codex, je pensais qu'une sorte de ramasse-miettes est implicite. Maintenant, je ne suis pas si sûr et je ne trouve aucun code qui fonctionne de la sorte.

Alors, sera-t-il bloqué dans la base de données pour toujours?

Rarst
la source
théoriquement, ils devraient être supprimés à l'exécution de cron (s'ils sont expirés)
onetrickpony le
1
@Ambitious Amoeba oui, j'ai un peu mentionné cela en question. Ce que je veux dire, c’est que la création de transitoires ne suppose ni ne garantit qu’il sera toujours demandé. Soulignant la question initiale - quand et si expiré, le transitoire est supprimé si je ne l' obtiens jamais ?
Rarst
1
cela suppose que vous nettoyez les données expirées, mais oui, vous avez raison, il existe des situations dans lesquelles elles ne seraient jamais supprimées. C'est comme supprimer un widget qui utilise des transitoires. Vous devriez soumettre un billet sur le circuit pour cela :)
onetrickpony
1
@Rarst - Cela semble être une chose parfaite pour écrire un correctif et le soumettre à Trac?
MikeSchinkel
1
Ticket de correspondance connexe
Stephen Harris

Réponses:

45

Ils sont maintenant

À partir de WordPress 3.7, les transitoires arrivés à expiration sont supprimés lors de la mise à niveau de la base de données, voir le n ° 20316.


Ancienne réponse

Si quelqu'un ne peut pas me montrer le contraire, il semble que les passagers ne soient pas ramassés après tout. Ce qui aggrave la situation, c'est que contrairement aux options, leur stockage dans la base de données n'est pas garanti. Il n’existe donc aucun moyen fiable d’extraire la liste de tous les transitoires pour vérifier leur expiration.

Quelques codes de fortune pour faire la récupération de place si la base de données est utilisée pour le stockage:

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
la source
$ time = $ _SERVER ['REQUEST_TIME']; puis en utilisant $ time dans la requête SQL - ne le faites pas. Traitez plus attentivement les variables / valeurs $ _SERVER pour éviter les injections SQL.
hakre
@hakre hm ... J'ai choisi cela dans la présentation sur les performances de PHP qui le recommandait plutôt que d'utiliser time()ce qui peut causer des bugs (l'exécution n'est pas instantanée par nature). Le temps de demande est défini par PHP lui-même, il ne provient d'aucune sorte de données fournies par l'utilisateur. Pourquoi cette vulnérabilité?
Rarst
@Rarst: Je n'ai pas dit que vous ne devriez pas l'utiliser, vous devez simplement vous assurer qu'il est codé en toute sécurité pour pouvoir être utilisé dans la requête SQL. Vous devriez faire cela avec chaque variable d'une source externe. Les variables $ _SERVER peuvent ne pas être définies comme prévu, mais par l'utilisateur demandeur même. Je voulais seulement propager de bonnes pratiques de codage. Comme toujours, pour connaître l'état réel de disponibilité, consultez la documentation. Pour PHP 4 par exemple, une telle variable n'existe pas et peut être écrasée par un en-tête personnalisé ou une variable d'environnement - php.net/manual/fr/reserved.variables.server.php
hakre le
@hakre corrigé (je pense), merci pour le rappel de PHP4 btw (j'ai hâte que WordPress abandonne le support)
Rarst
Cela semble beaucoup mieux à mes yeux;). Espérons qu'il n'y a pas de problème avec time () et les nombres entiers négatifs qui pourraient supprimer tous les transitoires, voire aucun, par accident. Ne faites jamais confiance à un système en fonctionnement: P
hakre
20

Déplacement de certains commentaires de la discussion dans une réponse, avec reformulation et reformatage.

En gros, si on a un cas extrême, ils n'ont pas vraiment besoin d'être "ramassés". Si vous ne les récupérez jamais, peu importe qu'ils soient là ou non.

Voir, les transitoires sont stockés dans la table d'options par défaut. Dans une installation de base, la table d'options contiendra peut-être 100 entrées. Chaque transitoire ajoute deux entrées supplémentaires, mais même si vous en avez des milliers, elles n’affectent pas la vitesse du site, car elles ne sont pas chargées automatiquement.

Au démarrage, WordPress charge les options en mémoire, mais il ne charge que les options dont l'indicateur de chargement automatique est activé. Les passagers ne comprennent pas cela et ne sont donc pas chargés en mémoire. Seuls les transitoires qui seront effectivement utilisés plus tard entraîneront des coûts.

Du point de vue de la base de données, la table des options contient des index sur l’option Id et sur le nom de l’option. Les transitoires sont toujours chargés en fonction du nom (clé). Par conséquent, leurs recherches sont toujours simples et se font sur une seule valeur de clé. Ainsi, la recherche est O (log (n)) et est super rapide. Avec un Big-O de log (n), il faudrait entrer dans les millions et les millions de lignes avant que cela devienne perceptible. Franchement, le temps système nécessaire à la configuration et à la suppression de la requête, ainsi que le transfert des données, est beaucoup plus long. La requête elle-même s'exécute pratiquement à zéro heure par comparaison. Donc, le simple fait d’ avoir des rangées inutilisées en plus n’affecte que l’utilisation d’espace disque supplémentaire.

L'indexation dans les bases de données est l'une de ces idées profondes qui n'a pas de sens pour ceux qui n'ont pas encore compris ce qui se passe dans les coulisses. Les bases de données sont conçues pour une récupération rapide des données, à partir de la base, et peuvent gérer ce genre de choses sans problèmes. C'est une très bonne lecture: http://en.wikipedia.org/wiki/Index_(database )

Désormais, le nettoyage de la manière la plus évidente (appeler SQL DELETE sur eux) ne les supprime pas réellement de la base de données. Il les supprime simplement de l'index et marque la ligne comme "supprimée". Encore une fois, c’est ainsi que fonctionnent les bases de données. Pour réellement libérer de l’espace disque, vous devez continuer et exécuter ensuite une table OPTIMIZE TABLE. Il ne s’agit pas d’une opération rapide. Ça prend du temps. Probablement plus de temps que ça en vaut la peine. Ce n'est probablement pas suffisant pour vous permettre d'économiser du temps processeur au total.

Si certains cas entraînent une insertion continue de nouveaux transitoires qui ne sont pas utilisés, vous devez alors rechercher le problème sous-jacent. Qu'est-ce que l'insertion de ces transitoires? Utilisent-ils une clé changeante ou en mutation? Si tel est le cas, le plug-in ou le code à l'origine de ce problème doit être corrigé pour ne pas le faire. Ce sera plus utile, car il est probable que le code qui ne les crée pas correctement ne les récupère pas non plus, ce qui représente plus de travail que nécessaire.

D'autre part, il peut arriver que des transitoires soient créés pour quelque chose comme toutes les publications. Cela peut en effet être parfaitement acceptable. Je le fais moi-même dans SFC, pour stocker les commentaires entrants de Facebook. Chaque publication est associée à un transitoire potentiel, ce qui signifie deux lignes supplémentaires par publication. Si vous avez 10k postes, vous aurez 20k lignes dans la table d'options (éventuellement). Ce n'est ni mauvais ni lent, car encore une fois, il y a très peu de différence entre 100 et 20 000 lignes pour ce qui est des bases de données. Tout est indexé. C'est rapide comme bonjour. Sous-sous-millisecondes.

Quand tu commences à entrer dans des millions de rangs, je m'inquiète. Lorsque la taille de la table d'options dépasse plusieurs centaines de mégaoctets, je serais suffisamment préoccupée pour examiner de plus près. Mais d’une manière générale, ce n’est pas un problème, sauf dans les cas extrêmes. Ce n’est certainement pas un problème pour des projets plus petits qu’un site comme un grand site d’informations, avec des centaines de milliers de messages. Et pour tout site suffisamment grand pour poser problème, vous devez utiliser un type de cache d’objets externe. Dans ce cas, les éléments transitoires sont automatiquement stockés dans cette base plutôt que dans la base de données.

Otto
la source
1
NB: les transitoires sans expiration ne s'autloaded, et aucune date d' expiration est le défaut , donc où une application / plugin crée beaucoup de transitoires et ne fixant pas une expiration , ils utiliseront des morceaux de mémoire sur chaque page / charge de poste.
Webaware
Il n'y a aucune raison d'utiliser un "transitoire sans expiration", car il est fondamentalement identique à une "option" normale.
Otto le
1
Bien sûr, mais c'est la valeur par défaut . En tant que tels, de nombreux auteurs de plugins ajoutent des transitoires non expirants.
Webaware
1
Eh bien, la solution est simple: n'utilisez pas ces plugins. Ils le font mal. Les transitoires ne doivent pas être utilisés comme sessions, vous ne devez pas les utiliser sans expiration significative, et ils ne doivent pas avoir de clé en mutation ou changeante.
Otto
2
Dis, 7 jours. Si un auteur de plugin / thème veut quelque chose de plus grand ou de plus petit, il le précisera. S'ils veulent charger automatiquement, ils ne devraient pas avoir à spécifier 0 pour l'expiration (= infini), mais c'est ce qu'ils ont actuellement avec le paramètre d'expiration faisant double emploi en tant que paramètre de chargement automatique oui / non. Quoi qu'il en soit, l'expiration par défaut ne devrait pas également conduire à autoload = yes par défaut; c'est juste demander des ennuis.
Webaware
18

Otto - Je ne pourrais pas être plus en désaccord avec vous. Le problème est que finalement avec tous ces transitoires, la taille de la table devient ridicule. Il ne faut pas des millions de lignes pour s'enliser. Je traite actuellement avec une table d'options comportant plus de 130 000 lignes et qui se bloque régulièrement. Étant donné que le champ de valeur est un type de texte volumineux, même rechercher uniquement les lignes de "chargement automatique" devient un cauchemar de performances. Ces champs de valeur sont stockés séparément du reste des données de la ligne. Même si cela fait logiquement partie de la même table, des jointures doivent avoir lieu pour afficher les lignes souhaitées. Les jointures prennent maintenant une éternité car les données dont vous avez besoin sont réparties sur le disque. Le profilage (en utilisant jet profiler pour mysql) l'a prouvé.

L'ajout du chargement automatique à la clé en cluster peut aider à résoudre ce problème. Le regroupement sur Autoload Desc, ID ASC par exemple, permettrait à toutes les lignes de chargement automatique de se regrouper en premier sur le disque. Même quand même, je pense que vous envisagez une énorme pression du point de vue de la DB.

Personnellement, je pense que la conception de ce système est géniale. Le tableau des options semble s'être transformé en un fourre-tout général pour beaucoup de choses. Cela convient si le champ de valeur est suffisamment petit pour être inclus sur la même page que le reste des rowdata et qu'il peut être indexé efficacement. Malheureusement ce n'est pas le cas. Celui qui a conçu cela doit retourner à la classe DB101.

myke
la source
5
C'est vrai, mais considérez que lorsque le développement de WordPress a commencé, personne ne pensait qu'il serait possible d'avoir des milliers de plugins en utilisant la table d'options comme stockage de données :)
onetrickpony
@onetrickpony c'est pourquoi il est important de toujours prendre son temps et de bien faire les choses, que l'on s'attende à ce que ce soit énorme ou pas demain.
Mahmoud Al-Qudsi