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ían 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ían 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