透過快取資料庫結果提高PHP效能(1)

日期:2006-09-28  作者:喜騰小二  來源:PHPChina


   眾所周知,快取資料庫查詢的結果可以顯着縮短指令檔執行時間,並最大限度地減少資料庫伺服器上的負載。如果要處理的資料基本上是靜態的,則該技術將非常有效。這是因為對遠端資料庫的許多資料請求最終可以從本機快取得到滿足,從而不必連線到資料庫、執行查詢以及獲取結果。


  但當您使用的資料庫與 Web
伺服器位於不同的電腦上時,快取資料庫結果集通常是一個不錯的方法。不過,根據您的情況確定最佳的快取策略卻是一個難題。例如,對於使用最新資料庫結果集比較重要的應用程式而言,時間觸發的快取方法(快取係統常用的方法,它假設每次到達失效時間戳記時就重新生成快取)可能並不是一個令人滿意的解決方案。這種情況下,您需要采用一種機制,每當應用程式需要快取的資料庫資料發生變更時,該機制將通知該應用程式,以便該應用程式將快取的過期資料與資料庫保持一緻。這種情況下使用“資料庫變更通知”將非常方便。

  “資料庫變更通知”入門


  “資料庫變更通知”特性的用法非常簡單:建立一個針對通知執行的通知處理程式 – 一個 PL/SQL 存儲過程或用戶端 OCI
回呼函式。然後,針對要接收其變更通知的資料庫物件注冊一個查詢,以便每當事務變更其中的任何物件並提交時調用通知處理程式。通常情況下,通知處理程式將被修改的表的名稱、所做變更的類型以及所變更行的行
ID(可選)發送給用戶端監聽程式,以便用戶端應用程式可以在回應中執行相應的處理。


  為了瞭解“資料庫變更通知”特性的作用方式,請考慮以下範例。假設您的 PHP 應用程式訪問 OE.ORDERS 表中存儲的訂單以及
OE.ORDER_ITEMS 中存儲的訂單項。鑑於很少變更已下訂單的資訊,您可能希望應用程式同時快取針對 ORDERS 和 ORDER_ITEMS
表的查詢結果集。要避免訪問過期資料,您可以使用“資料庫變更通知”,它可讓您的應用程式方便地獲知以上兩個表中所存儲資料的變更。

  您必須先將
CHANGE NOTIFICATION 係統授權權以及 EXECUTE ON DBMS_CHANGENOTIFICATION 授權權授予 OE 使用者,才能注冊對
ORDERS 和 ORDER_ITEMS 表的查詢,以便接收通知和回應對這兩個表所做的 DML 或 DDL 變更。為此,可以從 SQL 指令行工俱(如
SQL*Plus)中執行下列指令。
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
連線後,您可以建立一個通知處理程式。但首先,您必須建立將由通知處理程式使用的資料庫物件。例如,您可能需要建立一個或多個資料庫表,以便通知處理程式將登錄的變更記錄到其中。在以下範例中,您將建立
nfresults 表來記錄以下資訊:變更發生的日期和時間、被修改的表的名稱以及一個訊息(幫助通知處理程式是否成功地將通知訊息發送給用戶端)。
CONNECT oe/oe;

CREATE TABLE nfresults (
operdate DATE,
tblname VARCHAR2(60),
rslt_msg VARCHAR2(100)
);
  在實際情況中,您可能需要建立更多表來記錄通知事件以及所變更行的行 ID 等資訊,但就本文而言,nfresults 表完全可以滿足需要。


  使用 UTL_HTTP 嚮用戶端發送通知

  您可能還要建立一個或多個 PL/SQL
存儲過程,並從通知處理程式中調用這些存儲過程,從而實現一個更俱可維護性和靈活性的解決方案。例如,您可能要建立一個實現將通知訊息發送給用戶端的存儲過程。“清單
1”是 PL/SQL 過程 sendNotification。該過程使用 UTL_HTTPPL 套裝程式嚮用戶端應用程式發送變更通知。


  清單 1. 使用 UTL_HTTP 嚮用戶端發送通知
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 函式發出的 HTTP
請求的形式嚮用戶端發送通知訊息。此 URL 包含 ORDERS 表中已變更行的 order_id。然後,它使用 UTL_HTTP.GET_RESPONSE
獲取用戶端發出的回應資訊。實際上,sendNotification 並不需要處理用戶端返回的整個回應,而是隻獲取一個在 RESP 記錄的
reason_phrase 欄位中存儲的簡短訊息(描述狀態程式碼)。

<<<返回技術中心

技術文章

站內新聞

我要啦免费统计