데이터베이스 쿼리 결과를 캐싱하면 스크립트 실행 시간을 크게 줄이고 데이터베이스 서버의 부하를 최소화할 수 있는 것으로 알려져 있습니다. 이 기술은 처리 중인 데이터가 기본적으로 정적일 경우 매우 효과적입니다. 이는 원격 데이터베이스에 대한 많은 데이터 요청이 결국 로컬 캐시에서 충족될 수 있기 때문에 데이터베이스에 연결하고 쿼리를 실행하고 결과를 얻을 필요가 없기 때문입니다.
그러나 사용 중인 데이터베이스가 웹 서버와 다른 컴퓨터에 있는 경우에는 데이터베이스 결과 집합을 캐싱하는 것이 좋은 방법인 경우가 많습니다. 그러나 상황에 가장 적합한 캐싱 전략을 결정하는 것은 어려울 수 있습니다. 예를 들어, 최신 데이터베이스 결과 세트를 사용하는 것이 중요한 애플리케이션의 경우 시간 트리거 캐싱 접근 방식(만료 타임스탬프에 도달할 때마다 캐시가 재생성된다고 가정하는 캐싱 시스템에서 일반적으로 사용됨)은 만족스러운 솔루션이 아닐 수 있습니다. . 이 경우, 애플리케이션이 캐시해야 하는 데이터베이스 데이터가 변경될 때마다 애플리케이션에 이를 알리는 메커니즘이 필요합니다. 그래야 애플리케이션이 캐시된 만료된 데이터를 데이터베이스와 일관되게 유지할 수 있습니다. 이 경우 "데이터베이스 변경 알림"을 사용하는 것이 매우 편리합니다.
데이터베이스 변경 알림 시작하기
데이터베이스 변경 알림 기능의 사용법은 매우 간단합니다. 알림(PL/SQL 저장 프로시저 또는 클라이언트 OCI 콜백 함수)을 위해 실행되는 알림 핸들러를 생성합니다. 그런 다음 변경 알림을 받으려는 데이터베이스 개체에 대한 쿼리를 등록하면 트랜잭션이 해당 개체 내의 개체를 변경하고 커밋할 때마다 알림 처리기가 호출됩니다. 일반적으로 알림 핸들러는 클라이언트 애플리케이션이 응답에서 적절한 작업을 수행할 수 있도록 수정된 테이블 이름, 변경 유형 및 선택적으로 변경된 행의 행 ID를 클라이언트 리스너에게 보냅니다.
데이터베이스 변경 알림 기능이 작동하는 방식을 이해하려면 다음 예를 고려하십시오. PHP 애플리케이션이 OE.ORDERS 테이블에 저장된 주문과 OE.ORDER_ITEMS에 저장된 주문 항목에 액세스한다고 가정합니다. 접수된 주문에 대한 정보가 거의 변경되지 않는다는 점을 고려하면 애플리케이션이 ORDERS 및 ORDER_ITEMS 테이블 모두에 대한 쿼리 결과 세트를 캐시하도록 할 수 있습니다. 오래된 데이터에 액세스하지 않으려면 데이터베이스 변경 알림을 사용하면 위의 두 테이블에 저장된 데이터의 변경 사항을 애플리케이션에서 쉽게 알 수 있습니다.
ORDERS 및 ORDER_ITEMS 테이블에 대한 쿼리를 등록하여 알림을 받고 해당 테이블에 대한 DML 또는 DDL 변경 사항에 응답하려면 먼저 OE 사용자에게 CHANGE NOTIFICATION 시스템 권한과 EXECUTE ON DBMS_CHANGENOTIFICATION 권한을 부여해야 합니다. 이를 수행하려면 SQL*Plus와 같은 SQL 명령줄 도구에서 다음 명령을 실행하십시오.
연결/SYSDBA로;
oe에게 변경 알림을 부여합니다.
DBMS_CHANGE_NOTIFICATION에 대한 실행 권한을 oe에 부여합니다.
PL/SQL 알림을 받으려면 init.ora 매개변수 job_queue_processes가 0이 아닌 값으로 설정되어 있는지 확인하십시오. 또는 다음 ALTER SYSTEM 명령을 사용할 수 있습니다.
ALTER SYSTEM SET "job_queue_processes"=2; 그런 다음 OE/OE로 연결한 후 알림 처리기를 생성할 수 있습니다. 하지만 먼저 알림 처리기에서 사용할 데이터베이스 개체를 만들어야 합니다. 예를 들어 알림 처리기가 레지스트리 변경 사항을 기록하는 하나 이상의 데이터베이스 테이블을 생성할 수 있습니다. 다음 예에서는 nfresults 테이블을 생성하여 변경이 발생한 날짜와 시간, 수정된 테이블의 이름, 알림 핸들러가 클라이언트에 알림 메시지를 성공적으로 보냈는지 여부를 나타내는 메시지를 기록합니다.
oe/oe 연결
nfresults 테이블 생성(
운영DATE,
테이블이름 VARCHAR2(60),
rslt_msg VARCHAR2(100)
);
실제 시나리오에서는 알림 이벤트 및 변경된 행의 행 ID와 같은 정보를 기록하기 위해 더 많은 테이블을 생성해야 할 수도 있지만 이 문서의 목적에는 nfresults 테이블이면 충분합니다.
UTL_HTTP를 사용하여 클라이언트에 알림 보내기
또한 하나 이상의 PL/SQL 저장 프로시저를 생성하고 알림 처리기에서 이러한 저장 프로시저를 호출하여 보다 유지 관리하기 쉽고 유연한 솔루션을 얻을 수도 있습니다. 예를 들어 클라이언트에 알림 메시지 보내기를 구현하는 저장 프로시저를 만들 수 있습니다. "목록 1"은 PL/SQL 프로시저 sendNotification입니다. 이 프로세스는 UTL_HTTPPL 패키지를 사용하여 클라이언트 애플리케이션에 변경 알림을 보냅니다.
목록 1. UTL_HTTPCREATE 또는 REPLACE PROCEDURE를 사용하여 클라이언트에 알림 보내기
sendNotification(url IN VARCHAR2,
tblname IN VARCHAR2, order_id IN VARCHAR2) IS
UTL_HTTP.REQ 요청;
resp UTL_HTTP.RESP;
err_msg VARCHAR2(100);
tbl VARCHAR(60);
시작하다
tbl:=SUBSTR(tbl이름, INSTR(tbl이름, '.', 1, 1)+1, 60);
시작하다
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);
그 외의 경우에는 예외
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 프로시저orders_nf_callback을 살펴보겠습니다.
목록 2. OE.ORDERS 테이블CREATE OR REPLACE PROCEDURE Orders_nf_callback (ntfnds IN SYS.CHNF$_DESC) IS
에 대한 변경 알림을 처리하는 알림 핸들러
테이블이름 VARCHAR2(60);
숫자 테이블 NUMBER;
이벤트_유형 NUMBER;
행_ID VARCHAR2(20);
numrows NUMBER;
ord_id VARCHAR2(12);
URL VARCHAR2(256) := 'http://webserverhost/phpcache/dropResults.php?order_no=';
시작하다
event_type := ntfnds.event_type;
numtables := ntfnds.numtables;
IF (이벤트 유형 = 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 (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 주문 WHERE rowid = row_id;
sendNotification(url, tblname, ord_id);
엔드 루프;
종료하면;
엔드 루프;
종료하면;
저지르다;
끝;
/
"목록 2"에 표시된 대로 이 알림 핸들러는 SYS.CHNF$_DESC 개체를 매개변수로 사용하고 해당 속성을 사용하여 변경 사항에 대한 세부 정보를 가져옵니다. 이 예에서 이 알림 핸들러는 등록된 객체에 대한 DML 또는 DDL 변경에 대한 응답으로 데이터베이스에서 게시한 알림만 처리하고(즉, 알림 유형이 EVENT_OBJCHANGE인 경우에만) 인스턴스 시작 또는 인스턴스 시작이나 기타 데이터베이스 이벤트에 대한 정보는 무시합니다. 인스턴스 종료) 알림. 위 버전부터 핸들러는 OE.ORDERS 테이블의 영향을 받는 각 행에 대해 발행된 변경 알림을 처리할 수 있습니다. 이 문서 뒷부분의 "기존 등록에 테이블 추가" 섹션에서 처리기에 몇 줄의 코드를 추가하여 OE.ORDER_ITEMS 테이블의 수정된 행에 대한 알림을 처리할 수 있습니다.
변경 알림을 위한 등록 생성
알림 처리기를 생성한 후 이에 대한 쿼리 등록을 생성해야 합니다. 이 예에서는 등록 프로세스 중에 OE.ORDER 테이블에 대한 쿼리를 수행하고 주문_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.주문을 찾을 수 없음
02-mar-06 04:31:29 OE.주문을 찾을 수 없음
위 결과를 보면 Orders_nf_callback이 이미 작동하고 있지만 클라이언트 스크립트를 찾을 수 없다는 것이 분명합니다. URL에 지정된 dropResults.php 스크립트를 생성하지 않았기 때문에 이 예에서는 예상치 못한 일이 아닙니다. dropResults.php 스크립트에 대한 지침은 이 문서 뒷부분의 클라이언트 구축 섹션을 참조하세요.
기존 등록에 테이블 추가
이전 섹션에서는 변경 알림 서비스를 사용하여 등록 객체(위 예에서는 ORDERS 테이블)가 변경될 때 데이터베이스가 이를 알리도록 하는 방법을 보여주었습니다. 그러나 성능 관점에서 클라이언트 애플리케이션은 주문에 액세스할 때마다 ORDERS 테이블에서 한 행만 검색해야 하기 때문에 ORDERS 테이블 자체보다는 ORDER_ITEMS 테이블의 쿼리 결과 집합을 캐시하는 것을 선호할 수 있습니다. 동시에 ORDER_ITEMS 테이블에서 여러 행을 검색해야 합니다. 실제로 주문에는 수십 또는 수백 개의 광고 항목이 포함될 수 있습니다.
ORDERS 테이블에 대한 쿼리를 이미 등록했으므로 ORDER_ITEMS 테이블에 대한 쿼리를 등록하기 위해 등록을 생성할 필요가 없습니다. 대신 기존 등록을 사용할 수 있습니다. 이렇게 하려면 먼저 기존 등록의 ID를 검색해야 합니다. 이를 수행하려면 다음 쿼리를 실행할 수 있습니다.
SELECT regid, table_name FROM user_change_notification_regs 결과는 다음과 같습니다.
REGID TABLE_NAME
----- --------------
241 OE.주문
등록 ID를 얻은 후 다음과 같이 DBMS_CHANGE_NOTIFICATION.ENABLE_REG 함수를 사용하여 등록에 새 개체를 추가할 수 있습니다
.
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 LOOP
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 (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);
엔드 루프;
종료하면;
Orders_nf_callback을 다시 생성한 후 올바르게 작동하는지 테스트해야 합니다. 이를 위해 ORDER_ITEMS 테이블에 대해 다음 UPDATE 문을 실행하고 트랜잭션을 커밋할 수 있습니다.
UPDATE ORDER_ITEMS SET 수량 = 160 WHERE order_id=2421 AND line_item_id=1;
업데이트 ORDER_ITEMS 세트 수량 = 160 여기서 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 찾을 수 없음
왜 nfresults 테이블에 하나의 행만 삽입되었는지 궁금할 것입니다. 결국 ORDER_ITEMS 테이블에서 두 개의 행을 업데이트했기 때문입니다. 실제로 업데이트된 두 행의 order_id는 동일합니다. 즉, 동일한 주문에 속합니다. 여기서는 클라이언트 애플리케이션이 단일 명령문을 사용하여 주문의 모든 품목을 선택한다고 가정하므로 주문의 어떤 품목이 변경되었는지 정확히 알 필요가 없습니다. 대신 클라이언트는 하나 이상의 광고 항목이 수정, 삭제 또는 삽입된 주문 ID를 알아야 합니다.
클라이언트 구축
이제 ORDERS 및 ORDER_ITEMS 테이블에 대한 등록을 생성했으므로 이러한 테이블에 저장된 주문 및 해당 라인 항목에 액세스하는 클라이언트 애플리케이션에서 변경 알림을 사용하는 방법을 살펴보겠습니다. 이를 위해 위 테이블에 대한 쿼리 결과를 캐시하고 이러한 테이블 변경 사항에 대한 알림(데이터베이스 서버에서 수신)에 대한 응답으로 적절한 조치를 취하는 PHP 애플리케이션을 구축할 수 있습니다. 쉬운 방법은 캐시 데이터를 최신 상태로 유지하는 안정적인 메커니즘을 제공하는 PEAR::Cache_Lite 패키지를 사용하는 것입니다. 특히, 함수 호출을 캐시할 수 있는 Cache_Lite_Function 클래스(PEAR::Cache_Lite 패키지의 일부)를 사용할 수 있습니다.
예를 들어, 데이터베이스 연결을 설정하고, 데이터베이스에 대해 select 문을 실행하고, 검색 결과를 얻고, 마지막으로 결과를 배열로 반환하는 작업을 수행하는 함수를 만들 수 있습니다. 그런 다음 Cache_Lite_Function 인스턴스의 호출 메서드를 통해 함수에서 반환된 결과 배열을 캐시하여 백엔드 데이터베이스가 아닌 로컬 캐시에서 읽을 수 있으므로 애플리케이션 성능이 크게 향상될 수 있습니다. 그런 다음 캐시된 데이터에 대한 변경 알림을 받으면 Cache_Lite_Function 인스턴스의 drop 메서드를 사용하여 캐시에서 만료된 데이터를 삭제합니다.
이 기사의 예로 돌아가면, 애플리케이션이 데이터베이스와 상호 작용하는 두 가지 함수를 생성할 수 있습니다. 첫 번째 함수는 ORDERS 테이블을 쿼리하고 지정된 ID가 있는 주문을 반환하는 반면, 다른 함수는 ORDER_ITEMS를 쿼리합니다. table 및 return 이 주문에 대한 품목을 반환합니다. "목록 4"는 주문 ID를 승인하고 검색된 주문의 일부 필드를 포함하는 연관 배열을 반환하는 getOrderFields 함수를 포함하는 getOrderFields.php 스크립트를 보여줍니다.
목록 4. 지정된 순서의 필드 가져오기
<?php
//파일:getOrderFields.php
require_once 'connect.php';
함수 getOrderFields($order_no) {
if (!$rsConnection = GetConnection()){
거짓을 반환;
}
$strSQL = "SELECT TO_CHAR(ORDER_DATE) ORDER_DATE, CUSTOMER_ID,
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();
인쇄 $err['메시지'];
Trigger_error('쿼리 실패:' . $err['message']);
거짓을 반환;
}
$results = oci_fetch_assoc($rsStatement);
$결과를 반환합니다.
}
?>
"목록 5"는 getOrderItems.php 스크립트입니다. 스크립트에는 주문 ID를 승인하고 주문의 품목을 나타내는 행이 포함된 2차원 배열을 반환하는 getOrderItems 함수가 포함되어 있습니다.
목록 5. 지정된 주문의 광고 항목 가져오기
<?php
//파일:getOrderItems.php
require_once 'connect.php';
함수 getOrderItems($order_no) {
if (!$rsConnection = GetConnection()){
거짓을 반환;
}
$strSQL = "여기에서 ORDER_ITEMS에서 * 선택
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['message']);
거짓을 반환;
}
$nrows = oci_fetch_all($rsStatement, $results);
반환 배열($nrows, $results);
}
?>
위의 두 함수 모두 데이터베이스 연결을 반환하는 GetConnection 함수를 포함하는 connect.php 스크립트가 필요합니다. 목록 6은 connect.php 스크립트입니다.
목록 6. 데이터베이스 연결 얻기
<?php
//파일:connect.php
함수 GetConnection() {
$dbHost = "db서버호스트";
$dbHostPort="1521";
$dbServiceName = "orclR2";
$usr = "oe";
$pswd = "oe";
$dbConnStr = "(설명=(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['message']);
거짓을 반환;
}
$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 '캐시/라이트/Function.php'
$options = 배열(
'cacheDir' => '/tmp/',
'수명' => 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)){
인쇄 "<h3>ORDER #$order_no</h3>n";
"<테이블>"을 인쇄합니다.
"<tr><td>DATE:</td><td>".$orderfields['ORDER_DATE']."</td></tr>"를 인쇄합니다.
인쇄 "<tr><td>CUST_ID:</td><td>".$orderfields['CUSTOMER_ID']."</td></tr>";
"<tr><td>TOTAL:</td><td>".$orderfields['ORDER_TOTAL']."</td></tr>"를 인쇄합니다.
"</table>"을 인쇄합니다.
} 또 다른 {
"주문 필드를 가져오는 동안 문제가 발생했습니다!n"을 인쇄하세요.
$cache->drop('getOrderFields', $order_no);
}
if (list($nrows, $orderitems) = $cache->call('getOrderItems', $order_no)){
//"<h3>주문 내 라인 항목 #$order_no</h3>" 인쇄;
"<테이블 테두리=1>"을 인쇄합니다.
"<tr>n"을 인쇄합니다;
while (list($key, $value) = 각각($orderitems)) {
"<번째>$key</번째>n"을 인쇄합니다.
}
"</tr>n"을 인쇄합니다;
for ($i = 0; $i < $nrows; $i++) {
"<tr>"을 인쇄합니다;
인쇄 "<td>".$orderitems['ORDER_ID'][$i]."</td>";
인쇄 "<td>".$orderitems['LINE_ITEM_ID'][$i]."</td>";
인쇄 "<td>".$orderitems['PRODUCT_ID'][$i]."</td>";
인쇄 "<td>".$orderitems['UNIT_PRICE'][$i]."</td>";
인쇄 "<td>".$orderitems['QUANTITY'][$i]."</td>";
인쇄 "</tr>";
}
"</table>"을 인쇄합니다.
} 또 다른 {
"주문 항목을 가져오는 동안 일부 문제가 발생했습니다"를 인쇄합니다.
$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일 오전 6시 59분 31초 333617
고객_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시간 이내에 로컬 캐시에 의해 충족됩니다(수명 시간이 86400초로 설정되어 있기 때문). 그러나 Cache_Lite_Function 클래스는 지정된 매개변수를 사용하여 지정된 함수에 캐시를 사용할 수 있는지 여부를 테스트하는 API를 제공하지 않습니다. 따라서 애플리케이션이 실제로 캐시를 읽는지, 아니면 동일한 매개변수를 사용하여 호출될 때마다 함수를 실행하는지 확인하는 것이 약간 까다로울 수 있습니다. 예를 들어, 위의 예에서 캐싱 메커니즘이 제대로 작동하는지 확인하려면 connect.php 스크립트에 지정된 연결 정보를 일시적으로 변경하여 데이터베이스 연결을 설정할 수 없도록 할 수 있습니다. 예를 들어 잘못된 데이터베이스 서버 호스트 이름을 지정할 수 있습니다. , 그리고 order_no=를 다시 사용하십시오. 2108 testCache.php 스크립트를 실행하십시오. 캐싱이 제대로 작동한다면 브라우저의 출력은 이전과 동일해야 합니다.
또한 Cache_Lite_Function 클래스의 생성자에 캐시Dir 옵션(이 예에서는 /tmp)의 값으로 전달되는 캐시 디렉터리를 확인할 수 있습니다. 해당 디렉터리에는 방금 생성한 두 개의 캐시 파일(cache_7b181b55b55aee36ad5e7bd9d5a091ec_3ad04d3024f4cd54296f75c92a359154)과 유사한 이름이 있습니다. Windows 사용자인 경우 %SystemDrive%temp 디렉터리를 사용하여 캐시 파일을 저장할 수 있습니다. 그렇다면 캐시Dir 옵션을 /temp/로 설정해야 합니다.
캐싱 메커니즘이 제대로 작동하는지 확인한 후 PHP를 생성하여 데이터베이스 서버에서 받은 변경 알림을 처리할 수 있습니다. "목록 8"은 dropResult.php 스크립트입니다. 데이터베이스 서버는 ORDERS 및 ORDER_ITEMS 테이블 변경에 대한 응답으로 이 스크립트를 호출합니다.
목록 8. 데이터베이스 서버에서 수신된 변경 알림 처리하기
<?php
//파일:dropResults.php
require_once '캐시/라이트/Function.php'
$options = 배열(
'cacheDir' => '/tmp/'
);
$cache = 새로운 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']);
}
}
?>
dropResult.php 스크립트를 작성한 후 알림 핸들러(목록 2에 표시됨)에 지정된 URL이 올바른지 확인하십시오. 그런 다음 SQL*Plus 또는 유사한 도구에서 OE/OE로 연결하고 testCache.php 스크립트(여기서는 ID 2408의 주문)를 통해 이 섹션 앞부분에서 액세스한 동일한 주문에 영향을 주는 UPDATE 문을 실행합니다.
UPDATE ORDERS SET order_mode = ' direct' WHERE order_id=2408;
업데이트 ORDER_ITEMS 세트 수량 = 3 WHERE order_id=2408 AND line_item_id=1;
업데이트 ORDER_ITEMS 세트 수량 = 1 여기서 order_id=2408 AND line_item_id=2;
저지르다;
위 업데이트에 대한 응답으로 이 기사 앞부분에서 설명한 알림 핸들러는 다음 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 스크립트를 실행할 때 생성된 캐시 파일이 사라진 것을 확인할 수 있습니다. 이것이 본질적으로 의미하는 바는 다음에 testCache.php가 주문 ID 2408과 관련된 데이터를 요청할 때 로컬 캐시 대신 백엔드 데이터베이스에서 해당 데이터를 가져옵니다.
애플리케이션에서 요청한 결과 집합이 애플리케이션에서 사용되기 전에 변경될 가능성이 있는 상황에서 이 방법이 유용할 수 있습니다. 이 기사의 예에서 이는 testCache.php가 해당 주문에 액세스하기 전에 특정 주문과 관련된 데이터가 여러 번 변경될 수 있음을 의미합니다. 이러한 방식으로 애플리케이션은 데이터베이스 서버로부터 변경 알림을 받은 후 즉시 캐시를 플러시하여 불필요한 작업을 많이 수행합니다.
그러나 dropResult.php 스크립트가 변경 알림을 받자마자 캐시를 플러시하도록 하려면 drop 메소드를 호출한 후 두 호출에 동일한 매개변수를 지정하여 Cache_Lite_Function 인스턴스의 호출 메소드를 호출할 수 있습니다. 이 경우 dropResults.php가 getOrderFields 및 getOrderItems 함수를 호출하여 캐시를 새로 고칠 수 있도록 getOrderFields.php 및 getOrderItems.php 스크립트도 포함해야 합니다. "목록 9"는 수정된 dropResult.php 스크립트입니다.
목록 9. 변경 알림을 받은 후 즉시 캐시 플러시
<?php
//파일:dropResults.php
require_once '캐시/라이트/Function.php';
require_once 'getOrderItems.php';
require_once 'getOrderFields.php'
$옵션 = 배열(
'cacheDir' => '/tmp/',
'수명' => 86400
);
$cache = 새로운 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 Database 10g Release 2와 상호 작용하는 경우 데이터베이스 변경 알림 기능을 활용할 수 있습니다. 이를 통해 애플리케이션은 요청과 관련된 객체에 대한 DML 변경에 대한 응답으로 알림을 받을 수 있습니다. 이 기능을 사용하면 특정 기간 동안 애플리케이션의 캐시를 업데이트할 필요가 없습니다. 대신, 등록된 쿼리의 결과 집합이 변경된 경우에만 작업이 수행됩니다.