Se sabe que almacenar en caché los resultados de las consultas de la base de datos puede reducir significativamente el tiempo de ejecución del script y minimizar la carga en el servidor de la base de datos. Esta técnica funciona muy bien si los datos que está procesando son esencialmente estáticos. Esto se debe a que muchas solicitudes de datos a la base de datos remota pueden eventualmente satisfacerse desde la memoria caché local, eliminando la necesidad de conectarse a la base de datos, ejecutar la consulta y obtener los resultados.
Pero almacenar en caché el conjunto de resultados de la base de datos suele ser una buena idea cuando la base de datos que está utilizando está en una computadora diferente al servidor web. Sin embargo, determinar la mejor estrategia de almacenamiento en caché para su situación puede resultar complicado. Por ejemplo, para aplicaciones en las que es importante utilizar el último conjunto de resultados de la base de datos, un enfoque de almacenamiento en caché activado por tiempo (comúnmente utilizado por sistemas de almacenamiento en caché que suponen que el caché se regenera cada vez que se alcanza la marca de tiempo de vencimiento) puede no ser una solución satisfactoria. . En este caso, necesita un mecanismo que notifique a la aplicación cada vez que cambien los datos de la base de datos que la aplicación necesita almacenar en caché, de modo que la aplicación pueda mantener los datos caducados almacenados en caché consistentes con la base de datos. En este caso, será muy conveniente utilizar la "Notificación de cambio de base de datos".
Comenzando con la notificación de cambios en la base de datos
El uso de la función Notificación de cambios en la base de datos es muy simple: cree un controlador de notificaciones que se ejecute para la notificación: un procedimiento almacenado PL/SQL o una función de devolución de llamada OCI del cliente. Luego, registre una consulta contra los objetos de la base de datos para los cuales desea recibir notificaciones de cambios, de modo que se llame al controlador de notificaciones cada vez que una transacción cambie cualquier objeto dentro de él y se confirme. Normalmente, el controlador de notificaciones envía el nombre de la tabla que se modificó, el tipo de cambio realizado y, opcionalmente, el ID de la fila modificada al oyente del cliente para que la aplicación cliente pueda realizar las acciones adecuadas en la respuesta.
Para comprender cómo funciona la función Notificación de cambio de base de datos, considere el siguiente ejemplo. Supongamos que su aplicación PHP accede a los pedidos almacenados en la tabla OE.ORDERS y a los artículos de pedido almacenados en OE.ORDER_ITEMS. Dado que la información sobre los pedidos realizados rara vez cambia, es posible que desee que su aplicación almacene en caché los conjuntos de resultados de las consultas en las tablas ORDERS y ORDER_ITEMS. Para evitar el acceso a datos obsoletos, puede utilizar Notificaciones de cambios en la base de datos, que permiten que su aplicación reciba notificaciones fácilmente sobre los cambios en los datos almacenados en las dos tablas anteriores.
Debe otorgar el permiso del sistema CHANGE NOTIFICATION y el permiso EXECUTE ON DBMS_CHANGENOTIFICATION al usuario de OE antes de poder registrar consultas para las tablas ORDERS y ORDER_ITEMS para recibir notificaciones y responder a los cambios DML o DDL en estas tablas. Para hacer esto, ejecute el siguiente comando desde una herramienta de línea de comandos SQL como SQL*Plus.
CONECTAR/COMO SYSDBA;
CONCEDER NOTIFICACIÓN DE CAMBIO A oe;
CONCEDER EJECUTAR EN DBMS_CHANGE_NOTIFICATION A oe;
Asegúrese de que el parámetro job_queue_processes de init.ora esté establecido en un valor distinto de cero para poder recibir notificaciones PL/SQL. Alternativamente, puede usar el siguiente comando ALTER SYSTEM:
ALTER SYSTEM SET "job_queue_processes"=2 Luego, después de conectarse como OE/OE, puede crear un controlador de notificaciones. Pero primero, debe crear el objeto de base de datos que utilizará el controlador de notificaciones. Por ejemplo, es posible que desee crear una o más tablas de base de datos en las que el controlador de notificaciones registre los cambios del registro. En el siguiente ejemplo, crea la tabla nfresults para registrar la fecha y hora en que se produjo el cambio, el nombre de la tabla que se modificó y un mensaje que indica si el controlador de notificaciones envió correctamente el mensaje de notificación al cliente.
CONECTAR oe/oe;
CREAR TABLA nfresults (
operar FECHA,
nombretbl VARCHAR2(60),
rslt_msg VARCHAR2(100)
);
En un escenario del mundo real, es posible que necesite crear más tablas para registrar información como eventos de notificación y los ID de las filas modificadas, pero para los fines de este artículo, la tabla nfresults será suficiente.
Uso de UTL_HTTP para enviar notificaciones a clientes.
También puede crear uno o más procedimientos almacenados PL/SQL y llamar a estos procedimientos almacenados desde el controlador de notificaciones, logrando así una solución más flexible y fácil de mantener. Por ejemplo, es posible que desee crear un procedimiento almacenado que implemente el envío de mensajes de notificación a los clientes. El "Listado 1" es el procedimiento PL/SQL sendNotification. Este proceso utiliza el paquete UTL_HTTPPL para enviar notificaciones de cambios a las aplicaciones cliente.
Listado 1. Enviar notificación al cliente usando UTL_HTTPCREATE
O REEMPLAZAR EL PROCEDIMIENTO sendNotification(url IN VARCHAR2,
tblname EN VARCHAR2, order_id EN VARCHAR2) ES
solicitar UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
err_msg VARCHAR2(100);
tblVARCHAR(60);
COMENZAR
tbl:=SUBSTR(nombretbl, INSTR(nombretbl, '.', 1, 1)+1, 60);
COMENZAR
req := UTL_HTTP.BEGIN_REQUEST(url||order_id||'&'||'table='||tbl);
resp := UTL_HTTP.GET_RESPONSE(solicitud);
INSERTAR EN nfresults VALUES(SYSDATE, tblname, resp.reason_phrase);
UTL_HTTP.END_RESPONSE(resp);
EXCEPCIÓN CUANDO OTROS ENTONCES
error_msg := SUBSTR(SQLERRM, 1, 100);
INSERT INTO nfresults VALUES(SYSDATE, tblname, err_msg);
FIN;
COMPROMETERSE;
FIN;
/
Como se muestra en el "Listado 1", sendNotification envía un mensaje de notificación al cliente en forma de una solicitud HTTP emitida por la función UTL_HTTP.BEGIN_REQUEST. Esta URL contiene el order_id de la fila modificada en la tabla PEDIDOS. Luego utiliza UTL_HTTP.GET_RESPONSE para obtener la información de respuesta enviada por el cliente. De hecho, sendNotification no necesita procesar la respuesta completa devuelta por el cliente, solo obtiene un mensaje corto (que describe el código de estado) almacenado en el campo Reason_phrase del registro RESP.
Creación de un controlador de notificaciones
Ahora puede crear un controlador de notificaciones que enviará notificaciones de cambios a los clientes con la ayuda del procedimiento sendNotification descrito anteriormente. Echemos un vistazo al procedimiento PL/SQL pedidos_nf_callback en el "Listado 2".
Listado 2. Controlador de notificaciones que maneja notificaciones de cambios en la tabla OE.ORDERS
CREATE OR REPLACE PROCEDUREorders_nf_callback (ntfnds IN SYS.CHNF$_DESC) IS
tblname VARCHAR2(60);
tablas numéricas NÚMERO;
tipo_evento NÚMERO;
fila_id VARCHAR2(20);
números NÚMERO;
orden_id VARCHAR2(12);
URL VARCHAR2(256) := 'http://webserverhost/phpcache/dropResults.php?order_no=';
COMENZAR
tipo_evento := ntfnds.tipo_evento;
tablas numéricas := ntfnds.numtables;
SI (tipo_evento = DBMS_CHANGE_NOTIFICATION.EVENT_OBJCHANGE) ENTONCES
PARA i EN 1.. BUCLE de numtables
tblname := ntfnds.table_desc_array(i).table_name;
SI (bitand(ntfnds.table_desc_array(i).opflags,
DBMS_CHANGE_NOTIFICATION.ALL_ROWS) = 0) ENTONCES
números de filas := ntfnds.table_desc_array(i).numrows;
DEMÁS
números :=0;
FINALIZAR SI;
SI (tblname = 'OE.ORDERS') ENTONCES
PARA j EN 1..numrows BUCLE
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
SELECCIONE order_id EN ord_id DESDE pedidos DONDE rowid = row_id;
enviarNotificación(url, tblname, ord_id);
FINALIZAR BUCLE;
FINALIZAR SI;
FINALIZAR BUCLE;
FINALIZAR SI;
COMPROMETERSE;
FIN;
/
Como se muestra en el "Listado 2", este controlador de notificaciones toma el objeto SYS.CHNF$_DESC como parámetro y luego usa sus propiedades para obtener los detalles del cambio. En este ejemplo, este controlador de notificaciones solo manejará las notificaciones publicadas por la base de datos en respuesta a cambios DML o DDL en objetos registrados (es decir, solo si el tipo de notificación es EVENT_OBJCHANGE) e ignorará la información sobre otros eventos de la base de datos, como el inicio de la instancia o cierre de instancia) notificación. A partir de la versión anterior, el controlador puede manejar notificaciones de cambios emitidas para cada fila afectada en la tabla OE.ORDERS. Más adelante en este artículo, en la sección "Agregar una tabla a un registro existente", agregará algunas líneas de código al controlador para que pueda manejar notificaciones de filas modificadas en la tabla OE.ORDER_ITEMS.
Crear un registro para notificaciones de cambios
Después de crear un controlador de notificaciones, debe crear un registro de consulta para él. Para este ejemplo, debe realizar una consulta en la tabla OE.ORDER durante el proceso de registro y especificar pedidos_nf_callback como controlador de notificaciones. También debe especificar la opción QOS_ROWIDS en el paquete DBMS_CHANGE_NOTIFICATION para habilitar la granularidad a nivel de ROWID en los mensajes de notificación. El "Listado 3" es un bloque PL/SQL que crea el registro de consulta para el controlador de notificaciones pedidos_nf_callback.
Listado 3. Crear registro de consultaDECLARAR
para el controlador de notificaciones
REGDS SYS.CHNF$_REG_INFO;
NÚMERO de registro;
orden_id NÚMERO;
NÚMERO de qosflags;
COMENZAR
qosflags := DBMS_CHANGE_NOTIFICATION.QOS_RELIABLE +
DBMS_CHANGE_NOTIFICATION.QOS_ROWIDS;
REGDS := SYS.CHNF$_REG_INFO ('orders_nf_callback', qosflags, 0,0,0);
regid := DBMS_CHANGE_NOTIFICATION.NEW_REG_START (REGDS);
SELECCIONE order_id EN ord_id DE pedidos DONDE ROWNUM<2;
DBMS_CHANGE_NOTIFICATION.REG_END;
FIN;
/
Este ejemplo crea un registro en la tabla PEDIDOS y utiliza pedidos_nf_callback como controlador de notificaciones. Ahora, si usa una declaración DML o DDL para modificar la tabla PEDIDOS y confirmar la transacción, la función pedidos_nf_callback se llama automáticamente. Por ejemplo, puede ejecutar la siguiente instrucción UPDATE en la tabla ORDERS y confirmar la transacción:
UPDATE ORDERS SET order_mode = 'direct' WHERE order_id=2421;
ACTUALIZAR PEDIDOS SET order_mode = 'directo' DONDE order_id=2422;
COMPROMETERSE;
Para asegurarse de que la base de datos publique notificaciones en respuesta a la transacción anterior, puede consultar la tabla nfresults:
SELECT TO_CHAR(operdate, 'dd-mon-yy hh:mi:ss') operdate,
tblname, rslt_msg DE nfresults;
El resultado debería verse así:
OPERDATE TBLNAME RSLT_MSG
--------------------- ---------- ---------
02-mar-06 04:31:28 OE.PEDIDOS no encontrados
02-mar-06 04:31:29 OE.PEDIDOS no encontrados
De los resultados anteriores se desprende claramente que pedidos_nf_callback ya está funcionando pero no se encuentra el script del cliente. Esto no es inesperado en este ejemplo porque no creó el script dropResults.php especificado en la URL. Para obtener instrucciones sobre el script dropResults.php, consulte la sección Creación del cliente más adelante en este artículo.
Agregar una tabla a un registro existente
La sección anterior mostró cómo usar el Servicio de notificación de cambios para que la base de datos le notifique cuando cambia un objeto de registro (en el ejemplo anterior, la tabla PEDIDOS). Pero desde una perspectiva de rendimiento, la aplicación cliente puede preferir almacenar en caché el conjunto de resultados de la consulta de la tabla ORDER_ITEMS en lugar de la tabla ORDERS en sí, porque tiene que recuperar solo una fila de la tabla ORDERS cada vez que accede al pedido, pero al final Al mismo tiempo, se deben recuperar varias filas de la tabla ORDER_ITEMS. En realidad, un pedido puede contener docenas o incluso cientos de líneas de pedido.
Como ya ha registrado consultas en la tabla ORDERS, no necesita crear un registro para registrar consultas en la tabla ORDER_ITEMS. En su lugar, puede utilizar un registro existente. Para hacer esto, primero necesita recuperar el ID de un registro existente. Puede ejecutar la siguiente consulta para lograr esto:
SELECT regid, table_name FROM user_change_notification_regs Los resultados pueden verse así:
REGID TABLE_NAME;
----- --------------
241 PEDIDOS OE.
Después de obtener el ID de registro, puede agregar un nuevo objeto al registro usando la función DBMS_CHANGE_NOTIFICATION.ENABLE_REG de la siguiente manera:
DECLARE
orden_id NÚMERO;
COMENZAR
DBMS_CHANGE_NOTIFICATION.ENABLE_REG(241);
SELECCIONE order_id EN ord_id DESDE order_items DONDE ROWNUM < 2;
DBMS_CHANGE_NOTIFICATION.REG_END;
FIN;
/
¡Hecho! De ahora en adelante, la base de datos generará una notificación en respuesta a cualquier cambio realizado en PEDIDOS y ORDER_ITEMS, y llamará al procedimiento pedidos_nf_callback para manejar la notificación. Por lo tanto, el siguiente paso es editar pedidos_nf_callback para que pueda manejar notificaciones generadas por operaciones DML en la tabla ORDER_ITEMS. Pero antes de volver a crear el procedimientoorders_nf_callback, debe crear el siguiente tipo de tabla al que se hará referencia durante el proceso de actualización:
CREATE TYPE rdesc_tab AS TABLE OF SYS.CHNF$_RDESC Luego, regrese al Listado 2, después de la siguiente línea de; código:
SI (tblname = 'OE.ORDERS') ENTONCES
PARA j EN 1..numrows BUCLE
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
SELECCIONE order_id EN ord_id DESDE pedidos DONDE rowid = row_id;
enviarNotificación(url, tblname, ord_id);
FINALIZAR BUCLE;
FINALIZAR SI;
Inserte el siguiente código:
IF (tblname = 'OE.ORDER_ITEMS') ENTONCES
PARA rec IN (SELECT DISTINCT(o.order_id) o_id FROM
TABLE(CAST(ntfnds.table_desc_array(i).row_desc_array AS rdesc_tab)) t,
pedidos o, order_items d DONDE t.row_id = d.rowid AND d.order_id=o.order_id)
BUCLE
enviarNotificación(url, tblname, rec.o_id);
FINALIZAR BUCLE;
FINALIZAR SI;
Después de volver a crear pedidos_nf_callback, debes probar que funciona correctamente. Para hacer esto, puede ejecutar la siguiente instrucción UPDATE en la tabla ORDER_ITEMS y confirmar la transacción:
UPDATE ORDER_ITEMS SET cantidad = 160 WHERE order_id=2421 AND line_item_id=1;
ACTUALIZAR ORDER_ITEMS SET cantidad = 160 DONDE order_id=2421 AND line_item_id=2;
COMPROMETERSE;
Luego, verifique la tabla nfresults de la siguiente manera:
SELECT TO_CHAR(operdate, 'dd-mon-yy hh:mi:ss') operdate,
rslt_msg FROM nfresults WHERE tblname = 'OE.ORDER_ITEMS' El resultado puede verse así:
OPERDATE RSLT_MSG;
-----------------------------------
03-mar-06 12:32:27 No encontrado
Quizás se pregunte por qué solo se insertó una fila en la tabla nfresults; después de todo, actualizó dos filas en la tabla ORDER_ITEMS. De hecho, las dos filas actualizadas tienen el mismo order_id, es decir, pertenecen al mismo orden. Aquí, asumimos que la aplicación cliente utilizará una sola declaración para seleccionar todos los artículos en línea de un pedido, por lo que no necesita saber exactamente qué artículos en línea de un pedido se han modificado. En cambio, el cliente necesita saber el ID del pedido en el que se modificó, eliminó o insertó al menos una línea de pedido.
Creación del cliente
Ahora que ha creado registros para las tablas ORDERS y ORDER_ITEMS, echemos un vistazo a cómo las aplicaciones cliente utilizan las notificaciones de cambios que acceden a los pedidos y sus artículos en línea almacenados en estas tablas. Para hacer esto, puede crear una aplicación PHP que almacene en caché los resultados de las consultas en las tablas anteriores y tome las acciones apropiadas en respuesta a las notificaciones sobre cambios en estas tablas (que se reciben del servidor de la base de datos). Una forma sencilla es utilizar el paquete PEAR::Cache_Lite, que le proporciona un mecanismo confiable para mantener actualizados los datos de la caché. En particular, puede utilizar la clase Cache_Lite_Function (parte del paquete PEAR::Cache_Lite), que le permite almacenar en caché las llamadas a funciones.
Por ejemplo, puede crear una función que realice las siguientes tareas: establezca una conexión a la base de datos, ejecute una instrucción de selección en la base de datos, obtenga los resultados de la búsqueda y finalmente devuelva los resultados como una matriz. Luego puede almacenar en caché las matrices de resultados devueltas por la función a través del método de llamada de la instancia Cache_Lite_Function para que puedan leerse desde la caché local en lugar de desde la base de datos back-end, lo que puede mejorar significativamente el rendimiento de su aplicación. Luego, cuando se le notifiquen los cambios en los datos almacenados en caché, utilizará el método de eliminación de la instancia Cache_Lite_Function para eliminar los datos caducados en el caché.
Volviendo al ejemplo de este artículo, es posible que desee crear dos funciones para que su aplicación interactúe con la base de datos: la primera función consultará la tabla PEDIDOS y devolverá los pedidos con el ID especificado, mientras que la otra función consultará ORDER_ITEMS. table y return Devuelve los artículos de línea para este pedido. El "Listado 4" muestra el script getOrderFields.php que contiene la función getOrderFields, que acepta un ID de pedido y devuelve una matriz asociativa que contiene algunos de los campos del pedido recuperado.
Listado 4. Obtener los campos del orden especificado
<?php
//Archivo:getOrderFields.php
require_once 'conectar.php';
función getOrderFields($order_no) {
si (!$rsConnection = GetConnection()){
devolver falso;
}
$strSQL = "SELECT TO_CHAR(ORDER_DATE) ORDER_DATE, CLIENTE_ID,
ORDER_TOTAL DE PEDIDOS DONDE order_id =:order_no";
$rsStatement = oci_parse($rsConnection,$strSQL);
oci_bind_by_name($rsStatement, ":order_no", $order_no, 12);
si (!oci_execute($rsStatement)) {
$err = oci_error();
imprimir $err['mensaje'];
trigger_error('Consulta fallida:' . $err['mensaje']);
devolver falso;
}
$resultados = oci_fetch_assoc($rsStatement);
devolver $resultados;
}
?>
El "Listado 5" es el script getOrderItems.php. El script contiene la función getOrderItems, que acepta un ID de pedido y devuelve una matriz bidimensional que contiene filas que representan las líneas de pedido del pedido.
Listado 5. Obtenga las líneas de pedido del orden especificado
<?php
//Archivo:getOrderItems.php
require_once 'conectar.php';
función getOrderItems($order_no) {
si (!$rsConnection = GetConnection()){
devolver falso;
}
$strSQL = "SELECCIONAR * DE ORDER_ITEMS DONDE
order_id =:order_no ORDENAR POR line_item_id";
$rsStatement = oci_parse($rsConnection,$strSQL);
oci_bind_by_name($rsStatement, ":order_no", $order_no, 12);
si (!oci_execute($rsStatement)) {
$err = oci_error();
trigger_error('Consulta fallida:' . $err['mensaje']);
devolver falso;
}
$nrows = oci_fetch_all($rsStatement, $resultados);
matriz de retorno ($nrows, $resultados);
}
?>
Tenga en cuenta que ambas funciones anteriores requieren el script connect.php, que debe contener la función GetConnection que devuelve la conexión a la base de datos. El Listado 6 es el script connect.php:
Listado 6. Obtener conexión a la base de datos
<?php
//Archivo:connect.php
función ObtenerConexión() {
$dbHost = "dbserverhost";
$dbHostPort="1521";
$dbServiceName = "orclR2";
$usr = "oe";
$pswd = "oe";
$dbConnStr = "(DESCRIPCIÓN=(DIRECCIÓN=(PROTOCOLO=TCP)(HOST=".$dbHost.")
(PORT=".$dbHostPort."))(CONNECT_DATA=(SERVICE_NAME=".$dbServiceName.")))";
if(!$dbConn = oci_connect($usr,$pswd,$dbConnStr)) {
$err = oci_error();
trigger_error('Error al conectar ' .$err['mensaje']);
devolver falso;
}
devolver $dbConn;
}
?>
Ahora que ha creado todas las funciones necesarias para comunicarse con la base de datos, veamos cómo funciona la clase Cache_Lite_Function. El Listado 7 es el script testCache.php que utiliza la clase Cache_Lite_Function para almacenar en caché los resultados de la función anterior.
<?php
usando PEAR::Cache_Lite
//Archivo:testCache.php
require_once 'getOrderItems.php';
require_once 'getOrderFields.php';
require_once 'Caché/Lite/Function.php';
$opciones = matriz(
'cacheDir' => '/tmp/',
'tiempo de vida' => 86400
);
si (!isset($_GET['order_no'])) {
die('El parámetro order_no es obligatorio');
}
$núm_pedido=$_GET['núm_pedido'];
$caché = nueva Cache_Lite_Function($opciones);
if ($orderfields = $cache->call('getOrderFields', $order_no)){
print "<h3>ORDEN #$order_no</h3>n";
imprimir "<tabla>";
print "<tr><td>FECHA:</td><td>".$orderfields['ORDER_DATE']."</td></tr>";
print "<tr><td>CUST_ID:</td><td>".$orderfields['CUSTOMER_ID']."</td></tr>";
print "<tr><td>TOTAL:</td><td>".$orderfields['ORDER_TOTAL']."</td></tr>";
imprimir "</tabla>";
} demás {
print "¡Ocurrió algún problema al obtener los campos del pedido!n";
$cache->drop('getOrderFields', $order_no);
}
if (lista($nrows, $orderitems) = $cache->call('getOrderItems', $order_no)){
//imprimir "<h3>LINEA DE ARTÍCULOS EN PEDIDO #$order_no</h3>";
imprimir "<borde de la tabla=1>";
imprimir "<tr>n";
mientras (lista($clave, $valor) = cada uno($orderitems)) {
print "<th>$key</th>n";
}
imprimir "</tr>n";
para ($i = 0; $i < $nfilas; $i++) {
imprimir "<tr>";
print "<td>".$orderitems['ORDER_ID'][$i]."</td>";
print "<td>".$orderitems['LINE_ITEM_ID'][$i]."</td>";
print "<td>".$orderitems['PRODUCT_ID'][$i]."</td>";
print "<td>".$orderitems['UNIT_PRICE'][$i]."</td>";
print "<td>".$orderitems['CANTIDAD'][$i]."</td>";
imprimir "</tr>";
}
imprimir "</tabla>";
} demás {
print "Ocurrió algún problema al obtener las líneas de pedido";
$cache->drop('getOrderItems', $order_no);
}
?>
El script testCache.php en el "Listado 7" debe llamarse con el parámetro URL order_no (que representa el ID del pedido almacenado en la tabla OE.ORDER). Por ejemplo, para recuperar información relacionada con el pedido con ID 2408, ingresará la siguiente URL en su navegador:
http://webserverhost/phpcache/testCache.php?order_no=2408 Como resultado, el navegador generará el siguiente resultado :
PEDIDO #2408
FECHA: 29-JUN-99 06.59.31.333617 A.M.
CLIENTE_ID: 166
TOTAL: 309
ORDER_ID LINE_ITEM_ID PRODUCT_ID UNIT_PRICE CANTIDAD
2408 1 2751 61 3
2408 2 2761 26 1
2408 3 2783 10 10Ahora
, si hace clic en el botón recargar en el navegador, el script testCache.php no volverá a llamar a las funciones getOrderFields y getOrderItems. En cambio, leerá los resultados del caché local. Por lo tanto, cada llamada a getOrderFields o getOrderItems con order_no=2108 será satisfecha por el caché local dentro de 24 horas a partir de ahora (porque lifeTime está establecido en 86400 segundos). Sin embargo, tenga en cuenta que la clase Cache_Lite_Function no proporciona una API para probar si hay un caché disponible para una función determinada con parámetros determinados. Por lo tanto, puede resultar un poco complicado determinar si la aplicación realmente lee el caché o aún ejecuta la función cada vez que se llama con los mismos parámetros. Por ejemplo, en el ejemplo anterior, para garantizar que el mecanismo de almacenamiento en caché funcione correctamente, puede cambiar temporalmente la información de conexión especificada en el script connect.php para que no pueda establecer la conexión de la base de datos, por ejemplo, especificar un nombre de host del servidor de base de datos incorrecto; y luego use order_no= nuevamente 2108 Ejecute el script testCache.php. Si el almacenamiento en caché funciona correctamente, la salida del navegador debería ser la misma que antes.
Además, puede verificar el directorio de caché que se pasa al constructor de la clase Cache_Lite_Function como el valor de la opción cacheDir (/tmp en este ejemplo). En ese directorio encontrará dos archivos de caché que acaba de crear con nombres similares a: cache_7b181b55b55aee36ad5e7bd9d5a091ec_3ad04d3024f4cd54296f75c92a359154. Tenga en cuenta que si es usuario de Windows, es posible que desee utilizar el directorio %SystemDrive%temp para guardar archivos de caché. Si es así, la opción cacheDir debe establecerse en /temp/.
Después de verificar que el mecanismo de almacenamiento en caché funciona correctamente, puede crear un PHP para manejar las notificaciones de cambios recibidas del servidor de la base de datos. El "Listado 8" es el script dropResult.php. El servidor de la base de datos llamará a este script en respuesta a cambios en las tablas ORDERS y ORDER_ITEMS.
Listado 8. Manejo de notificaciones de cambios recibidas del servidor de base de datos
<?php
//Archivo:dropResults.php
require_once 'Caché/Lite/Function.php';
$opciones = matriz(
'cacheDir' => '/tmp/'
);
$caché = nueva Cache_Lite_Function($opciones);
si (isset($_GET['order_no'])&& isset($_GET['table'])) {
si($_GET['tabla']=='ORDER_ITEMS'){
$cache->drop('getOrderItems', $_GET['order_no']);
}
si ($_GET['tabla']=='PEDIDOS'){
$cache->drop('getOrderFields', $_GET['order_no']);
}
}
?>
Después de crear el script dropResult.php, asegúrese de que la URL especificada en el controlador de notificaciones (que se muestra en el Listado 2) sea correcta. Luego, conéctese como OE/OE en SQL*Plus o herramienta similar y ejecute declaraciones ACTUALIZAR que afectarán a las mismas órdenes a las que se accedió anteriormente en esta sección a través del script testCache.php (aquí la orden con ID 2408):
ACTUALIZAR ORDERS SET order_mode = ' directo' DONDE order_id=2408;
ACTUALIZAR ORDER_ITEMS SET cantidad = 3 DONDE order_id=2408 AND line_item_id=1;
ACTUALIZAR ORDER_ITEMS SET cantidad = 1 DONDE order_id=2408 AND line_item_id=2;
COMPROMETERSE;
En respuesta a la actualización anterior, el controlador de notificaciones descrito anteriormente en este artículo ejecutará el script dropResults.php dos veces, utilizando las siguientes URL: http://webserverhost/phpcache/dropResults.php?order_no=2408&table=ORDERS
http://webserverhost/phpcache/dropresults.php?order_no=2408&table=ORDER_ITEMS
En el "Listado 8" se puede ver claramente que el script dropResult.php no vacía el caché después de recibir la notificación de cambio del servidor de la base de datos. Simplemente elimina los archivos de caché que contienen datos caducados. Entonces, si revisa el directorio de caché ahora, verá que el archivo de caché creado al ejecutar el script testCache.php con order_no=2408 ha desaparecido. Lo que esto significa esencialmente es que la próxima vez que testCache.php solicite datos relacionados con el ID de pedido 2408, obtendrá esos datos de la base de datos backend en lugar del caché local.
Este método puede resultarle útil en situaciones en las que es probable que el conjunto de resultados solicitado por la aplicación cambie antes de que la aplicación lo utilice. Para los propósitos del ejemplo de este artículo, esto significa que los datos relacionados con un pedido específico pueden cambiar varias veces antes de que testCache.php acceda a ese pedido. De esta manera, la aplicación realiza una gran cantidad de trabajo innecesario al vaciar su caché inmediatamente después de recibir notificaciones de cambios del servidor de la base de datos.
Pero si desea que el script dropResult.php vacíe el caché tan pronto como se le notifique el cambio, puede llamar al método de llamada de la instancia Cache_Lite_Function después de llamar al método drop, especificando los mismos parámetros para ambas llamadas. En este caso, también debes asegurarte de incluir los scripts getOrderFields.php y getOrderItems.php para que dropResults.php pueda llamar a las funciones getOrderFields y getOrderItems para actualizar el caché. El "Listado 9" es el script dropResult.php modificado.
Listado 9. Vaciar el caché inmediatamente después de recibir la notificación de cambio
<?php
//Archivo:dropResults.php
require_once 'Caché/Lite/Function.php';
require_once 'getOrderItems.php';
require_once 'getOrderFields.php';
$opciones = matriz(
'cacheDir' => '/tmp/',
'tiempo de vida' => 86400
);
$caché = nueva Cache_Lite_Function($opciones);
si (isset($_GET['order_no'])&& isset($_GET['table'])) {
si($_GET['tabla']=='ORDER_ITEMS'){
$cache->drop('getOrderItems', $_GET['order_no']);
$cache->call('getOrderItems', $_GET['order_no']);
}
si ($_GET['tabla']=='PEDIDOS'){
$cache->drop('getOrderFields', $_GET['order_no']);
$cache->call('getOrderFields', $_GET['order_no']);
}
}
?>
El enfoque anterior puede resultar útil si los datos almacenados en las tablas ORDERS y ORDER_ITEMS rara vez cambian y la aplicación accede a ellos con frecuencia.
Resumen
Si su aplicación PHP interactúa con Oracle Database 10g Versión 2, puede aprovechar la función Notificación de cambio de base de datos, que permite que su aplicación reciba notificaciones en respuesta a cambios DML en el objeto asociado con la solicitud realizada. Al utilizar esta función, no es necesario que actualice el caché de su aplicación durante un período de tiempo específico. En cambio, la operación se realiza sólo si el conjunto de resultados de la consulta registrada ha cambiado.