国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
ORDER #$order_no
LINE ITEMS IN ORDER #$order_no
首頁 php教程 php手冊 通過緩存數據庫結果提高PHP性能的原理介紹

通過緩存數據庫結果提高PHP性能的原理介紹

Jun 13, 2016 am 11:58 AM
php web 不同 介紹 原理 性能 提高 數據庫 服務器 實際的 結果 緩存 通過

但當您使用的數據庫與 Web 服務器位于不同的計算機上時,緩存數據庫結果集通常是一個不錯的方法。不過,根據您的情況確定最佳的緩存策略卻是一個難題。例如,對于使用最新數據庫結果集比較重要的應用程序而言,時間觸發(fā)的緩存方法(緩存系統常用的方法,它假設每次到達失效時間戳記時就重新生成緩存)可能并不是一個令人滿意的解決方案。這種情況下,您需要采用一種機制,每當應用程序需要緩存的數據庫數據發(fā)生更改時,該機制將通知該應用程序,以便該應用程序將緩存的過期數據與數據庫保持一致。這種情況下使用“數據庫更改通知”(一個新的 Oracle 數據庫 10g 第 2 版特性)將非常方便。

  “數據庫更改通知”入門

  “數據庫更改通知”特性的用法非常簡單:創(chuàng)建一個針對通知執(zhí)行的通知處理程序 – 一個 PL/SQL 存儲過程或客戶端 OCI 回調函數。然后,針對要接收其更改通知的數據庫對象注冊一個查詢,以便每當事務更改其中的任何對象并提交時調用通知處理程序。通常情況下,通知處理程序將被修改的表的名稱、所做更改的類型以及所更改行的行 ID(可選)發(fā)送給客戶端監(jiān)聽程序,以便客戶端應用程序可以在響應中執(zhí)行相應的處理。

  為了了解“數據庫更改通知”特性的作用方式,請考慮以下示例。假設您的 PHP 應用程序訪問 OE.ORDERS 表中存儲的訂單以及 OE.ORDER_ITEMS 中存儲的訂單項。鑒于很少更改已下訂單的信息,您可能希望應用程序同時緩存針對 ORDERS 和 ORDER_ITEMS 表的查詢結果集。要避免訪問過期數據,您可以使用“數據庫更改通知”,它可讓您的應用程序方便地獲知以上兩個表中所存儲數據的更改。

  您必須先將 CHANGE NOTIFICATION 系統權限以及 EXECUTE ON DBMS_CHANGENOTIFICATION 權限授予 OE 用戶,才能注冊對 ORDERS 和 ORDER_ITEMS 表的查詢,以便接收通知和響應對這兩個表所做的 DML 或 DDL 更改。為此,可以從 SQL 命令行工具(如 SQL*Plus)中執(zhí)行下列命令。

CONNECT / AS SYSDBA;
GRANT CHANGE NOTIFICATION TO oe;
GRANT EXECUTE ON DBMS_CHANGE_NOTIFICATION TO oe;
  確保將 init.ora 參數 job_queue_processes 設置為非零值,以便接收 PL/SQL 通知。或者,您也可以使用下面的 ALTER SYSTEM 命令:

ALTER SYSTEM SET "job_queue_processes"=2;  然后,在以 OE/OE 連接后,您可以創(chuàng)建一個通知處理程序。但首先,您必須創(chuàng)建將由通知處理程序使用的數據庫對象。例如,您可能需要創(chuàng)建一個或多個數據庫表,以便通知處理程序將注冊表的更改記錄到其中。在以下示例中,您將創(chuàng)建 nfresults 表來記錄以下信息:更改發(fā)生的日期和時間、被修改的表的名稱以及一個消息(說明通知處理程序是否成功地將通知消息發(fā)送給客戶端)。

CONNECT oe/oe;
CREATE TABLE nfresults (
operdate DATE,
tblname VARCHAR2(60),
rslt_msg VARCHAR2(100)
);
  在實際情況中,您可能需要創(chuàng)建更多表來記錄通知事件以及所更改行的行 ID 等信息,但就本文而言,nfresults 表完全可以滿足需要。
  使用 UTL_HTTP 向客戶端發(fā)送通知
  您可能還要創(chuàng)建一個或多個 PL/SQL 存儲過程,并從通知處理程序中調用這些存儲過程,從而實現一個更具可維護性和靈活性的解決方案。例如,您可能要創(chuàng)建一個實現將通知消息發(fā)送給客戶端的存儲過程。“清單 1”是 PL/SQL 過程 sendNotification。該過程使用 UTL_HTTPPL 程序包向客戶端應用程序發(fā)送更改通知。

  清單 1. 使用 UTL_HTTP 向客戶端發(fā)送通知

復制代碼 代碼如下:


CREATE OR REPLACE PROCEDURE sendNotification(url IN VARCHAR2,
tblname IN VARCHAR2, order_id IN VARCHAR2) IS
req UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
err_msg VARCHAR2(100);
tbl VARCHAR(60);
BEGIN
tbl:=SUBSTR(tblname, INSTR(tblname, '.', 1, 1)+1, 60);
BEGIN
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 WHEN OTHERS THEN
err_msg := SUBSTR(SQLERRM, 1, 100);
INSERT INTO nfresults VALUES(SYSDATE, tblname, err_msg);
END;
COMMIT;
END;
/



  如“清單 1”所示,sendNotification 以 UTL_HTTP.BEGIN_REQUEST 函數發(fā)出的 HTTP 請求的形式向客戶端發(fā)送通知消息。此 URL 包含 ORDERS 表中已更改行的 order_id。然后,它使用 UTL_HTTP.GET_RESPONSE 獲取客戶端發(fā)出的響應信息。實際上,sendNotification 并不需要處理客戶端返回的整個響應,而是只獲取一個在 RESP 記錄的 reason_phrase 字段中存儲的簡短消息(描述狀態(tài)代碼)。

  創(chuàng)建通知處理程序

  現在,您可以創(chuàng)建一個通知處理程序,它將借助于上面介紹的 sendNotification 過程向客戶端發(fā)送更改通知。來看一看“清單 2”中的 PL/SQL 過程 orders_nf_callback。

  清單 2. 處理對 OE.ORDERS 表所做更改的通知的通知處理程序

復制代碼 代碼如下:


CREATE OR REPLACE PROCEDURE orders_nf_callback (ntfnds IN SYS.CHNF$_DESC) IS
tblname VARCHAR2(60);
numtables NUMBER;
event_type NUMBER;
row_id VARCHAR2(20);
numrows NUMBER;
ord_id VARCHAR2(12);
url VARCHAR2(256) := 'http://webserverhost/phpcache/dropResults.php?order_no=';
BEGIN
event_type := ntfnds.event_type;
numtables := ntfnds.numtables;
IF (event_type = DBMS_CHANGE_NOTIFICATION.EVENT_OBJCHANGE) THEN
FOR i IN 1..numtables LOOP
tblname := ntfnds.table_desc_array(i).table_name;
IF (bitand(ntfnds.table_desc_array(i).opflags,
DBMS_CHANGE_NOTIFICATION.ALL_ROWS) = 0) THEN
numrows := ntfnds.table_desc_array(i).numrows;
ELSE
numrows :=0;
END IF;
IF (tblname = 'OE.ORDERS') THEN
FOR j IN 1..numrows LOOP
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
SELECT order_id INTO ord_id FROM orders WHERE rowid = row_id;
sendNotification(url, tblname, ord_id);
END LOOP;
END IF;
END LOOP;
END IF;
COMMIT;
END;
/



  如“清單 2”所示,此通知處理程序將 SYS.CHNF$_DESC 對象用作參數,然后使用它的屬性獲取該更改的詳細信息。在該示例中,此通知處理程序將只處理數據庫為響應對注冊對象進行的 DML 或 DDL 更改(也就是說,僅當通知類型為 EVENT_OBJCHANGE 時)而發(fā)布的通知,并忽略有關其他數據庫事件(如實例啟動或實例關閉)的通知。從以上版本開始,處理程序可以處理針對 OE.ORDERS 表中每個受影響的行發(fā)出的更改通知。在本文后面的“將表添加到現有注冊”部分中,您將向處理程序中添加幾行代碼,以便它可以處理針對 OE.ORDER_ITEMS 表中被修改的行發(fā)出的通知。

  為更改通知創(chuàng)建注冊
  創(chuàng)建通知處理程序后,必須為其創(chuàng)建一個查詢注冊。對于本示例而言,您必須在注冊過程中對 OE.ORDER 表執(zhí)行查詢并將 orders_nf_callback 指定為通知處理程序。您還需要在 DBMS_CHANGE_NOTIFICATION 程序包中指定 QOS_ROWIDS 選項,以便在通知消息中啟用 ROWID 級別的粒度?!扒鍐?3”是一個 PL/SQL 塊,它為 orders_nf_callback 通知處理程序創(chuàng)建查詢注冊。

  清單 3. 為通知處理程序創(chuàng)建查詢注冊

復制代碼 代碼如下:


DECLARE
REGDS SYS.CHNF$_REG_INFO;
regid NUMBER;
ord_id NUMBER;
qosflags NUMBER;
BEGIN
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 orders WHERE ROWNUMDBMS_CHANGE_NOTIFICATION.REG_END;
END;
/


  本示例針對 ORDERS 表創(chuàng)建了一個注冊,并將 orders_nf_callback 用作通知處理程序?,F在,如果您使用 DML 或 DDL 語句修改 ORDERS 表并提交事務,則將自動調用 orders_nf_callback 函數。例如,您可能針對 ORDERS 表執(zhí)行下列 UPDATE 語句并提交該事務:

UPDATE ORDERS SET order_mode = 'direct' WHERE order_id=2421;
UPDATE ORDERS SET order_mode = 'direct' WHERE order_id=2422;
COMMIT;

  要確保數據庫發(fā)布了通知來響應以上事務,您可以檢查 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 Not Found
02-mar-06 04:31:29 OE.ORDERS Not Found
  從以上結果中可以清楚地看到,orders_nf_callback 已經正常工作,但未找到客戶端腳本。在該示例中出現這種情況并不意外,這是因為您并未創(chuàng)建 URL 中指定的 dropResults.php 腳本。
  將表添加到現有注冊
  前一部分介紹了如何使用更改通知服務使數據庫在注冊對象(在以上示例中為 ORDERS 表)發(fā)生更改時發(fā)出通知。但從性能角度而言,客戶端應用程序可能更希望緩存 ORDER_ITEMS 表而非 ORDERS 表本身的查詢結果集,這是因為它在每次訪問訂單時,不得不從 ORDERS 表中只檢索一行,但同時必須從 ORDER_ITEMS 表中檢索多個行。在實際情況中,訂單可能包含數十個甚至數百個訂單項。
  由于您已經對 ORDERS 表注冊了查詢,因此不必再創(chuàng)建一個注冊來注冊對 ORDER_ITEMS 表的查詢了。相反,您可以使用現有注冊。為此,您首先需要檢索現有注冊的 ID。可以執(zhí)行以下查詢來完成此工作:

SELECT regid, table_name FROM user_change_notification_regs;  結果可能如下所示:

REGID TABLE_NAME
----- --------------
241 OE.ORDERS
  獲取注冊 ID 后,可以使用 DBMS_CHANGE_NOTIFICATION.ENABLE_REG 函數將一個新對象添加到該注冊,如下所示:

復制代碼 代碼如下:


DECLARE
ord_id NUMBER;
BEGIN
DBMS_CHANGE_NOTIFICATION.ENABLE_REG(241);
SELECT order_id INTO ord_id FROM order_items WHERE ROWNUM DBMS_CHANGE_NOTIFICATION.REG_END;
END;


  完成了!從現在開始,數據庫將生成一個通知來響應對 ORDERS 和 ORDER_ITEMS 所做的任何更改,并調用 orders_nf_callback 過程來處理通知。因此,下一步就是編輯 orders_nf_callback,以便它可以處理因對 ORDER_ITEMS 表執(zhí)行 DML 操作而生成的通知。但在重新創(chuàng)建 orders_nf_callback 過程之前,您需要創(chuàng)建以下將在更新過程中引用的表類型:

CREATE TYPE rdesc_tab AS TABLE OF SYS.CHNF$_RDESC;  然后,返回清單,在以下代碼行之后:

復制代碼 代碼如下:


IF (tblname = 'OE.ORDERS') THEN
FOR j IN 1..numrows LOOP
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
SELECT order_id INTO ord_id FROM orders WHERE rowid = row_id;
sendNotification(url, tblname, ord_id);
END LOOP;
END 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,
orders o, order_items d WHERE t.row_id = d.rowid AND d.order_id=o.order_id)
LOOP
sendNotification(url, tblname, rec.o_id);
END LOOP;
END IF;


  重新創(chuàng)建 orders_nf_callback 后,您需要測試它能否正常工作。為此,您可以針對 ORDER_ITEMS 表執(zhí)行下列 UPDATE 語句并提交該事務:

UPDATE ORDER_ITEMS SET quantity = 160 WHERE order_id=2421 AND line_item_id=1;
UPDATE ORDER_ITEMS SET quantity = 160 WHERE order_id=2421 AND line_item_id=2;
COMMIT;
  然后,檢查 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 Not Found
  您可能很奇怪為什么只向 nfresults 表中插入了一行 – 畢竟您更新了 ORDER_ITEMS 表中的兩行。實際上,這兩個更新了的行具有相同的 order_id – 即它們屬于同一訂單。此處,我們假設客戶端應用程序將使用一個語句選擇訂單的所有訂單項,因此它并不需要確切知道已經更改了某個訂單的哪些訂單項。相反,客戶端需要知道其中至少修改、刪除或插入了一個訂單項的訂單 ID。
  構建客戶端
  現在,您已經針對 ORDERS 和 ORDER_ITEMS 表創(chuàng)建了注冊,下面我們將了解一下訪問這些表中存儲的訂單及其訂單項的客戶端應用程序如何使用更改通知。為此,您可以構建一個 PHP 應用程序,它將緩存針對以上表的查詢結果,并采取相應的操作來響應有關對這些表所做更改的通知(從數據庫服務器中收到這些通知)。一個簡單的方法是使用 PEAR::Cache_Lite 程序包,它為您提供了一個可靠的機制來使緩存數據保持最新狀態(tài)。尤其是,您可以使用 Cache_Lite_Function 類(PEAR::Cache_Lite 程序包的一部分),通過該類您可以緩存函數調用。
  例如,您可以創(chuàng)建一個函數來執(zhí)行下列任務:建立數據庫連接、針對該數據庫執(zhí)行 select 語句、獲取檢索結果并最終以數組形式返回結果。然后,您可以通過 Cache_Lite_Function 實例的 call 方法緩存由該函數返回的結果數組,以便可以從本地緩存而不是從后端數據庫讀取這些數組,這樣可以顯著提高應用程序的性能。然后,在收到緩存數據更改的通知時,您將使用 Cache_Lite_Function 實例的 drop 方法刪除緩存中的過期數據。
  回過頭來看看本文的示例,您可能要創(chuàng)建兩個函數,用于應用程序與數據庫交互:第一個函數將查詢 ORDERS 表并返回具有指定 ID 的訂單,而另一個函數將查詢 ORDER_ITEMS 表并返回該訂單的訂單項?!扒鍐?4”顯示了包含 getOrderFields 函數(該函數接受訂單 ID 并返回一個包含所檢索到訂單的某些字段的關聯數組)的 getOrderFields.php 腳本。

  清單 4. 獲取指定訂單的字段

復制代碼 代碼如下:


//File:getOrderFields.php
require_once 'connect.php';
function getOrderFields($order_no) {
if (!$rsConnection = GetConnection()){
return false;
}
$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);
if (!oci_execute($rsStatement)) {
$err = oci_error();
print $err['message'];
trigger_error('Query failed:' . $err['message']);
return false;
}
$results = oci_fetch_assoc($rsStatement);
return $results;
}
?>


  “清單 5”是 getOrderItems.php 腳本。該腳本包含 getOrderItems 函數,該函數接受訂單 ID 并返回一個二維數組,該數組包含表示訂單的訂單項的行。

  清單 5. 獲取指定訂單的訂單項

復制代碼 代碼如下:


//File:getOrderItems.php
require_once 'connect.php';
function getOrderItems($order_no) {
if (!$rsConnection = GetConnection()){
return 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('Query failed:' . $err['message']);
return false;
}
$nrows = oci_fetch_all($rsStatement, $results);
return array ($nrows, $results);
}
?>


  注意,以上兩個函數都需要 connect.php 腳本,該腳本應包含返回數據庫連接的 GetConnection 函數。清單 6 就是 connect.php 腳本:

  清單 6. 獲取數據庫連接

復制代碼 代碼如下:


//File:connect.php
function GetConnection() {
$dbHost = "dbserverhost";
$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('Failed to connect ' .$err['message']);
return false;
}
return $dbConn;
}
?>


  現在,您已經創(chuàng)建了與數據庫通信所需的所有函數,下面我們將了解一下 Cache_Lite_Function 類的工作方式。清單 7 是 testCache.php 腳本,該腳本使用 Cache_Lite_Function 類緩存以上函數的結果。

  清單 7. 使用 PEAR::Cache_Lite 緩存

復制代碼 代碼如下:


//File: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('The order_no parameter is required');
}
$order_no=$_GET['order_no'];
$cache = new Cache_Lite_Function($options);
if ($orderfields = $cache->call('getOrderFields', $order_no)){
print "

ORDER #$order_no

\n";
print "";
print "";
print "";
print "";
print "
DATE: ".$orderfields['ORDER_DATE']."
CUST_ID: ".$orderfields['CUSTOMER_ID']."
TOTAL: ".$orderfields['ORDER_TOTAL']."
";
} else {
print "Some problem occurred while getting order fields!\n";
$cache->drop('getOrderFields', $order_no);
}
if (list($nrows, $orderitems) = $cache->call('getOrderItems', $order_no)){
//print "

LINE ITEMS IN ORDER #$order_no

";
print "";
print "\n";
while (list($key, $value) = each($orderitems)) {
print "\n";
}
print "\n";
for ($i = 0; $i print "";
print "";
print "";
print "";
print "";
print "";
print "";
}
print "
$key
".$orderitems['ORDER_ID'][$i]."".$orderitems['LINE_ITEM_ID'][$i]."".$orderitems['PRODUCT_ID'][$i]."".$orderitems['UNIT_PRICE'][$i]."".$orderitems['QUANTITY'][$i]."
";
} else {
print "Some problem occurred while getting order line items";
$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  結果,瀏覽器將生成以下輸出:
  ORDER #2408

DATE: 29-JUN-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 10

  現在,如果您單擊瀏覽器中的 reload 按鈕,testCache.php 腳本將不會再次調用 getOrderFields 和 getOrderItems 函數。相反,它將從本地緩存中讀取它們的結果。因此,從現在起的 24 小時(因為 lifeTime 設置為 86400 秒)以內,本地緩存即可滿足使用 order_no=2108 的每個 getOrderFields 或 getOrderItems 調用的需要。但請注意,Cache_Lite_Function 類未提供 API 來測試具有給定參數的給定函數是否存在可用緩存。因此,要確定每次使用相同參數調用函數時應用程序是實際上讀取緩存還是仍執(zhí)行該函數可能有點棘手。例如,在以上示例中,要確保緩存機制正常工作,您可以臨時更改 connect.php 腳本中指定的連接信息,以便它無法建立數據庫連接;比如指定一個錯誤的數據庫服務器主機名稱,然后再次使用 order_no=2108 運行 testCache.php 腳本。如果緩存正常工作,瀏覽器的輸出應與先前的一樣。

  此外,您還可以檢查緩存目錄,該目錄作為 cacheDir 選項的值(在該示例中為 /tmp)傳遞給 Cache_Lite_Function 類的構造函數。在該目錄中,您將找到兩個剛創(chuàng)建的緩存文件,這些文件的名稱類似于:cache_7b181b55b55aee36ad5e7bd9d5a091ec_3ad04d3024f4cd54296f75c92a359154。注意,如果您是一位 Windows 用戶,則可能要使用 %SystemDrive%\temp 目錄保存緩存文件。如果是這樣,則必須將 cacheDir 選項設置為 /temp/。

  驗證緩存機制正常工作后,可以接著創(chuàng)建一個 PHP 來處理從數據庫服務器收到的更改通知?!扒鍐?8”是 dropResult.php 腳本。數據庫服務器將調用該腳本來響應 ORDERS 和 ORDER_ITEMS 表的更改。

  清單 8. 處理從數據庫服務器收到的更改通知

復制代碼 代碼如下:


//File:dropResults.php
require_once 'Cache/Lite/Function.php';
$options = array(
'cacheDir' => '/tmp/'
);
$cache = new Cache_Lite_Function($options);
if (isset($_GET['order_no'])&& isset($_GET['table'])) {
if($_GET['table']=='ORDER_ITEMS'){
$cache->drop('getOrderItems', $_GET['order_no']);
}
if ($_GET['table']=='ORDERS'){
$cache->drop('getOrderFields', $_GET['order_no']);
}
}
?>



  創(chuàng)建 dropResult.php 腳本后,請確保在通知處理程序中指定的 URL(如清單 2 所示)正確。然后,在 SQL*Plus 或類似工具中以 OE/OE 連接,并執(zhí)行 UPDATE 語句,這些語句將影響本部分先前通過 testCache.php 腳本訪問的同一訂單(此處是 ID 為 2408 的訂單):

UPDATE ORDERS SET order_mode = 'direct' WHERE order_id=2408;
UPDATE ORDER_ITEMS SET quantity = 3 WHERE order_id=2408 AND line_item_id=1;
UPDATE ORDER_ITEMS SET quantity = 1 WHERE order_id=2408 AND line_item_id=2;
COMMIT;
  為響應以上更新,本文前面介紹的通知處理程序將逐個使用下列 URL 運行 dropResults.php 腳本兩次:

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 腳本時創(chuàng)建的緩存文件已經消失。這實際上意味著,testCache.php 在下次請求與 ID 為 2408 的訂單相關的數據時將從后端數據庫而非本地緩存中獲取該數據。

  您會發(fā)現,在應用程序請求的結果集很有可能在應用程序使用它之前更改的情況下該方法將很有用。就本文的示例而言,這意味著與特定訂單相關的數據可能在 testCache.php 訪問該訂單之前多次更改。這樣,應用程序會因在從數據庫服務器收到更改通知后立即刷新它的緩存而做了大量不必要的工作。

  但如果您希望 dropResult.php 腳本在收到更改通知后立即刷新緩存,則可以在調用 drop 方法后調用 Cache_Lite_Function 實例的 call 方法,并為這兩個調用指定相同的參數。在該情形下,還應確保包含 getOrderFields.php 和 getOrderItems.php 腳本,以便 dropResults.php 可以調用 getOrderFields 和 getOrderItems 函數來刷新緩存?!扒鍐?9”是修改后的 dropResult.php 腳本。

  清單 9. 在收到更改通知后立即刷新緩存

復制代碼 代碼如下:


//File:dropResults.php
require_once 'Cache/Lite/Function.php';
require_once 'getOrderItems.php';
require_once 'getOrderFields.php';
$options = array(
'cacheDir' => '/tmp/',
'lifeTime' => 86400
);
$cache = new Cache_Lite_Function($options);
if (isset($_GET['order_no'])&& isset($_GET['table'])) {
if($_GET['table']=='ORDER_ITEMS'){
$cache->drop('getOrderItems', $_GET['order_no']);
$cache->call('getOrderItems', $_GET['order_no']);
}
if ($_GET['table']=='ORDERS'){
$cache->drop('getOrderFields', $_GET['order_no']);
$cache->call('getOrderFields', $_GET['order_no']);
}
}
?>


  如果存儲在 ORDERS 和 ORDER_ITEMS 表中的數據很少更改并且應用程序頻繁訪問它,則以上方法可能很有用。

  總結

  如果 PHP 應用程序與 Oracle 數據庫 10g 第 2 版交互,則可以利用“數據庫更改通知特性”,通過該特性應用程序可以接收通知來響應對與發(fā)出的請求關聯的對象進行的 DML 更改。使用該特性,您不必在特定時間段更新應用程序中的緩存。相反,僅當注冊查詢的結果集已經更改時才執(zhí)行該操作。
本站聲明
本文內容由網友自發(fā)貢獻,版權歸原作者所有,本站不承擔相應法律責任。如您發(fā)現有涉嫌抄襲侵權的內容,請聯系admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣服圖片

Undresser.AI Undress

Undresser.AI Undress

人工智能驅動的應用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用于從照片中去除衣服的在線人工智能工具。

Clothoff.io

Clothoff.io

AI脫衣機

Video Face Swap

Video Face Swap

使用我們完全免費的人工智能換臉工具輕松在任何視頻中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的代碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

功能強大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級代碼編輯軟件(SublimeText3)

如何在PHP中獲取當前的會話ID? 如何在PHP中獲取當前的會話ID? Jul 13, 2025 am 03:02 AM

在PHP中獲取當前會話ID的方法是使用session_id()函數,但必須先調用session_start()才能成功獲取。1.調用session_start()啟動會話;2.使用session_id()讀取會話ID,輸出類似abc123def456ghi789的字符串;3.若返回為空,檢查是否遺漏session_start()、用戶是否首次訪問或會話是否被銷毀;4.會話ID可用于日志記錄、安全驗證和跨請求通信,但需注意安全性。確保正確開啟會話后即可順利獲取ID。

php從字符串獲取子字符串 php從字符串獲取子字符串 Jul 13, 2025 am 02:59 AM

要從PHP字符串中提取子字符串,可使用substr()函數,其語法為substr(string$string,int$start,?int$length=null),若未指定長度則截取至末尾;處理多字節(jié)字符如中文時應使用mb_substr()函數以避免亂碼;若需根據特定分隔符截取字符串,可使用explode()或結合strpos()與substr()實現,例如提取文件名擴展名或域名。

如何將字符串分為PHP中的數組 如何將字符串分為PHP中的數組 Jul 13, 2025 am 02:59 AM

在PHP中,最常用的方法是使用explode()函數將字符串拆分為數組。該函數通過指定的分隔符將字符串分割成多個部分并返回數組,語法為explode(separator,string,limit),其中separator為分隔符,string為原字符串,limit為可選參數控制最大分割數量。例如$str="apple,banana,orange";$arr=explode(",",$str);結果為["apple","bana

JavaScript數據類型:原始與參考 JavaScript數據類型:原始與參考 Jul 13, 2025 am 02:43 AM

JavaScript的數據類型分為原始類型和引用類型。原始類型包括string、number、boolean、null、undefined和symbol,其值不可變且賦值時復制副本,因此互不影響;引用類型如對象、數組和函數存儲的是內存地址,指向同一對象的變量會相互影響。判斷類型可用typeof和instanceof,但需注意typeofnull的歷史問題。理解這兩類差異有助于編寫更穩(wěn)定可靠的代碼。

在C中使用std :: Chrono 在C中使用std :: Chrono Jul 15, 2025 am 01:30 AM

std::chrono在C 中用于處理時間,包括獲取當前時間、測量執(zhí)行時間、操作時間點與持續(xù)時間及格式化解析時間。1.獲取當前時間使用std::chrono::system_clock::now(),可轉換為可讀字符串但系統時鐘可能不單調;2.測量執(zhí)行時間應使用std::chrono::steady_clock以確保單調性,并通過duration_cast轉換為毫秒、秒等單位;3.時間點(time_point)和持續(xù)時間(duration)可相互操作,但需注意單位兼容性和時鐘紀元(epoch)

PHP如何處理環(huán)境變量? PHP如何處理環(huán)境變量? Jul 14, 2025 am 03:01 AM

toAccessenvironmentVariablesInphp,useGetenv()或$ _envsuperglobal.1.getEnv('var_name')retievesSpecificvariable.2。$ _ en v ['var_name'] accessesvariablesifvariables_orderInphp.iniincludes“ e” .setVariablesViaCliWithvar = vualitephpscript.php,inapach

如何將會話變量傳遞給PHP中的另一頁? 如何將會話變量傳遞給PHP中的另一頁? Jul 13, 2025 am 02:39 AM

在PHP中,要將一個會話變量傳到另一個頁面,關鍵在于正確開啟會話并使用相同的$_SESSION鍵名。1.每個頁面使用session變量前必須調用session_start(),且放在腳本最前面;2.在第一個頁面設置session變量如$_SESSION['username']='JohnDoe';3.在另一頁面同樣調用session_start()后通過相同鍵名訪問變量;4.確保每個頁面都調用session_start()、避免提前輸出內容、檢查服務器上session存儲路徑可寫;5.使用ses

See all articles