La estrategia de invalidación predeterminada del complemento de caché de consultas es el Tiempo de Vida
(TTL
de 'Time To Live' en inglés). Los gestores de almacenamiento internos usarán el
TTL
predeterminado definido por el valor de configuración de PHP
mysqlnd_qc.ttl
a menos que la cadena de consulta contenga una sugerencia para establecer un
TTL
diferente. El TTL
se especifica en segundos.
Por omisión, las entradas de la caché expirarán tras 30
segundos.
El ejemplo establece mysqlnd_qc.ttl=3
para almacenar en caché
sentencias durante tres segundos por omisión. Cada segundo se actualiza
un registro de la tabla de la base de datos para mantener el tiempo actual, y se ejecuta
una sentencia SELECT
para obtener el registro desde la base
de datos. La sentencia SELECT
se almacena en caché durante
tres segundos debido a que está prefijada con la sugerencia SQL que habilita el almacenamiento
en caché. La salida verifica que los resultados de la consulta son tomados
desde la caché durante tres segundos antes de que
sean refrescados.
Ejemplo #1 Establecer el TTL con el ajuste ini mysqlnd_qc.ttl
mysqlnd_qc.enable_qc=1 mysqlnd_qc.ttl=3
<?php
/* Conectar, crear y rellenar la tabla test */
$mysqli = new mysqli("host", "usuario", "contraseña", "esquema", "puerto", "socket");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id VARCHAR(255))");
for ($i = 0; $i < 7; $i++) {
/* actualizar la fila de la BD */
if (!$mysqli->query("DELETE FROM test") ||
!$mysqli->query("INSERT INTO test(id) VALUES (NOW())"))
/* Por supuesto, un script de la vida real debería realizar un manejo de errores mejor */
die(sprintf("[%d] %s\n", $mysqli->errno, $mysqli->error));
/* seleccionar la última fila pero almacenando en caché los resultados */
$consulta = "/*" . MYSQLND_QC_ENABLE_SWITCH . "*/";
$consulta .= "SELECT id AS _time FROM test";
if (!($res = $mysqli->query($consulta)) ||
!($fila = $res->fetch_assoc()))
{
printf("[%d] %s\n", $mysqli->errno, $mysqli->error);
}
$res->free();
printf("Hora actual %s - Hora de la fila de la BD %s\n", date("H:i:s"), $fila['_time']);
/* pausar durante un segundo */
sleep(1);
}
?>
El resultado de los ejemplos sería algo similar a:
Hora actual 14:55:59 - Hora de la fila de la BD 2012-01-11 14:55:59 Hora actual 14:56:00 - Hora de la fila de la BD 2012-01-11 14:55:59 Hora actual 14:56:01 - Hora de la fila de la BD 2012-01-11 14:55:59 Hora actual 14:56:02 - Hora de la fila de la BD 2012-01-11 14:56:02 Hora actual 14:56:03 - Hora de la fila de la BD 2012-01-11 14:56:02 Hora actual 14:56:04 - Hora de la fila de la BD 2012-01-11 14:56:02 Hora actual 14:56:05 - Hora de la fila de la BD 2012-01-11 14:56:05
Como se puede ver en el ejemplo, cualquier caché basada en TTL
puede servir datos antiguos. Las entradas de la caché no son automáticamente invalidadas
si cambian los datos subyacentes. Las aplicaciones que usen la estragegia de invalidacón de
TTL
predeterminada deben poder funcionar correctamente
con datos antiguos.
Un gestor de almacenamiento definido por el usuario puede implementar cualquier estrategia de invalidación para evitar esta limitación.
El TTL
predeterminado se puede sobrescribir usando la sugerencia SQL
/*qc_tt=seconds*/
. Esta sugerencia SQL debe aparecer inmediatamente
después de la sugerencia SQL que habilita el almacenamiento en caché. Se recomienda usar la constante de PHP
MYSQLND_QC_TTL_SWITCH
en lugar del valor de cadena.
Ejemplo #2 Establecer el TTL con sugerencias SQL
<?php
$inicio = microtime(true);
/* Conectar, crear y rellenar la tabla test */
$mysqli = new mysqli("host", "usuario", "contraseña", "esquema", "puerto", "socket");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2)");
printf("TTL predeterminado\t: %d segundos\n", ini_get("mysqlnd_qc.ttl"));
/* Será almacenada en caché durante 2 segundos */
$sql = sprintf("/*%s*//*%s%d*/SELECT id FROM test WHERE id = 1", MYSQLND_QC_ENABLE_SWITCH, MYSQLND_QC_TTL_SWITCH, 2);
$res = $mysqli->query($sql);
var_dump($res->fetch_assoc());
$res->free();
$mysqli->query("DELETE FROM test WHERE id = 1");
sleep(1);
/* Coincidencia con la caché - ¡sin invalidación automática y aún válida! */
$res = $mysqli->query($sql);
var_dump($res->fetch_assoc());
$res->free();
sleep(2);
/* No coincide con la caché - la entrada de la caché ha expirado */
$res = $mysqli->query($sql);
var_dump($res->fetch_assoc());
$res->free();
printf("Tiempo de ejecución del script\t: %d segundos\n", microtime(true) - $inicio);
?>
El resultado de los ejemplos sería algo similar a:
TTL predeterminado : 30 segundos array(1) { ["id"]=> string(1) "1" } array(1) { ["id"]=> string(1) "1" } NULL Tiempo de ejecución del script : 3 segundos