データベース クエリの結果をキャッシュすると、スクリプトの実行時間が大幅に短縮され、データベース サーバーの負荷が最小限に抑えられることが知られています。この手法は、処理しているデータが基本的に静的である場合に非常にうまく機能します。これは、リモート データベースへの多くのデータ要求は最終的にローカル キャッシュから満たされるため、データベースに接続してクエリを実行し、結果を取得する必要がなくなるからです。
ただし、使用しているデータベースが Web サーバーとは別のコンピュータ上にある場合は、データベースの結果セットをキャッシュすることをお勧めします。ただし、状況に応じて最適なキャッシュ戦略を決定するのは難しい場合があります。たとえば、最新のデータベース結果セットを使用することが重要なアプリケーションの場合、時間トリガーのキャッシュ手法 (有効期限のタイムスタンプに達するたびにキャッシュが再生成されることを前提とするキャッシュ システムで一般的に使用されます) は満足のいく解決策ではない可能性があります。 。この場合、アプリケーションがキャッシュする必要のあるデータベース データが変更されるたびにアプリケーションに通知して、キャッシュされた期限切れのデータとデータベースの一貫性をアプリケーションが維持できるようにするメカニズムが必要です。このような場合には「データベース変更通知」を利用すると大変便利です。
データベース変更通知の概要
データベース変更通知機能の使用方法は非常に簡単です。通知のために実行する通知ハンドラ (PL/SQL ストアド プロシージャまたはクライアント OCI コールバック関数) を作成します。次に、変更通知を受け取りたいデータベース オブジェクトに対するクエリを登録します。これにより、トランザクションがその中のオブジェクトを変更してコミットするたびに通知ハンドラーが呼び出されます。通常、通知ハンドラーは、クライアント アプリケーションが応答で適切なアクションを実行できるように、変更されたテーブルの名前、行われた変更の種類、およびオプションで変更された行の行 ID をクライアント リスナーに送信します。
データベース変更通知機能がどのように動作するかを理解するために、次の例を考えてみましょう。 PHP アプリケーションが OE.ORDERS テーブルに格納されている注文と OE.ORDER_ITEMS に格納されている品目を注文するとします。発注された注文に関する情報がほとんど変更されないことを考慮すると、アプリケーションで ORDERS テーブルと ORDER_ITEMS テーブルの両方に対するクエリの結果セットをキャッシュすることができます。古いデータへのアクセスを回避するには、データベース変更通知を使用します。これにより、上記の 2 つのテーブルに格納されているデータの変更をアプリケーションに簡単に通知できます。
ORDERS テーブルおよび ORDER_ITEMS テーブルのクエリを登録して通知を受け取り、これらのテーブルに対する DML または DDL 変更に応答するには、事前に CHANGE NOTIFICATION システム権限と EXECUTE ON DBMS_CHANGENOTIFICATION 権限を OE ユーザーに付与する必要があります。これを行うには、SQL*Plus などの SQL コマンド ライン ツールから次のコマンドを実行します。
SYSDBA として接続します。
oe に変更通知を許可します。
DBMS_CHANGE_NOTIFICATION の実行を oe に許可します。
PL/SQL通知を受信するには、init.oraパラメータjob_queue_processesがゼロ以外の値に設定されていることを確認してください。または、次の ALTER SYSTEM コマンドを使用することもできます。
ALTER SYSTEM SET "job_queue_processes"=2; 次に、OE/OE として接続した後、通知ハンドラーを作成できます。ただし、その前に、通知ハンドラーによって使用されるデータベース オブジェクトを作成する必要があります。たとえば、通知ハンドラーがレジストリの変更を記録するデータベース テーブルを 1 つ以上作成することができます。次の例では、変更が発生した日時、変更されたテーブルの名前、および通知ハンドラーがクライアントに通知メッセージを正常に送信したかどうかを示すメッセージを記録する nfresults テーブルを作成します。
接続 oe/oe
CREATE TABLE nfresults (
操作日、
tblname VARCHAR2(60)、
rslt_msg VARCHAR2(100)
);
実際のシナリオでは、通知イベントや変更された行の行 ID などの情報を記録するためにさらにテーブルを作成する必要がある場合がありますが、この記事の目的では、nfresults テーブルで十分です。
UTL_HTTP を使用したクライアントへの通知の送信
1 つ以上の PL/SQL ストアド プロシージャを作成し、通知ハンドラからこれらのストアド プロシージャを呼び出すこともでき、これにより、より保守しやすく柔軟なソリューションを実現できます。たとえば、クライアントへの通知メッセージの送信を実装するストアド プロシージャを作成するとします。 「リスト 1」は、PL/SQL プロシージャ sendNotification です。このプロセスでは、UTL_HTTPPL パッケージを使用して、クライアント アプリケーションに変更通知を送信します。
リスト 1. UTL_HTTPCREATE
OR REPLACE PROCEDURE を使用してクライアントに通知を送信する sendNotification(url IN VARCHAR2,
tblname IN VARCHAR2、order_id IN VARCHAR2) は
要求 UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
err_msg VARCHAR2(100);
tbl VARCHAR(60);
始める
tbl:=SUBSTR(tblname, INSTR(tblname, '.', 1, 1)+1, 60);
始める
req := UTL_HTTP.BEGIN_REQUEST(url||order_id||'&'||'table='||tbl);
応答 := UTL_HTTP.GET_RESPONSE(req);
INSERT INTO nfresults VALUES(SYSDATE, tblname, resp.reason_phrase);
UTL_HTTP.END_RESPONSE(それぞれ);
その他の場合は例外
err_msg := SUBSTR(SQLERRM, 1, 100);
INSERT INTO nfresults VALUES(SYSDATE, tblname, err_msg);
終わり;
専念;
終わり;
/
「リスト 1」に示すように、sendNotification は、UTL_HTTP.BEGIN_REQUEST 関数によって発行された HTTP リクエストの形式でクライアントに通知メッセージを送信します。この URL には、ORDERS テーブル内の変更された行の order_id が含まれています。次に、UTL_HTTP.GET_RESPONSE を使用して、クライアントから送信された応答情報を取得します。実際、sendNotification はクライアントから返された応答全体を処理する必要はなく、RESP レコードのreason_phrase フィールドに格納されている短いメッセージ (ステータス コードを説明する) を取得するだけです。
通知ハンドラーの作成
ここで、上で説明した sendNotification プロシージャを使用してクライアントに変更通知を送信する通知ハンドラーを作成できます。 「リスト 2」の PL/SQL プロシージャ order_nf_callback を見てみましょう。
リスト 2. OE.ORDERS テーブルへの変更の通知を処理する通知ハンドラー
CREATE OR REPLACE PROCEDURE order_nf_callback (ntfnds IN SYS.CHNF$_DESC) IS
tblname VARCHAR2(60);
numtables NUMBER;
イベントの種類 NUMBER;
row_id VARCHAR2(20);
numrows NUMBER;
ord_id VARCHAR2(12);
URL VARCHAR2(256) := 'http://webserverhost/phpcache/dropResults.php?order_no=';
始める
イベントタイプ := ntfnds.イベントタイプ;
numtables := ntfnds.numtables;
IF (event_type = DBMS_CHANGE_NOTIFICATION.EVENT_OBJCHANGE) THEN
FOR i IN 1..numtables ループ
tblname := ntfnds.table_desc_array(i).table_name;
IF (bitand(ntfnds.table_desc_array(i).opflags,
DBMS_CHANGE_NOTIFICATION.ALL_ROWS) = 0) その後
numrows := ntfnds.table_desc_array(i).numrows;
それ以外
数値 :=0;
終了 IF;
IF (tblname = 'OE.ORDERS') THEN
FOR j IN 1..numrows ループ
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
SELECT order_id INTO ord_id FROM 注文 WHERE rowid = row_id;
sendNotification(url, tblname, ord_id);
ループを終了します。
終了 IF;
ループを終了します。
終了 IF;
専念;
終わり;
/
「リスト 2」に示すように、この通知ハンドラーは SYS.CHNF$_DESC オブジェクトをパラメーターとして受け取り、そのプロパティを使用して変更の詳細を取得します。この例では、この通知ハンドラーは、登録されたオブジェクトに対する DML または DDL の変更に応じてデータベースによってポストされた通知のみを処理し (つまり、通知タイプが EVENT_OBJCHANGE の場合のみ)、インスタンスの起動やイベントなどの他のデータベース イベントに関する情報は無視します。インスタンスのシャットダウン) 通知。上記のバージョン以降、ハンドラーは、OE.ORDERS テーブル内の影響を受ける各行に対して発行された変更通知を処理できるようになりました。この記事の後半の「既存の登録へのテーブルの追加」セクションで、ハンドラーに数行のコードを追加して、OE.ORDER_ITEMS テーブル内の変更された行の通知を処理できるようにします。
変更通知の登録を作成する
通知ハンドラーを作成したら、それに対するクエリ登録を作成する必要があります。この例では、登録プロセス中に OE.ORDER テーブルに対してクエリを実行し、orders_nf_callback を通知ハンドラーとして指定する必要があります。通知メッセージで ROWID レベルの粒度を有効にするには、 DBMS_CHANGE_NOTIFICATION パッケージの QOS_ROWIDS オプションを指定する必要もあります。 「リスト 3」は、orders_nf_callback 通知ハンドラのクエリ登録を作成する PL/SQL ブロックです。
リスト 3.通知ハンドラーの
クエリ登録DECLARE
を作成する
REGDS SYS.CHNF$_REG_INFO;
登録番号;
ord_id NUMBER;
qosflags NUMBER;
始める
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 注文 WHERE ROWNUM<2;
DBMS_CHANGE_NOTIFICATION.REG_END;
終わり;
/
この例では、ORDERS テーブルに対する登録を作成し、orders_nf_callback を通知ハンドラーとして使用します。ここで、DML または DDL ステートメントを使用して ORDERS テーブルを変更し、トランザクションをコミットすると、orders_nf_callback 関数が自動的に呼び出されます。たとえば、ORDERS テーブルに対して次の UPDATE ステートメントを実行し、トランザクションをコミットするとします。
UPDATE ORDERS SET order_mode = 'direct' WHERE order_id=2421;
注文を更新します。 order_mode = 'direct' WHERE order_id=2422;
専念;
上記のトランザクションに応答してデータベースが通知をポストしたことを確認するには、nfresults テーブルをチェックします。
SELECT TO_CHAR(operdate, 'dd-mon-yy hh:mi:ss') operdate,
tblname、rslt_msg FROM nfresults;
結果は次のようになります:
OPERDATE TBLNAME RSLT_MSG
--------------------- ---------- --------
02-mar-06 04:31:28 OE.ORDERS が見つかりません
02-mar-06 04:31:29 OE.ORDERS が見つかりません
上記の結果から、orders_nf_callback はすでに動作していますが、クライアント スクリプトが見つからないことは明らかです。この例では、URL で指定された DropResults.php スクリプトを作成していないため、これは予期せぬことではありません。 dropResults.php スクリプトの手順については、この記事で後述する「クライアントの構築」セクションを参照してください。
既存の登録へのテーブルの追加
前のセクションでは、変更通知サービスを使用して、登録オブジェクト (上の例では ORDERS テーブル) が変更されたときにデータベースに通知させる方法を示しました。ただし、パフォーマンスの観点から、クライアント アプリケーションは、ORDERS テーブル自体ではなく、ORDER_ITEMS テーブルのクエリ結果セットをキャッシュすることを好む場合があります。これは、注文にアクセスするたびに ORDERS テーブルから 1 行だけを取得する必要があるためです。同時に複数の行を ORDER_ITEMS テーブルから取得する必要があります。実際には、注文には数十、場合によっては数百の項目が含まれる場合があります。
ORDERS テーブルに対してクエリをすでに登録しているため、ORDER_ITEMS テーブルに対してクエリを登録するための登録を作成する必要はありません。代わりに、既存の登録を使用できます。これを行うには、まず既存の登録の ID を取得する必要があります。これを行うには、次のクエリを実行します。
SELECT regid, table_name FROMuser_change_notification_regs
; 結果は次のようになります。
----- --------------
241 OE.注文
登録 ID を取得した後、次のように DBMS_CHANGE_NOTIFICATION.ENABLE_REG 関数を使用して、新しいオブジェクトを登録に追加できます。
DECLARE
ord_id NUMBER;
始める
DBMS_CHANGE_NOTIFICATION.ENABLE_REG(241);
SELECT order_id INTO ord_id FROM order_items WHERE ROWNUM < 2;
DBMS_CHANGE_NOTIFICATION.REG_END;
終わり;
/
終わり!今後、データベースは、ORDERS および ORDER_ITEMS に対する変更に応じて通知を生成し、orders_nf_callback プロシージャを呼び出して通知を処理します。したがって、次の手順では、ORDER_ITEMS テーブルの DML 操作によって生成された通知を処理できるように、orders_nf_callback を編集します。ただし、orders_nf_callback プロシージャを再作成する前に、更新プロセス中に参照される次のテーブル タイプを作成する必要があります。
CREATE TYPE rdesc_tab AS TABLE OF SYS.CHNF$_RDESC; 次に、リスト 2 の次の行の後に戻ります。コード:
IF (tblname = 'OE.ORDERS') THEN
FOR j IN 1..numrows ループ
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
SELECT order_id INTO ord_id FROM 注文 WHERE rowid = row_id;
sendNotification(url, tblname, ord_id);
ループを終了します。
終了 IF;
次のコードを挿入します:
IF (tblname = 'OE.ORDER_ITEMS') THEN
FOR rec IN (SELECT DISTINCT(o.order_id) o_id FROM
TABLE(CAST(ntfnds.table_desc_array(i).row_desc_array AS rdesc_tab)) t,
注文 o、order_items d WHERE t.row_id = d.rowid AND d.order_id=o.order_id)
ループ
sendNotification(url、tblname、rec.o_id);
ループを終了します。
終了 IF;
order_nf_callback を再作成した後、それが正しく動作することをテストする必要があります。
ORDER_ITEMS
テーブルに対して次の UPDATE ステートメントを実行し、トランザクションをコミットします。
UPDATE ORDER_ITEMS SET 数量 = 160 WHERE order_id=2421 AND line_item_id=2;
専念;
次に、次のように nfresults テーブルを確認します。
SELECT TO_CHAR(operdate, 'dd-mon-yy hh:mi:ss') operdate,
rslt_msg FROM nfresults WHERE tblname = 'OE.ORDER_ITEMS'; 出力は次のようになります。
OPERDATE RSLT_MSG
-----------------------------------
03-mar-06 12:32:27 見つかりませんでした
ORDER_ITEMS テーブルの 2 行を更新したのに、なぜ nfresults テーブルに 1 行だけが挿入されたのか疑問に思われるかもしれません。実際、更新された 2 つの行は同じ order_id を持っています。つまり、同じ注文に属しています。ここでは、クライアント アプリケーションが 1 つのステートメントを使用して注文のすべての明細を選択すると想定しているため、注文のどの明細が変更されたかを正確に知る必要はありません。代わりに、クライアントは、少なくとも 1 つの明細項目が変更、削除、または挿入された注文 ID を知る必要があります。
クライアントの構築
ORDERS テーブルと ORDER_ITEMS テーブルの登録を作成したので、これらのテーブルに格納されている注文と明細項目にアクセスするクライアント アプリケーションによって変更通知がどのように使用されるかを見てみましょう。これを行うには、上記のテーブルに対するクエリの結果をキャッシュし、これらのテーブルへの変更に関する通知 (データベース サーバーから受信する) に応じて適切なアクションを実行する PHP アプリケーションを構築できます。簡単な方法は、キャッシュ データを最新の状態に保つための信頼できるメカニズムを提供する PEAR::Cache_Lite パッケージを使用することです。特に、Cache_Lite_Function クラス (PEAR::Cache_Lite パッケージの一部) を使用すると、関数呼び出しをキャッシュできます。
たとえば、データベース接続を確立し、データベースに対して選択ステートメントを実行し、検索結果を取得し、最後に結果を配列として返すというタスクを実行する関数を作成できます。その後、Cache_Lite_Function インスタンスの call メソッドを通じて関数から返された結果配列をキャッシュし、バックエンド データベースではなくローカル キャッシュから読み取れるようにすることで、アプリケーションのパフォーマンスを大幅に向上させることができます。その後、キャッシュされたデータの変更が通知されたときに、Cache_Lite_Function インスタンスのdrop メソッドを使用して、キャッシュ内の期限切れのデータを削除します。
この記事の例に戻ると、アプリケーションがデータベースと対話するために 2 つの関数を作成するとよいでしょう。最初の関数は ORDERS テーブルをクエリして、指定された ID を持つ注文を返し、もう 1 つの関数は ORDER_ITEMS をクエリします。 table and return この注文の項目を返します。 「リスト 4」は、getOrderFields 関数を含む getOrderFields.php スクリプトを示しています。この関数は注文 ID を受け取り、取得した注文のフィールドの一部を含む連想配列を返します。
リスト 4. 指定された順序のフィールドを取得する
<?php
//ファイル:getOrderFields.php
require_once 'connect.php';
関数 getOrderFields($order_no) {
if (!$rsConnection = GetConnection()){
false を返します。
}
$strSQL = "SELECT TO_CHAR(ORDER_DATE) ORDER_DATE、CUSTOMER_ID、
order_id =:order_no"; の場合の注文からの ORDER_TOTAL
$rsStatement = oci_parse($rsConnection,$strSQL);
oci_bind_by_name($rsStatement, ":order_no", $order_no, 12);
if (!oci_execute($rsStatement)) {
$err = oci_error();
print $err['メッセージ'];
trigger_error('クエリが失敗しました:' . $err['メッセージ']);
false を返します。
}
$results = oci_fetch_assoc($rsStatement);
$result を返します。
}
?>
「リスト 5」は getOrderItems.php スクリプトです。スクリプトには getOrderItems 関数が含まれており、この関数は注文 ID を受け取り、注文の品目を表す行を含む 2 次元配列を返します。
リスト 5. 指定された順序の項目を取得する
<?php
//ファイル:getOrderItems.php
require_once 'connect.php';
関数 getOrderItems($order_no) {
if (!$rsConnection = GetConnection()){
false を返します。
}
$strSQL = "SELECT * FROM ORDER_ITEMS WHERE
order_id =:order_no ORDER BY line_item_id";
$rsStatement = oci_parse($rsConnection,$strSQL);
oci_bind_by_name($rsStatement, ":order_no", $order_no, 12);
if (!oci_execute($rsStatement)) {
$err = oci_error();
trigger_error('クエリが失敗しました:' . $err['メッセージ']);
false を返します。
}
$nrows = oci_fetch_all($rsStatement, $results);
配列を返します ($nrows, $results);
}
?>
上記の関数はどちらも connect.php スクリプトを必要とすることに注意してください。このスクリプトには、データベース接続を返す GetConnection 関数が含まれている必要があります。リスト 6 は connect.php スクリプトです。
リスト 6. データベース接続の取得
<?php
// ファイル:connect.php
関数 GetConnection() {
$dbHost = "データベースサーバーホスト";
$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)) {
$err = oci_error();
trigger_error('接続に失敗しました ' .$err['メッセージ']);
false を返します。
}
$dbConn を返します。
}
?>
データベースとの通信に必要な関数をすべて作成したので、Cache_Lite_Function クラスがどのように機能するかを見てみましょう。リスト 7 は、Cache_Lite_Function クラスを使用して上記の関数の結果をキャッシュする testCache.php スクリプトです。
PEAR::Cache_Lite を使用した
<?php
のキャッシュ
// ファイル:testCache.php
require_once 'getOrderItems.php';
require_once 'getOrderFields.php';
require_once 'Cache/Lite/Function.php'
$options = array(
'cacheDir' => '/tmp/',
'lifeTime' => 86400
);
if (!isset($_GET['order_no'])) {
die('order_no パラメータは必要です');
order_no
=$_GET['order_no'];
$cache = 新しい Cache_Lite_Function($options);
if ($orderfields = $cache->call('getOrderFields', $order_no)){
print "<h3>ORDER #$order_no</h3>n";
print "<テーブル>";
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>";
「</table>」を印刷します。
} それ以外 {
print "注文フィールドの取得中に問題が発生しました!n";
$cache->drop('getOrderFields', $order_no);
if (list($nrows, $orderitems) = $cache->call('getOrderItems', $order_no))
{
//print "<h3>LINE ITEMS IN ORDER #$order_no</h3>";
print "<table border=1>";
"<tr>n" を印刷します。
while (list($key, $value) = each($orderitems)) {
print "<th>$key</th>n";
}
print "</tr>n";
for ($i = 0; $i < $nrows; $i++) {
「<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>";
「</tr>」を印刷します。
}
"</table>" を印刷します。
} それ以外 {
print "注文品目の取得中に問題が発生しました";
$cache->drop('getOrderItems', $order_no);
}
?>
「リスト 7」の testCache.php スクリプトは、order_no URL パラメーター (OE.ORDER テーブルに保管されている注文 ID を表す) を使用して呼び出す必要があります。たとえば、ID 2408 の注文に関連する情報を取得するには、次の URL をブラウザに入力します。
http://webserverhost/phpcache/testCache.php?order_no=2408その結果、ブラウザは次の出力を生成します。 :
注文 #2408
日付: 99 年 6 月 29 日 06.59.31.333617 AM
CUST_ID: 166
合計: 309
ORDER_ID LINE_ITEM_ID PRODUCT_ID UNIT_PRICE 数量
2408 1 2751 61 3
2408 2 2761 26 1
2408 3 2783 10 10ここで
、ブラウザの再読み込みボタンをクリックすると、testCache.php スクリプトは getOrderFields 関数と getOrderItems 関数を再度呼び出すことはありません。代わりに、ローカル キャッシュから結果を読み取ります。したがって、order_no=2108 を指定したすべての getOrderFields または getOrderItems 呼び出しは、今から 24 時間以内にローカル キャッシュによって満たされます (lifeTime が 86400 秒に設定されているため)。ただし、Cache_Lite_Function クラスは、指定されたパラメーターを持つ指定された関数でキャッシュが使用できるかどうかをテストする API を提供しないことに注意してください。したがって、アプリケーションが実際にキャッシュを読み取るのか、それとも同じパラメーターで呼び出されるたびに関数を実行するのかを判断するのは少し難しい場合があります。たとえば、上記の例では、キャッシュ メカニズムが正しく動作することを確認するために、connect.php スクリプトで指定された接続情報を一時的に変更して、データベース接続を確立できないようにすることができます。たとえば、間違ったデータベース サーバーのホスト名を指定します。 2108 testCache.php スクリプトを実行します。キャッシュが適切に機能している場合、ブラウザの出力は以前と同じになるはずです。
さらに、cache_Lite_Function クラスのコンストラクターに、cacheDir オプション (この例では /tmp) の値として渡されるキャッシュ ディレクトリを確認できます。そのディレクトリには、cache_7b181b55b55aee36ad5e7bd9d5a091ec_3ad04d3024f4cd54296f75c92a359154 のような名前で作成した 2 つのキャッシュ ファイルがあります。 Windows ユーザーの場合は、%SystemDrive%temp ディレクトリを使用してキャッシュ ファイルを保存することをお勧めします。その場合、cacheDir オプションを /temp/ に設定する必要があります。
キャッシュ メカニズムが適切に動作していることを確認したら、データベース サーバーから受信した変更通知を処理するための PHP を作成できます。 「リスト 8」は、dropResult.php スクリプトです。データベース サーバーは、ORDERS テーブルと ORDER_ITEMS テーブルへの変更に応じてこのスクリプトを呼び出します。
リスト 8. データベース サーバー
<?php
から受信した変更通知の処理
// ファイル:dropResults.php
require_once 'Cache/Lite/Function.php'
$options = array(
'cacheDir' => '/tmp/'
);
$cache = 新しい Cache_Lite_Function($options);
if (isset($_GET['order_no'])&& isset($_GET['table'])) {
if($_GET['テーブル']=='ORDER_ITEMS'){
$cache->drop('getOrderItems', $_GET['order_no']);
}
if ($_GET['テーブル']=='ORDERS'){
$cache->drop('getOrderFields', $_GET['order_no']);
}
}
?>
dropResult.php スクリプトを作成した後、通知ハンドラー (リスト 2 を参照) で指定された URL が正しいことを確認してください。次に、SQL*Plus または同様のツールで OE/OE として接続し、このセクションの前半で testCache.php スクリプトを介してアクセスしたのと同じ注文 (ここでは ID 2408 の注文) に影響を与える UPDATE ステートメントを実行します。
UPDATE ORDERS SET order_mode = ' direct' WHERE order_id=2408;
UPDATE ORDER_ITEMS SET 数量 = 3 WHERE order_id=2408 AND line_item_id=1;
UPDATE ORDER_ITEMS SET 数量 = 1 WHERE order_id=2408 AND line_item_id=2;
専念;
上記の更新に応じて、この記事の前半で説明した通知ハンドラーは、次の URL を使用して、dropResults.php スクリプトを 2 回実行します。 http://webserverhost/phpcache/dropResults.php?order_no=2408&table=ORDERS
http://webserverhost/phpcache/dropresults.php?order_no=2408&table=ORDER_ITEMS
「リスト 8」からは、dropResult.php スクリプトがデータベース サーバーから変更通知を受信した後にキャッシュをフラッシュしていないことが明確にわかります。期限切れのデータを含むキャッシュ ファイルを削除するだけです。ここでキャッシュ ディレクトリを確認すると、order_no=2408 を指定して testCache.php スクリプトを実行したときに作成されたキャッシュ ファイルが消えていることがわかります。これが本質的に意味するのは、次回 testCache.php が注文 ID 2408 に関連するデータをリクエストするときに、ローカル キャッシュではなくバックエンド データベースからそのデータを取得するということです。
このメソッドは、アプリケーションによって要求された結果セットがアプリケーションで使用される前に変更される可能性がある状況で役立つ場合があります。この記事の例では、これは、testCache.php がその注文にアクセスする前に、特定の注文に関連するデータが複数回変更される可能性があることを意味します。このように、アプリケーションはデータベース サーバーから変更通知を受信した直後にキャッシュをフラッシュすることで、多くの不必要な作業を実行します。
ただし、dropResult.php スクリプトで変更が通知されたらすぐにキャッシュをフラッシュしたい場合は、drop メソッドを呼び出した後に Cache_Lite_Function インスタンスの call メソッドを呼び出し、両方の呼び出しに同じパラメーターを指定します。この場合、dropResults.php が getOrderFields 関数と getOrderItems 関数を呼び出してキャッシュを更新できるように、getOrderFields.php スクリプトと getOrderItems.php スクリプトも必ず含める必要があります。 「リスト 9」は、変更されたdropResult.phpスクリプトです。
リスト 9. 変更通知を受け取った直後にキャッシュをフラッシュする
<?php
// ファイル:dropResults.php
require_once 'Cache/Lite/Function.php';
require_once 'getOrderItems.php';
require_once 'getOrderFields.php'
$options = array(
'cacheDir' => '/tmp/',
'lifeTime' => 86400
);
$cache = 新しい Cache_Lite_Function($options);
if (isset($_GET['order_no'])&& isset($_GET['table'])) {
if($_GET['テーブル']=='ORDER_ITEMS'){
$cache->drop('getOrderItems', $_GET['order_no']);
$cache->call('getOrderItems', $_GET['order_no']);
}
if ($_GET['テーブル']=='ORDERS'){
$cache->drop('getOrderFields', $_GET['order_no']);
$cache->call('getOrderFields', $_GET['order_no']);
}
}
?>
上記のアプローチは、ORDERS テーブルと ORDER_ITEMS テーブルに格納されているデータがほとんど変更されず、アプリケーションが頻繁にアクセスする場合に便利です。
概要
PHP アプリケーションが Oracle Database 10g Release 2 と対話する場合は、データベース変更通知機能を利用できます。これにより、アプリケーションは、行われたリクエストに関連付けられたオブジェクトに対する DML 変更に応じて通知を受け取ることができます。この機能を使用すると、特定の期間中にアプリケーションのキャッシュを更新する必要がなくなります。代わりに、登録されたクエリの結果セットが変更された場合にのみ操作が実行されます。