¿Se recolectan los desechos transitorios?

61

Esta pregunta me hizo pensar que las fuentes RSS transitorias en wp_options no se eliminan automáticamente.

Se supone que los transitorios caducan y se eliminan. Sin embargo, la única forma en que veo que esto se maneja es cuando el transitorio caduca y se solicita, luego se elimina durante la solicitud.

¿Qué pasa si el transitorio expiró pero nunca se solicitó después de eso? De la descripción en Codex, pensé que algún tipo de recolección de basura está implícito. Ahora no estoy tan seguro y no puedo encontrar ningún código que realice tal.

Entonces, ¿se quedará atascado en la base de datos para siempre?

Rarst
fuente
teóricamente deberían eliminarse cuando se ejecuta cron (si han caducado)
onetrickpony
1
@ Amoeba ambiciosa, sí, mencioné eso en cuestión. Mi punto es: la creación transitoria no asume ni garantiza que alguna vez se va a solicitar. Destacando la pregunta original: ¿ cuándo y si el transitorio caducado se elimina si nunca lo consigo ?
Rarst
1
supone que limpia los datos caducados, pero sí, tiene razón, hay situaciones en las que nunca se eliminarían. Como eliminar un widget que usa transitorios. Debería enviar un ticket en el trác para esto :)
onetrickpony
1
@Rarst: ¿Parece algo perfecto para escribir un parche y enviarlo a trac?
MikeSchinkel
1
Boleto de
Stephen Harris

Respuestas:

45

Ahora son

Comenzando con WordPress 3.7, los transitorios caducados se eliminan en las actualizaciones de la base de datos, ver # 20316


Vieja respuesta

Si alguien no puede mostrarme lo contrario, parece que los transitorios no son basura recolectada después de todo. Lo que lo empeora es que, a diferencia de las opciones, no se garantiza que se almacenen en la base de datos. Por lo tanto, no hay una forma confiable de obtener una lista de todos los transitorios para verificar que caduquen.

Algunos códigos improvisados ​​para la recolección de basura si la base de datos se usa para almacenamiento:

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
fuente
$ time = $ _SERVER ['REQUEST_TIME']; y luego haciendo uso de $ time en la consulta SQL, no hagas eso. Trate más cuidadosamente con las variables / valores $ _SERVER para evitar inyecciones SQL.
Hakre
@hakre hm ... Elegí eso de la presentación sobre el rendimiento de PHP que lo recomendó sobre el uso time()que puede causar errores (la ejecución no es instantánea por naturaleza). El tiempo de solicitud lo establece el propio PHP, no proviene de ningún tipo de datos proporcionados por el usuario. ¿Por qué es esta vulnerabilidad?
Rarst
@Rarst: No dije que no debería usarlo, solo debería asegurarse de que esté codificado de forma segura para usarse dentro de la consulta SQL. Debe hacer esto con cada variable de una fuente externa. Es posible que las variables $ _SERVER no se configuren como se esperaba y, en su lugar, el usuario solicitante las configure incluso. Solo quería propagar algunas buenas prácticas de codificación. Como siempre, para conocer el estado real de disponibilidad, consulte los documentos. Para PHP 4, por ejemplo, una variable tal no existe y puede ser sobreescrita por un encabezado personalizado o variable de entorno - php.net/manual/en/reserved.variables.server.php
hakre
@hakre fijo (creo), gracias por el recordatorio PHP4 por cierto (no puedo esperar a que WordPress deje de
admitirlo
Eso se ve mucho mejor en mis ojos;). Esperemos que no haya ningún problema con el tiempo () y los enteros negativos que puedan eliminar todos o ninguno de los transitorios que por accidente. Nunca confíes en un sistema en ejecución: P
hakre
20

Trasladar algunos de los comentarios de la discusión a una respuesta, con una nueva redacción y un nuevo formato.

Básicamente, todo se reduce a que, a menos que tenga un caso súper extremo, en realidad no necesitan ser "recolectados de basura". Si nunca los busca, entonces no importa si están allí o no.

Ver, los transitorios se almacenan en la tabla de opciones de forma predeterminada. En una instalación básica, la tabla de opciones tendrá quizás 100 entradas. Cada transitorio agrega dos entradas más, pero incluso si tiene miles, no afectan la velocidad del sitio, ya que no se cargan automáticamente.

Al inicio, WordPress carga las opciones en la memoria, pero solo carga las opciones que tienen activada su bandera de carga automática. Los transitorios no reciben esto, por lo que no se cargan en la memoria. Solo los transitorios que se usan realmente más tarde incurrirán en un costo.

Desde la perspectiva de la base de datos, la tabla de opciones tiene índices tanto en la ID de la opción como en el nombre de la opción. Los transitorios siempre se cargan en función del nombre (clave), por lo que las búsquedas para ellos siempre son selecciones simples en un único valor de clave único. Por lo tanto, la búsqueda es O (log (n)) y es súper rápida. Con un Big-O de log (n), tendrías que entrar en los millones y millones de filas antes de que sea notable. Francamente, la sobrecarga en la configuración y desmontaje de la consulta, junto con la transferencia de datos real, es mucho más larga. La consulta en sí se ejecuta esencialmente en tiempo cero en comparación. Entonces, simplemente tener filas adicionales sin usar no afecta nada más que usar espacio extra en disco.

La indexación en bases de datos es una de esas ideas de lectura profunda que no tiene sentido para las personas que realmente no han entendido lo que está sucediendo detrás de escena. Las bases de datos están diseñadas para una recuperación rápida de datos, desde cero, y pueden manejar este tipo de cosas sin problemas. Esta es una lectura bastante buena: http://en.wikipedia.org/wiki/Index_(database )

Ahora, la limpieza de la manera más obvia (llamando a SQL DELETE en ellos) en realidad no los elimina de la base de datos. Simplemente los elimina del índice y marca la fila como "eliminada". Nuevamente, así es como funcionan las bases de datos. Para liberar realmente el espacio en disco, debe continuar y hacer una TABLA DE OPTIMIZACIÓN después, y esta no es una operación rápida. Toma tiempo. Probablemente más tiempo del que vale. Probablemente no sea suficiente para darle un ahorro en tiempo de CPU, en total.

Si tiene algún caso que está causando una inserción continua de nuevos transitorios que no se están utilizando, entonces necesita encontrar el problema subyacente. ¿Qué está insertando estos transitorios? ¿Están utilizando una clave cambiante o mutante? Si es así, entonces el complemento o el código que causa esto debería estar arreglado, básicamente, para no hacerlo. Eso será más útil, porque es probable que el código que no los crea correctamente tampoco los recupere y, por lo tanto, haga más trabajo del que tiene que hacer.

Por otro lado, puede haber un caso en el que se crean transitorios para algo como cada publicación. De hecho, esto puede ser perfectamente aceptable. Lo hago yo mismo en SFC, para almacenar los comentarios entrantes de Facebook. Cada publicación tiene un potencial transitorio asociado, lo que significa dos filas adicionales por publicación. Si tiene 10k publicaciones, tendrá 20k filas en la tabla de opciones (eventualmente). Esto no es malo ni lento, porque de nuevo, hay muy poca diferencia entre 100 filas y 20,000 filas en lo que a las bases de datos realmente les importa. Todo está indexado. Es rápido como el diablo. Sub-sub-milisegundos.

Cuando empiezas a meterte en millones de filas, entonces me preocuparía. Cuando el tamaño de la tabla de opciones aumenta por encima de cientos de megabytes, entonces me preocuparía lo suficiente como para echar un vistazo más de cerca. Pero en general, esto no es un problema, excepto en casos extremos. Ciertamente, no es un problema para nada más pequeño que algo como un gran sitio de noticias, con cientos de miles de publicaciones. Y para cualquier sitio lo suficientemente grande como para que sea un problema, debe usar un caché de objetos externo de algún tipo, y en ese caso, los transitorios se almacenan automáticamente allí en lugar de en la base de datos.

Otón
fuente
1
NB: los transitorios sin la expiración do obtener autloaded, y sin caducidad es el predeterminado , por lo que una solicitud / plugin está creando un montón de transitorios y no establecer una caducidad que van a utilizar trozos de memoria en cada carga de página / post.
webaware
No hay ninguna razón para usar un "transitorio sin vencimiento", porque eso es básicamente idéntico a una "opción" normal.
Otto
1
Claro, pero es el valor predeterminado . Como tal, muchos autores de complementos están agregando transitorios que no caducan.
webaware
1
Bueno, la solución aquí es simple: no use esos complementos. Lo están haciendo mal. Los transitorios no deben usarse como sesiones, no debe usarlos sin una caducidad significativa, y no deben tener claves mutantes o cambiantes.
Otto
2
Digamos, 7 días. Si un autor de plugin / tema quiere algo más grande o más pequeño, lo especificará. Si quieren la carga automática, no deberían tener que especificar 0 para la caducidad (= infinito), pero eso es lo que tienen actualmente con el parámetro de caducidad haciendo doble trabajo como el parámetro de carga automática sí / no. De cualquier manera, la caducidad predeterminada no debería conducir también a autoload = yes como predeterminado; eso es solo pedir problemas.
webaware
18

Otto: no podría estar más en desacuerdo contigo. El problema es que eventualmente con todos esos transitorios, el tamaño de la tabla se vuelve ridículo. No se necesitan millones de filas para atascarse. Actualmente estoy lidiando con una tabla de opciones que tiene más de 130k filas y se cuelga regularmente. Debido a que el campo de valor es un tipo de texto grande, incluso buscar solo las filas de "carga automática" se convierte en una pesadilla de rendimiento. Esos campos de valor se almacenan por separado del resto de los datos de la fila. Aunque es lógicamente parte de la misma tabla, las uniones deben ocurrir para extraer las filas que desee. Uniones que ahora tardan una eternidad porque los datos que necesita se extienden por todo el lugar en el disco. El perfilado (usando jet profiler para mysql) ha demostrado esto.

Agregar carga automática a la clave agrupada podría ayudar a resolver este problema. La agrupación en Autoload Desc, ID ASC por ejemplo, permitiría que todas las filas de carga automática se agrupen primero en el disco. Aún así, creo que estás viendo una gran tensión desde una perspectiva DB.

Personalmente creo que el diseño de este sistema es wack. La tabla de opciones parece haberse convertido en un genérico para muchas cosas. Eso está bien si el campo de valor es lo suficientemente pequeño como para incluirse en la misma página que el resto de los datos de la fila, y puede indexarse ​​de manera efectiva. Lamentablemente ese no es el caso. Quien haya diseñado esto debe volver a la clase DB101.

myke
fuente
55
cierto, pero considere que cuando comenzó el desarrollo de WordPress, nadie pensó que llegaría a tener miles de complementos usando la tabla de opciones como almacenamiento de datos :)
onetrickpony
@onetrickpony por eso es importante tomarse siempre su tiempo y hacer las cosas bien, ya sea que espere que sea enorme algún día o no :)
Mahmoud Al-Qudsi