Il est connu que la mise en cache des résultats des requêtes de base de données peut réduire considérablement le temps d'exécution du script et minimiser la charge sur le serveur de base de données. Cette technique fonctionne très bien si les données que vous traitez sont essentiellement statiques. En effet, de nombreuses requêtes de données adressées à la base de données distante peuvent éventuellement être satisfaites à partir du cache local, éliminant ainsi le besoin de se connecter à la base de données, d'exécuter la requête et d'obtenir les résultats.
Mais la mise en cache du jeu de résultats de la base de données est souvent une bonne idée lorsque la base de données que vous utilisez se trouve sur un ordinateur différent de celui du serveur Web. Cependant, déterminer la meilleure stratégie de mise en cache pour votre situation peut s’avérer difficile. Par exemple, pour les applications où il est important d'utiliser le dernier jeu de résultats de base de données, une approche de mise en cache déclenchée par le temps (couramment utilisée par les systèmes de mise en cache qui supposent que le cache est régénéré à chaque fois que l'horodatage d'expiration est atteint) peut ne pas être une solution satisfaisante. . Dans ce cas, vous avez besoin d'un mécanisme qui avertira l'application chaque fois que les données de la base de données que l'application doit mettre en cache changent, afin que l'application puisse conserver les données expirées mises en cache cohérentes avec la base de données. Dans ce cas, utiliser « Notification de modification de base de données » sera très pratique.
Premiers pas avec la notification de modification de base de données
L'utilisation de la fonctionnalité de notification de modification de base de données est très simple : créez un gestionnaire de notification qui exécute pour la notification - une procédure stockée PL/SQL ou une fonction de rappel OCI client. Ensuite, enregistrez une requête sur les objets de base de données pour lesquels vous souhaitez recevoir des notifications de modification, afin que le gestionnaire de notifications soit appelé chaque fois qu'une transaction modifie un objet qu'elle contient et est validée. En règle générale, le gestionnaire de notification envoie le nom de la table qui a été modifiée, le type de modification effectuée et éventuellement l'ID de la ligne modifiée à l'écouteur client afin que l'application client puisse effectuer les actions appropriées dans la réponse.
Pour comprendre le fonctionnement de la fonctionnalité de notification de modification de base de données, considérez l'exemple suivant. Supposons que votre application PHP accède aux commandes stockées dans la table OE.ORDERS et aux éléments de commande stockés dans OE.ORDER_ITEMS. Étant donné que les informations sur les commandes passées changent rarement, vous souhaiterez peut-être que votre application mette en cache les ensembles de résultats des requêtes par rapport aux tables ORDERS et ORDER_ITEMS. Pour éviter d'accéder à des données obsolètes, vous pouvez utiliser les notifications de modification de base de données, qui permettent à votre application d'être facilement informée des modifications apportées aux données stockées dans les deux tableaux ci-dessus.
Vous devez accorder l'autorisation système CHANGE NOTIFICATION et l'autorisation EXECUTE ON DBMS_CHANGENOTIFICATION à l'utilisateur OE avant de pouvoir enregistrer des requêtes pour les tables ORDERS et ORDER_ITEMS afin de recevoir des notifications et de répondre aux modifications DML ou DDL apportées à ces tables. Pour ce faire, exécutez la commande suivante à partir d'un outil de ligne de commande SQL tel que SQL*Plus.
CONNECTER/EN TANT QUE SYSDBA ;
ACCORDER UNE NOTIFICATION DE CHANGEMENT À oe ;
GRANT EXECUTE ON DBMS_CHANGE_NOTIFICATION TO oe ;
Assurez-vous que le paramètre init.ora job_queue_processes est défini sur une valeur non nulle afin de recevoir les notifications PL/SQL. Vous pouvez également utiliser la commande ALTER SYSTEM suivante :
ALTER SYSTEM SET "job_queue_processes"=2; Ensuite, après vous être connecté en tant qu'OE/OE, vous pouvez créer un gestionnaire de notifications. Mais d’abord, vous devez créer l’objet base de données qui sera utilisé par le gestionnaire de notifications. Par exemple, vous souhaiterez peut-être créer une ou plusieurs tables de base de données dans lesquelles le gestionnaire de notifications enregistre les modifications du registre. Dans l'exemple suivant, vous créez la table nfresults pour enregistrer la date et l'heure de la modification, le nom de la table qui a été modifiée et un message indiquant si le gestionnaire de notifications a envoyé avec succès le message de notification au client.
CONNECT oe/oe ;
CRÉER TABLE nfresults (
date d'opération,
nom de table VARCHAR2(60),
rslt_msg VARCHAR2(100)
);
Dans un scénario réel, vous devrez peut-être créer davantage de tables pour enregistrer des informations telles que les événements de notification et les ID des lignes modifiées, mais pour les besoins de cet article, la table nfresults suffira.
Utilisation de UTL_HTTP pour envoyer des notifications aux clients
Vous pouvez également créer une ou plusieurs procédures stockées PL/SQL et appeler ces procédures stockées à partir du gestionnaire de notifications, obtenant ainsi une solution plus maintenable et plus flexible. Par exemple, vous souhaiterez peut-être créer une procédure stockée qui implémente l'envoi de messages de notification aux clients. "Listing 1" est la procédure PL/SQL sendNotification. Ce processus utilise le package UTL_HTTPPL pour envoyer des notifications de modification aux applications clientes.
Listing 1. Envoyer une notification au client en utilisant UTL_HTTPCREATE
OR REPLACE PROCEDURE sendNotification(url IN VARCHAR2,
nom_table DANS VARCHAR2, id_commande DANS VARCHAR2) EST
req UTL_HTTP.REQ ;
resp UTL_HTTP.RESP;
err_msg VARCHAR2(100);
à table VARCHAR(60);
COMMENCER
tbl:=SUBSTR(nom de table, INSTR(nom de table, '.', 1, 1)+1, 60);
COMMENCER
req := UTL_HTTP.BEGIN_REQUEST(url||order_id||'&'||'table='||tbl);
resp := UTL_HTTP.GET_RESPONSE(req);
INSERT INTO nfresults VALUES(SYSDATE, tblname, resp.reason_phrase);
UTL_HTTP.END_RESPONSE(resp);
EXCEPTION QUAND LES AUTRES PUIS
err_msg := SUBSTR(SQLERRM, 1, 100);
INSERT INTO nfresults VALUES(SYSDATE, tblname, err_msg);
FIN;
COMMETTRE;
FIN;
/
Comme le montre le « Listing 1 », sendNotification envoie un message de notification au client sous la forme d'une requête HTTP émise par la fonction UTL_HTTP.BEGIN_REQUEST. Cette URL contient le order_id de la ligne modifiée dans la table ORDERS. Il utilise ensuite UTL_HTTP.GET_RESPONSE pour obtenir les informations de réponse envoyées par le client. En fait, sendNotification n'a pas besoin de traiter l'intégralité de la réponse renvoyée par le client, mais obtient uniquement un court message (décrivant le code d'état) stocké dans le champ Reason_phrase de l'enregistrement RESP.
Création d'un gestionnaire de notifications
Vous pouvez maintenant créer un gestionnaire de notifications qui enverra des notifications de modification aux clients à l'aide de la procédure sendNotification décrite ci-dessus. Jetons un coup d'oeil à la procédure PL/SQL commandes_nf_callback dans le "Listing 2".
Listing 2. Gestionnaire de notifications qui gère les notifications de modifications apportées à la table OE.ORDERS
CREATE OR REPLACE PROCEDURE commandes_nf_callback (ntfnds IN SYS.CHNF$_DESC) IS
nom de table VARCHAR2(60);
numtables NOMBRE ;
type_événement NUMÉRO ;
row_id VARCHAR2(20);
nombres NOMBRE ;
ord_id VARCHAR2(12);
url VARCHAR2(256) := 'http://webserverhost/phpcache/dropResults.php?order_no=';
COMMENCER
event_type := ntfnds.event_type;
numtables := ntfnds.numtables;
SI (event_type = DBMS_CHANGE_NOTIFICATION.EVENT_OBJCHANGE) ALORS
POUR i EN 1..boucle numtables
nom_table := ntfnds.table_desc_array(i).nom_table ;
SI (bitand(ntfnds.table_desc_array(i).opflags,
DBMS_CHANGE_NOTIFICATION.ALL_ROWS) = 0) ALORS
numrows := ntfnds.table_desc_array(i).numrows;
AUTRE
nombres :=0;
FIN SI ;
SI (nom de table = 'OE.ORDERS') ALORS
POUR j IN 1..numrows BOUCLE
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
SELECT order_id INTO ord_id FROM commandes WHERE rowid = row_id ;
sendNotification (url, nom de table, ord_id);
FIN DE BOUCLE ;
FIN SI ;
FIN DE BOUCLE ;
FIN SI ;
COMMETTRE;
FIN;
/
Comme le montre le « Listing 2 », ce gestionnaire de notifications prend l'objet SYS.CHNF$_DESC comme paramètre et utilise ensuite ses propriétés pour obtenir les détails de la modification. Dans cet exemple, ce gestionnaire de notifications traitera uniquement les notifications publiées par la base de données en réponse aux modifications DML ou DDL apportées aux objets enregistrés (c'est-à-dire uniquement si le type de notification est EVENT_OBJCHANGE) et ignorera les informations sur d'autres événements de base de données tels que le démarrage de l'instance ou instance d'arrêt). À partir de la version ci-dessus, le gestionnaire peut gérer les notifications de modification émises pour chaque ligne affectée dans la table OE.ORDERS. Plus loin dans cet article, dans la section « Ajout d'une table à un enregistrement existant », vous ajouterez quelques lignes de code au gestionnaire afin qu'il puisse gérer les notifications pour les lignes modifiées dans la table OE.ORDER_ITEMS.
Créer un enregistrement pour les notifications de modification
Après avoir créé un gestionnaire de notifications, vous devez créer un enregistrement de requête pour celui-ci. Pour cet exemple, vous devez effectuer une requête sur la table OE.ORDER pendant le processus d'enregistrement et spécifierorders_nf_callback comme gestionnaire de notification. Vous devez également spécifier l'option QOS_ROWIDS dans le package DBMS_CHANGE_NOTIFICATION pour activer la granularité au niveau ROWID dans les messages de notification. "Listing 3" est un bloc PL/SQL qui crée l'enregistrement de requête pour le gestionnaire de notificationorders_nf_callback.
Listing 3. Créer un enregistrement de requêteDECLARE
pour le gestionnaire de notifications
REGDS SYS.CHNF$_REG_INFO ;
NOMBRE enregistré ;
ord_id NUMÉRO ;
qosflags NUMÉRO ;
COMMENCER
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);
SELECT order_id INTO ord_id FROM commandes WHERE ROWNUM<2 ;
DBMS_CHANGE_NOTIFICATION.REG_END ;
FIN;
/
Cet exemple crée un enregistrement sur la table ORDERS et utilise commandes_nf_callback comme gestionnaire de notification. Désormais, si vous utilisez une instruction DML ou DDL pour modifier la table ORDERS et valider la transaction, la fonctionorders_nf_callback est automatiquement appelée. Par exemple, vous pouvez exécuter l'instruction UPDATE suivante sur la table ORDERS et valider la transaction :
UPDATE ORDERS SET order_mode = 'direct' WHERE order_id=2421;
MISE À JOUR DES COMMANDES SET order_mode = 'direct' WHERE order_id=2422;
COMMETTRE;
Pour vous assurer que la base de données a publié des notifications en réponse à la transaction ci-dessus, vous pouvez vérifier la table nfresults :
SELECT TO_CHAR(operdate, 'dd-mon-yy hh:mi:ss') operdate,
nom de table, rslt_msg FROM nfresults ;
Le résultat devrait ressembler à ceci :
OPERDATE TBLNAME RSLT_MSG
----------- ---------- ---------
02 mars 06 04:31:28 OE.ORDERS introuvable
02 mars 06 04:31:29 OE.ORDERS introuvable
Il ressort clairement des résultats ci-dessus que commandes_nf_callback fonctionne déjà mais que le script client n'est pas trouvé. Ceci n'est pas inattendu dans cet exemple car vous n'avez pas créé le script dropResults.php spécifié dans l'URL. Pour obtenir des instructions sur le script dropResults.php, consultez la section Création du client plus loin dans cet article.
Ajout d'une table à un enregistrement existant
La section précédente a montré comment utiliser le service de notification de modification pour que la base de données vous avertisse lorsqu'un objet d'enregistrement (dans l'exemple ci-dessus, la table ORDERS) change. Mais du point de vue des performances, l'application client peut préférer mettre en cache le jeu de résultats de requête de la table ORDER_ITEMS plutôt que la table ORDERS elle-même, car elle ne doit récupérer qu'une seule ligne de la table ORDERS à chaque fois qu'elle accède à la commande, mais au en même temps Plusieurs lignes doivent être récupérées de la table ORDER_ITEMS. En réalité, une campagne peut contenir des dizaines, voire des centaines d’éléments de campagne.
Puisque vous avez déjà enregistré des requêtes sur la table ORDERS, vous n'avez pas besoin de créer un enregistrement pour enregistrer des requêtes sur la table ORDER_ITEMS. Au lieu de cela, vous pouvez utiliser une inscription existante. Pour ce faire, vous devez d'abord récupérer l'identifiant d'une inscription existante. Pour ce faire, vous pouvez exécuter la requête suivante :
SELECT regid, table_name FROM user_change_notification_regs. Les résultats peuvent ressembler à ceci :
REGID TABLE_NAME;
----- ---------------
241 OE.COMMANDES
Après avoir obtenu l'ID d'enregistrement, vous pouvez ajouter un nouvel objet à l'enregistrement à l'aide de la fonction DBMS_CHANGE_NOTIFICATION.ENABLE_REG comme suit :
DECLARE
ord_id NUMÉRO ;
COMMENCER
DBMS_CHANGE_NOTIFICATION.ENABLE_REG(241);
SELECT order_id INTO ord_id FROM order_items WHERE ROWNUM < 2 ;
DBMS_CHANGE_NOTIFICATION.REG_END ;
FIN;
/
Fait! Désormais, la base de données générera une notification en réponse à toute modification apportée à ORDERS et ORDER_ITEMS, et appellera la procédureorders_nf_callback pour gérer la notification. Par conséquent, l'étape suivante consiste à modifier commandes_nf_callback afin qu'il puisse gérer les notifications générées par les opérations DML sur la table ORDER_ITEMS. Mais avant de recréer la procédureorders_nf_callback, vous devez créer le type de table suivant qui sera référencé lors du processus de mise à jour :
CREATE TYPE rdesc_tab AS TABLE OF SYS.CHNF$_RDESC Ensuite, revenez au Listing 2, après la ligne suivante de code :
SI (tblname = 'OE.ORDERS') ALORS
POUR j IN 1..numrows BOUCLE
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
SELECT order_id INTO ord_id FROM commandes WHERE rowid = row_id ;
sendNotification (url, nom de table, ord_id);
FIN DE BOUCLE ;
FIN SI ;
Insérez le code suivant :
IF (tblname = 'OE.ORDER_ITEMS') ALORS
POUR rec IN (SELECT DISTINCT(o.order_id) o_id FROM
TABLE(CAST(ntfnds.table_desc_array(i).row_desc_array AS rdesc_tab)) t,
commandes o, order_items d OÙ t.row_id = d.rowid ET d.order_id=o.order_id)
BOUCLE
sendNotification (url, nom de table, rec.o_id);
FIN DE BOUCLE ;
FIN SI ;
Après avoir recréé order_nf_callback, vous devez tester qu'il fonctionne correctement. Pour ce faire, vous pouvez exécuter l'instruction UPDATE suivante sur la table ORDER_ITEMS et valider la transaction :
UPDATE ORDER_ITEMS SET quantité = 160 WHERE order_id=2421 AND line_item_id=1;
UPDATE ORDER_ITEMS SET quantité = 160 WHERE order_id=2421 AND line_item_id=2 ;
COMMETTRE;
Ensuite, vérifiez la table nfresults comme suit :
SELECT TO_CHAR(operdate, 'dd-mon-yy hh:mi:ss') operdate,
rslt_msg FROM nfresults WHERE tblname = 'OE.ORDER_ITEMS'; Le résultat peut ressembler à ceci :
OPERDATE RSLT_MSG;
-----------------------------------
03 mars 06 12:32:27 Introuvable
Vous vous demandez peut-être pourquoi une seule ligne a été insérée dans la table nfresults – après tout, vous avez mis à jour deux lignes dans la table ORDER_ITEMS. En fait, les deux lignes mises à jour ont le même order_id, c'est-à-dire qu'elles appartiennent à la même commande. Ici, nous supposons que l'application client utilisera une seule instruction pour sélectionner tous les éléments de ligne d'une commande, elle n'a donc pas besoin de savoir exactement quels éléments de ligne d'une commande ont été modifiés. Au lieu de cela, le client doit connaître l'ID de commande dans lequel au moins un élément de campagne a été modifié, supprimé ou inséré.
Construire le client
Maintenant que vous avez créé des enregistrements pour les tables ORDERS et ORDER_ITEMS, examinons comment les notifications de modification sont utilisées par les applications clientes qui accèdent aux commandes et à leurs éléments de ligne stockés dans ces tables. Pour ce faire, vous pouvez créer une application PHP qui mettra en cache les résultats des requêtes sur les tables ci-dessus et prendra les actions appropriées en réponse aux notifications concernant les modifications apportées à ces tables (qui sont reçues du serveur de base de données). Un moyen simple consiste à utiliser le package PEAR::Cache_Lite, qui vous fournit un mécanisme fiable pour maintenir les données du cache à jour. En particulier, vous pouvez utiliser la classe Cache_Lite_Function (qui fait partie du package PEAR::Cache_Lite), qui vous permet de mettre en cache les appels de fonction.
Par exemple, vous pouvez créer une fonction qui effectue les tâches suivantes : établit une connexion à la base de données, exécute une instruction select sur la base de données, obtient les résultats de la recherche et renvoie enfin les résultats sous forme de tableau. Vous pouvez ensuite mettre en cache les tableaux de résultats renvoyés par la fonction via la méthode d'appel de l'instance Cache_Lite_Function afin qu'ils puissent être lus à partir du cache local plutôt qu'à partir de la base de données principale, ce qui peut améliorer considérablement les performances de votre application. Ensuite, lorsque vous serez informé des modifications apportées aux données mises en cache, vous utiliserez la méthode drop de l'instance Cache_Lite_Function pour supprimer les données expirées dans le cache.
En revenant à l'exemple de cet article, vous souhaiterez peut-être créer deux fonctions pour que votre application interagisse avec la base de données : la première fonction interrogera la table ORDERS et renverra les commandes avec l'ID spécifié, tandis que l'autre fonction interrogera la table ORDER_ITEMS. table et return Renvoie les éléments de campagne pour cette commande. Le "Listing 4" montre le script getOrderFields.php qui contient la fonction getOrderFields, qui accepte un ID de commande et renvoie un tableau associatif contenant certains des champs de la commande récupérée.
Listing 4. Obtenir les champs dans l'ordre spécifié
<?php
//Fichier : getOrderFields.php
require_once 'connect.php';
fonction getOrderFields($order_no) {
si (!$rsConnection = GetConnection()){
renvoie faux ;
}
$strSQL = "SELECT TO_CHAR(ORDER_DATE) ORDER_DATE, CUSTOMER_ID,
ORDER_TOTAL FROM ORDERS WHERE order_id =:order_no";
$rsStatement = oci_parse($rsConnection,$strSQL);
oci_bind_by_name($rsStatement, ":order_no", $order_no, 12);
si (!oci_execute($rsStatement)) {
$erreur = oci_error();
imprimer $err['message'];
trigger_error('Échec de la requête :' . $err['message']);
renvoie faux ;
}
$results = oci_fetch_assoc($rsStatement);
renvoyer $results ;
}
?>
"Listing 5" est le script getOrderItems.php. Le script contient la fonction getOrderItems, qui accepte un ID de commande et renvoie un tableau bidimensionnel contenant des lignes représentant les éléments de campagne de la commande.
Liste 5. Obtenir les éléments de campagne dans l'ordre spécifié
<?php
//Fichier : getOrderItems.php
require_once 'connect.php';
fonction getOrderItems ($order_no) {
si (!$rsConnection = GetConnection()){
renvoie faux ;
}
$strSQL = "SELECT * FROM ORDER_ITEMS OÙ
order_id =:order_no ORDER BY line_item_id";
$rsStatement = oci_parse($rsConnection,$strSQL);
oci_bind_by_name($rsStatement, ":order_no", $order_no, 12);
si (!oci_execute($rsStatement)) {
$erreur = oci_erreur();
trigger_error('Échec de la requête :' . $err['message']);
renvoie faux ;
}
$nrows = oci_fetch_all($rsStatement, $results);
tableau de retour ($nrows, $results);
}
?>
Notez que les deux fonctions ci-dessus nécessitent le script connect.php, qui doit contenir la fonction GetConnection qui renvoie la connexion à la base de données. Le listing 6 est le script connect.php :
Listing 6. Obtenir la connexion à la base de données
<?php
//Fichier:connect.php
fonction GetConnection() {
$dbHost = "hôte du serveur de base de données" ;
$dbHostPort="1521";
$dbServiceName = "orclR2" ;
$usr = "oe";
$pswd = "oe" ;
$dbConnStr = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$dbHost.")
(PORT=".$dbHostPort."))(CONNECT_DATA=(SERVICE_NAME=".$dbServiceName.")))";
if(!$dbConn = oci_connect($usr,$pswd,$dbConnStr)) {
$erreur = oci_error();
trigger_error('Échec de la connexion ' .$err['message']);
renvoie faux ;
}
renvoie $dbConn ;
}
?>
Maintenant que vous avez créé toutes les fonctions nécessaires pour communiquer avec la base de données, voyons comment fonctionne la classe Cache_Lite_Function. Le listing 7 est le script testCache.php qui utilise la classe Cache_Lite_Function pour mettre en cache les résultats de la fonction ci-dessus.
de <?php
à l'aide de PEAR::Cache_Lite
//Fichier : testCache.php
require_once 'getOrderItems.php';
require_once 'getOrderFields.php';
require_once 'Cache/Lite/Function.php';
$options = tableau(
'cacheDir' => '/tmp/',
'durée de vie' => 86400
);
si (!isset($_GET['order_no'])) {
die('Le paramètre order_no est obligatoire');
}
$order_no=$_GET['order_no'];
$cache = nouveau Cache_Lite_Function($options);
if ($orderfields = $cache->call('getOrderFields', $order_no)){
print "<h3>ORDER #$order_no</h3>n";
imprimer "<table>" ;
print "<tr><td>DATE:</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>";
imprimer "</table>" ;
} autre {
print "Un problème est survenu lors de l'obtention des champs de commande !n";
$cache->drop('getOrderFields', $order_no);
}
if (list($nrows, $orderitems) = $cache->call('getOrderItems', $order_no)){
//print "<h3>ÉLÉMENTS DE LIGNE DANS L'ORDRE #$order_no</h3>";
print "<table border=1>";
imprimer "<tr>n" ;
while (list($key, $value) = each($orderitems)) {
print "<ième>$clé</ième>n";
}
imprimer "</tr>n" ;
pour ($i = 0; $i < $nrows; $i++) {
imprimer "<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['QUANTITY'][$i]."</td>";
imprimer "</tr>" ;
}
imprimer "</table>" ;
} autre {
print "Un problème est survenu lors de l'obtention des éléments de ligne de commande" ;
$cache->drop('getOrderItems', $order_no);
}
?>
Le script testCache.php du "Listing 7" doit être appelé avec le paramètre URL order_no (représentant l'ID de commande stocké dans la table OE.ORDER). Par exemple, pour récupérer les informations relatives à la commande portant l'ID 2408, vous devez saisir l'URL suivante dans votre navigateur :
http://webserverhost/phpcache/testCache.php?order_no=2408. En conséquence, le navigateur générera la sortie suivante :
COMMANDE #2408
DATE : 29-JUIN-99 06.59.31.333617 AM
CUST_ID : 166
TOTAL : 309
ORDER_ID LINE_ITEM_ID PRODUCT_ID UNIT_PRICE QUANTITY
2408 1 2751 61 3
2408 2 2761 26 1
2408 3 2783 10 10Maintenant
, si vous cliquez sur le bouton de rechargement dans le navigateur, le script testCache.php n'appellera plus les fonctions getOrderFields et getOrderItems. Au lieu de cela, il lira leurs résultats à partir du cache local. Par conséquent, chaque appel getOrderFields ou getOrderItems avec order_no=2108 sera satisfait par le cache local dans les 24 heures (car lifeTime est défini sur 86 400 secondes). Notez cependant que la classe Cache_Lite_Function ne fournit pas d'API pour tester si un cache est disponible pour une fonction donnée avec des paramètres donnés. Par conséquent, il peut être un peu délicat de déterminer si l'application lit réellement le cache ou exécute toujours la fonction à chaque fois qu'elle est appelée avec les mêmes paramètres. Par exemple, dans l'exemple ci-dessus, pour garantir le bon fonctionnement du mécanisme de mise en cache, vous pouvez modifier temporairement les informations de connexion spécifiées dans le script connect.php afin qu'il ne puisse pas établir la connexion à la base de données, par exemple en spécifiant un mauvais nom d'hôte du serveur de base de données ; , puis utilisez à nouveau order_no= 2108 Exécutez le script testCache.php. Si la mise en cache fonctionne correctement, la sortie du navigateur devrait être la même qu'auparavant.
De plus, vous pouvez vérifier le répertoire de cache transmis au constructeur de la classe Cache_Lite_Function comme valeur de l'option cacheDir (/tmp dans cet exemple). Dans ce répertoire, vous trouverez deux fichiers cache que vous venez de créer avec des noms similaires à : cache_7b181b55b55aee36ad5e7bd9d5a091ec_3ad04d3024f4cd54296f75c92a359154. Notez que si vous êtes un utilisateur Windows, vous souhaiterez peut-être utiliser le répertoire %SystemDrive%temp pour enregistrer les fichiers de cache. Si tel est le cas, l'option cacheDir doit être définie sur /temp/.
Après avoir vérifié que le mécanisme de mise en cache fonctionne correctement, vous pouvez ensuite créer un PHP pour gérer les notifications de modifications reçues du serveur de base de données. "Listing 8" est le script dropResult.php. Le serveur de base de données appellera ce script en réponse aux modifications apportées aux tables ORDERS et ORDER_ITEMS.
Listing 8. Gestion des notifications de changement reçues du serveur de base de données
<?php
//Fichier : dropResults.php
require_once 'Cache/Lite/Function.php';
$options = tableau(
'cacheDir' => '/tmp/'
);
$cache = nouveau Cache_Lite_Function($options);
if (isset($_GET['order_no'])&& isset($_GET['table'])) {
si($_GET['table']=='ORDER_ITEMS'){
$cache->drop('getOrderItems', $_GET['order_no']);
}
si ($_GET['table']=='ORDERS'){
$cache->drop('getOrderFields', $_GET['order_no']);
}
}
?>
Après avoir créé le script dropResult.php, assurez-vous que l'URL spécifiée dans le gestionnaire de notification (affichée dans le listing 2) est correcte. Ensuite, connectez-vous en tant qu'OE/OE dans SQL*Plus ou un outil similaire et exécutez les instructions UPDATE qui affecteront les mêmes commandes consultées plus tôt dans cette section via le script testCache.php (ici la commande avec l'ID 2408) :
UPDATE ORDERS SET order_mode = ' direct' OÙ order_id=2408;
UPDATE ORDER_ITEMS SET quantité = 3 WHERE order_id=2408 AND line_item_id=1 ;
UPDATE ORDER_ITEMS SET quantité = 1 WHERE order_id=2408 AND line_item_id=2 ;
COMMETTRE;
En réponse à la mise à jour ci-dessus, le gestionnaire de notifications décrit plus haut dans cet article exécutera le script dropResults.php deux fois, en utilisant les URL suivantes : http://webserverhost/phpcache/dropResults.php?order_no=2408&table=ORDERS
http://webserverhost/phpcache/dropresults.php?order_no=2408&table=ORDER_ITEMS
Dans le "Listing 8", vous pouvez clairement voir que le script dropResult.php ne vide pas le cache après avoir reçu la notification de modification du serveur de base de données. Il supprime simplement les fichiers de cache contenant des données expirées. Donc, si vous vérifiez le répertoire cache maintenant, vous verrez que le fichier cache créé lors de l'exécution du script testCache.php avec order_no=2408 a disparu. Cela signifie essentiellement que la prochaine fois que testCache.php demandera des données liées à l'ID de commande 2408, il obtiendra ces données de la base de données principale au lieu du cache local.
Cette méthode peut s'avérer utile dans les situations où le jeu de résultats demandé par l'application est susceptible de changer avant que l'application ne l'utilise. Pour les besoins de l'exemple de cet article, cela signifie que les données liées à une commande spécifique peuvent changer plusieurs fois avant que testCache.php accède à cette commande. De cette façon, l'application effectue beaucoup de travail inutile en vidant son cache immédiatement après avoir reçu des notifications de modification du serveur de base de données.
Mais si vous souhaitez que le script dropResult.php vide le cache dès qu'il est informé du changement, vous pouvez appeler la méthode d'appel de l'instance Cache_Lite_Function après avoir appelé la méthode drop, en spécifiant les mêmes paramètres pour les deux appels. Dans ce cas, vous devez également vous assurer d'inclure les scripts getOrderFields.php et getOrderItems.php afin que dropResults.php puisse appeler les fonctions getOrderFields et getOrderItems pour actualiser le cache. "Listing 9" est le script dropResult.php modifié.
Listing 9. Vider le cache immédiatement après avoir reçu une notification de modification
<?php
//Fichier : dropResults.php
require_once 'Cache/Lite/Function.php';
require_once 'getOrderItems.php';
require_once 'getOrderFields.php';
$options = tableau(
'cacheDir' => '/tmp/',
'durée de vie' => 86400
);
$cache = nouveau Cache_Lite_Function($options);
if (isset($_GET['order_no'])&& isset($_GET['table'])) {
si($_GET['table']=='ORDER_ITEMS'){
$cache->drop('getOrderItems', $_GET['order_no']);
$cache->call('getOrderItems', $_GET['order_no']);
}
si ($_GET['table']=='ORDERS'){
$cache->drop('getOrderFields', $_GET['order_no']);
$cache->call('getOrderFields', $_GET['order_no']);
}
}
?>
L'approche ci-dessus peut être utile si les données stockées dans les tables ORDERS et ORDER_ITEMS changent rarement et que l'application y accède fréquemment.
Résumé
Si votre application PHP interagit avec Oracle Database 10g Release 2, vous pouvez profiter de la fonctionnalité de notification de modification de base de données, qui permet à votre application de recevoir des notifications en réponse aux modifications DML apportées à l'objet associé à la demande effectuée. Grâce à cette fonctionnalité, vous n'avez pas besoin de mettre à jour le cache de votre application pendant une période de temps spécifique. Au lieu de cela, l'opération est effectuée uniquement si le jeu de résultats de la requête enregistrée a changé.