من المعروف أن التخزين المؤقت لنتائج استعلامات قاعدة البيانات يمكن أن يقلل بشكل كبير من وقت تنفيذ البرنامج النصي ويقلل الحمل على خادم قاعدة البيانات. تعمل هذه التقنية بشكل جيد للغاية إذا كانت البيانات التي تقوم بمعالجتها ثابتة بشكل أساسي. وذلك لأن العديد من طلبات البيانات إلى قاعدة البيانات البعيدة يمكن تلبيتها في النهاية من ذاكرة التخزين المؤقت المحلية، مما يلغي الحاجة إلى الاتصال بقاعدة البيانات وتنفيذ الاستعلام والحصول على النتائج.
لكن التخزين المؤقت لمجموعة نتائج قاعدة البيانات غالبًا ما يكون فكرة جيدة عندما تكون قاعدة البيانات التي تستخدمها موجودة على جهاز كمبيوتر مختلف عن خادم الويب. ومع ذلك، قد يكون من الصعب تحديد أفضل استراتيجية للتخزين المؤقت لموقفك. على سبيل المثال، بالنسبة للتطبيقات التي يكون فيها من المهم استخدام أحدث مجموعة نتائج لقاعدة البيانات، قد لا يكون أسلوب التخزين المؤقت المفعّل بالوقت (الذي يشيع استخدامه بواسطة أنظمة التخزين المؤقت التي تفترض إعادة إنشاء ذاكرة التخزين المؤقت في كل مرة يتم فيها الوصول إلى الطابع الزمني لانتهاء الصلاحية) حلاً مرضيًا . في هذه الحالة، تحتاج إلى آلية لإعلام التطبيق عندما تتغير بيانات قاعدة البيانات التي يحتاج التطبيق إلى تخزينها مؤقتًا، حتى يتمكن التطبيق من الاحتفاظ بالبيانات منتهية الصلاحية المخزنة مؤقتًا بما يتوافق مع قاعدة البيانات. في هذه الحالة، سيكون استخدام "إشعار تغيير قاعدة البيانات" أمرًا مريحًا للغاية.
الشروع في العمل مع إعلام تغيير قاعدة البيانات
يعد استخدام ميزة إعلام تغيير قاعدة البيانات أمرًا بسيطًا للغاية: قم بإنشاء معالج إعلام ينفذ الإشعار - إجراء مخزن PL/SQL أو وظيفة رد اتصال OCI للعميل. بعد ذلك، قم بتسجيل استعلام مقابل كائنات قاعدة البيانات التي تريد تلقي إشعارات التغيير الخاصة بها، بحيث يتم استدعاء معالج الإشعارات عندما تقوم معاملة بتغيير أي كائن داخلها وتنفيذها. عادةً، يرسل معالج الإعلام اسم الجدول الذي تم تعديله، ونوع التغيير الذي تم إجراؤه، ومعرف الصف الخاص بالصف الذي تم تغييره بشكل اختياري إلى مستمع العميل حتى يتمكن تطبيق العميل من تنفيذ الإجراءات المناسبة في التعامل مع الاستجابة.
لفهم كيفية عمل ميزة "إعلام تغيير قاعدة البيانات"، خذ بعين الاعتبار المثال التالي. افترض أن تطبيق PHP الخاص بك يصل إلى الطلبات المخزنة في جدول OE.ORDERS وعناصر الطلب المخزنة في OE.ORDER_ITEMS. نظرًا لأن المعلومات المتعلقة بالطلبات المقدمة نادرًا ما تتغير، فقد ترغب في أن يقوم تطبيقك بتخزين مجموعات نتائج الاستعلامات مؤقتًا مقابل جدولي ORDERS وORDER_ITEMS. لتجنب الوصول إلى البيانات القديمة، يمكنك استخدام إشعارات تغيير قاعدة البيانات، والتي تسمح بإخطار تطبيقك بسهولة بالتغييرات التي تطرأ على البيانات المخزنة في الجدولين أعلاه.
يجب عليك منح إذن نظام CHANGE NOTIFICATION وإذن EXECUTE ON DBMS_CHANGENOTIFICATION لمستخدم OE قبل أن تتمكن من تسجيل الاستعلامات الخاصة بجداول ORDERS وORDER_ITEMS لتلقي الإشعارات والاستجابة لتغييرات DML أو DDL لهذه الجداول. للقيام بذلك، قم بتنفيذ الأمر التالي من أداة سطر أوامر SQL مثل SQL*Plus.
الاتصال/كما SYSDBA؛
منح إشعار التغيير إلى oe؛
منح التنفيذ على DBMS_CHANGE_NOTIFICATION إلى oe؛
تأكد من تعيين المعلمة init.ora job_queue_processes على قيمة غير صفرية لتلقي إشعارات PL/SQL. بدلاً من ذلك، يمكنك استخدام أمر ALTER SYSTEM التالي:
ALTER SYSTEM SET "job_queue_processes" = 2؛ ثم، بعد الاتصال كـ OE/OE، يمكنك إنشاء معالج إعلام. لكن عليك أولاً إنشاء كائن قاعدة البيانات الذي سيتم استخدامه بواسطة معالج الإشعارات. على سبيل المثال، قد ترغب في إنشاء جدول قاعدة بيانات واحد أو أكثر حيث يقوم معالج الإعلام بتسجيل تغييرات التسجيل. في المثال التالي، يمكنك إنشاء جدول nfresults لتسجيل تاريخ ووقت حدوث التغيير، واسم الجدول الذي تم تعديله، ورسالة تشير إلى ما إذا كان معالج الإشعارات قد أرسل رسالة الإشعار إلى العميل بنجاح.
CONNECT oe/oe;
إنشاء نتائج الجدول (
تاريخ التشغيل,
اسم الجدول VARCHAR2(60)،
rslt_msg VARCHAR2(100)
);
في سيناريو العالم الحقيقي، قد تحتاج إلى إنشاء المزيد من الجداول لتسجيل المعلومات مثل أحداث الإعلام ومعرفات الصفوف للصفوف التي تم تغييرها، ولكن لأغراض هذه المقالة، سيكون جدول nfresults كافيًا.
استخدام UTL_HTTP لإرسال إشعارات إلى العملاء
يمكنك أيضًا إنشاء واحد أو أكثر من إجراءات PL/SQL المخزنة واستدعاء هذه الإجراءات المخزنة من معالج الإشعارات، وبالتالي تحقيق حل أكثر مرونة وقابلية للصيانة. على سبيل المثال، قد ترغب في إنشاء إجراء مخزن يقوم بتنفيذ إرسال رسائل الإعلام إلى العملاء. "القائمة 1" هي إجراء PL/SQL sendNotification. تستخدم هذه العملية حزمة UTL_HTTPPL لإرسال إشعارات التغيير إلى تطبيقات العميل.
القائمة 1. إرسال إشعار إلى العميل باستخدام UTL_HTTPREATE
أو استبدال الإجراء 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);
يبدأ
tbl:=SUBSTR(tblname, INSTR(tblname, '.', 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 رسالة إشعار إلى العميل في شكل طلب HTTP صادر عن وظيفة UTL_HTTP.BEGIN_REQUEST. يحتوي عنوان URL هذا على معرف الطلب الخاص بالصف الذي تم تغييره في جدول الطلبات. ثم يستخدم UTL_HTTP.GET_RESPONSE للحصول على معلومات الاستجابة المرسلة من قبل العميل. في الواقع، لا يحتاج sendNotification إلى معالجة الاستجابة الكاملة التي تم إرجاعها من قبل العميل، ولكنه يحصل فقط على رسالة قصيرة (تصف رمز الحالة) مخزنة في حقل Reason_phrase لسجل RESP.
إنشاء معالج الإشعارات
يمكنك الآن إنشاء معالج الإشعارات الذي سيرسل إشعارات التغيير إلى العملاء بمساعدة إجراء sendNotification الموضح أعلاه. دعونا نلقي نظرة على إجراءات PL/SQL Orders_nf_callback في "القائمة 2".
القائمة 2. معالج الإشعارات الذي يعالج إخطارات التغييرات في جدول OE.ORDERS
CREATE OR REPLACE PROCEDUREorders_nf_callback (ntfnds IN SYS.CHNF$_DESC) IS
tblname VARCHAR2(60);
عدد الأرقام؛
حدث_نوع رقم؛
Row_id VARCHAR2(20);
عدد الأرقام؛
ord_id VARCHAR2(12);
url VARCHAR2(256) := 'http://webserverhost/phpcache/dropResults.php?order_no=';
يبدأ
Event_type := ntfnds.event_type;
numtables := ntfnds.numtables;
إذا (event_type = DBMS_CHANGE_NOTIFICATION.EVENT_OBJCHANGE) ثم
لأني في 1.. حلقة الأرقام
tblname := ntfnds.table_desc_array(i).table_name;
إذا (bitand(ntfnds.table_desc_array(i).opflags،
DBMS_CHANGE_NOTIFICATION.ALL_ROWS) = 0) ثم
numrows := ntfnds.table_desc_array(i).numrows;
آخر
الأعداد :=0;
نهاية إذا؛
إذا (tblname = 'OE.ORDERS') إذن
لـ j IN 1.. حلقة الأرقام
Row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
حدد order_id INTO ord_id من الطلبات WHERE Rowid = Row_id;
sendNotification(url, tblname, ord_id);
حلقة النهاية؛
نهاية إذا؛
حلقة النهاية؛
نهاية إذا؛
يقترف؛
نهاية؛
/
كما هو موضح في "القائمة 2"، يأخذ معالج الإعلام هذا كائن SYS.CHNF$_DESC كمعلمة ثم يستخدم خصائصه للحصول على تفاصيل التغيير. في هذا المثال، سيتعامل معالج الإعلام هذا فقط مع الإعلامات التي نشرتها قاعدة البيانات استجابة لتغييرات DML أو DDL للكائنات المسجلة (أي فقط إذا كان نوع الإعلام هو EVENT_OBJCHANGE)، ويتجاهل المعلومات حول أحداث قاعدة البيانات الأخرى مثل بدء تشغيل المثيل أو إيقاف تشغيل المثيل) إشعار. بدءًا من الإصدار أعلاه، يستطيع المعالج التعامل مع إشعارات التغيير الصادرة لكل صف متأثر في جدول OE.ORDERS. لاحقًا في هذه المقالة، في القسم "إضافة جدول إلى تسجيل موجود"، ستضيف بضعة أسطر من التعليمات البرمجية إلى المعالج حتى يتمكن من معالجة الإعلامات الخاصة بالصفوف المعدلة في الجدول OE.ORDER_ITEMS.
إنشاء تسجيل لإعلامات التغيير
بعد إنشاء معالج إعلام، يجب عليك إنشاء تسجيل استعلام له. في هذا المثال، يجب عليك إجراء استعلام في جدول OE.ORDER أثناء عملية التسجيل وتحديد Orders_nf_callback كمعالج الإشعارات. تحتاج أيضًا إلى تحديد خيار QOS_ROWIDS في حزمة DBMS_CHANGE_NOTIFICATION لتمكين الدقة على مستوى ROWID في رسائل الإعلام. "القائمة 3" عبارة عن كتلة PL/SQL تقوم بإنشاء تسجيل الاستعلام لمعالج إعلام Orders_nf_callback.
القائمة 3. قم بإنشاء تسجيل استعلامأعلن
عن معالج الإشعارات
REGDS SYS.CHNF$_REG_INFO;
رقم التسجيل؛
ord_id رقم؛
رقم qosflags؛
يبدأ
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);
حدد order_id INTO ord_id من الطلبات حيث ROWNUM<2؛
DBMS_CHANGE_NOTIFICATION.REG_END;
نهاية؛
/
يقوم هذا المثال بإنشاء تسجيل مقابل جدول ORDERS ويستخدم Orders_nf_callback كمعالج للإشعارات. الآن، إذا كنت تستخدم عبارة DML أو DDL لتعديل جدول الطلبات وتنفيذ المعاملة، فسيتم استدعاء وظيفة Orders_nf_callback تلقائيًا. على سبيل المثال، يمكنك تنفيذ عبارة UPDATE التالية مقابل جدول ORDERS وتنفيذ المعاملة:
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 يعمل بالفعل ولكن لم يتم العثور على البرنامج النصي للعميل. وهذا ليس أمرًا غير متوقع في هذا المثال لأنك لم تقم بإنشاء البرنامج النصي dropResults.php المحدد في عنوان URL. للحصول على إرشادات حول البرنامج النصي dropResults.php، راجع قسم "إنشاء العميل" لاحقًا في هذه المقالة.
إضافة جدول إلى تسجيل موجود
أظهر القسم السابق كيفية استخدام خدمة إشعار التغيير لجعل قاعدة البيانات تعلمك عندما يتغير كائن التسجيل (في المثال أعلاه، جدول الطلبات). ولكن من منظور الأداء، قد يفضل تطبيق العميل تخزين مجموعة نتائج الاستعلام الخاصة بجدول ORDER_ITEMS مؤقتًا بدلاً من جدول ORDERS نفسه، لأنه يجب عليه استرداد صف واحد فقط من جدول ORDERS في كل مرة يصل فيها إلى الطلب، ولكن عند في نفس الوقت يجب استرداد صفوف متعددة من جدول ORDER_ITEMS. في الواقع، قد يحتوي الطلب على عشرات أو حتى مئات العناصر.
نظرًا لأنك قمت بالفعل بتسجيل الاستعلامات في جدول ORDERS، فلن تحتاج إلى إنشاء تسجيل لتسجيل الاستعلامات في جدول ORDER_ITEMS. بدلاً من ذلك، يمكنك استخدام تسجيل موجود. للقيام بذلك، تحتاج أولاً إلى استرداد معرف التسجيل الموجود. يمكنك تنفيذ الاستعلام التالي لإنجاز ذلك:
SELECT regid, table_name FROM user_change_notification_regs; قد تبدو النتائج كما يلي:
REGID TABLE_NAME
----- --------------
241 أوامر OE
بعد الحصول على معرف التسجيل، يمكنك إضافة كائن جديد إلى التسجيل باستخدام الدالة DBMS_CHANGE_NOTIFICATION.ENABLE_REG كما يلي:
DECLARE
ord_id رقم؛
يبدأ
DBMS_CHANGE_NOTIFICATION.ENABLE_REG(241);
حدد order_id INTO ord_id FROM order_items WHERE ROWNUM < 2؛
DBMS_CHANGE_NOTIFICATION.REG_END;
نهاية؛
/
منتهي! من الآن فصاعدًا، ستقوم قاعدة البيانات بإنشاء إشعار استجابة لأية تغييرات تم إجراؤها على ORDERS وORDER_ITEMS، واستدعاء إجراء Orders_nf_callback للتعامل مع الإشعار. لذلك، فإن الخطوة التالية هي تحرير Orders_nf_callback حتى يتمكن من التعامل مع الإشعارات التي تم إنشاؤها بواسطة عمليات DML في الجدول ORDER_ITEMS. ولكن قبل إعادة إنشاء إجراء Orders_nf_callback، تحتاج إلى إنشاء نوع الجدول التالي الذي سيتم الرجوع إليه أثناء عملية التحديث:
CREATE TYPE rdesc_tab AS TABLE OF SYS.CHNF$_RDESC؛ ثم ارجع إلى القائمة 2، بعد السطر التالي من الكود:
IF (tblname = 'OE.ORDERS') إذن
لـ j IN 1.. حلقة الأرقام
Row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
حدد order_id INTO ord_id من الطلبات WHERE Rowid = Row_id;
sendNotification(url, tblname, ord_id);
حلقة النهاية؛
نهاية إذا؛
أدخل التعليمة البرمجية التالية:
IF (tblname = 'OE.ORDER_ITEMS') THEN
للتسجيل في (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 حيث t.row_id = d.rowid AND d.order_id=o.order_id)
حلقة
sendNotification(url, tblname, rec.o_id);
حلقة النهاية؛
نهاية إذا؛
بعد إعادة إنشاء Orders_nf_callback، تحتاج إلى اختبار ما إذا كان يعمل بشكل صحيح. للقيام بذلك، يمكنك تنفيذ عبارة UPDATE التالية مقابل جدول ORDER_ITEMS وتنفيذ المعاملة:
UPDATE ORDER_ITEMS SETquantity = 160 WHERE order_id=2421 AND line_item_id=1;
تحديث كمية مجموعة ORDER_ITEMS = 160 حيث order_id=2421 و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-مارس-06 12:32:27 غير موجود
ربما تتساءل عن سبب إدراج صف واحد فقط في جدول nfresults - ففي النهاية، قمت بتحديث صفين في جدول ORDER_ITEMS. في الواقع، يحتوي الصفان المحدثان على نفس order_id - أي أنهما ينتميان إلى نفس الترتيب. هنا، نفترض أن تطبيق العميل سيستخدم عبارة واحدة لتحديد كافة عناصر الطلب، لذلك لا يحتاج إلى معرفة عناصر الطلب التي تم تغييرها بالضبط. وبدلاً من ذلك، يحتاج العميل إلى معرفة معرف الطلب الذي تم تعديل أو حذف أو إدراج عنصر واحد فيه على الأقل.
بناء العميل
الآن بعد أن قمت بإنشاء تسجيلات لجدولي ORDERS وORDER_ITEMS، دعنا نلقي نظرة على كيفية استخدام إشعارات التغيير بواسطة تطبيقات العميل التي تصل إلى الطلبات وعناصرها المخزنة في هذه الجداول. للقيام بذلك، يمكنك إنشاء تطبيق PHP الذي سيقوم بتخزين نتائج الاستعلامات مقابل الجداول المذكورة أعلاه واتخاذ الإجراءات المناسبة استجابة للإشعارات حول التغييرات التي تطرأ على هذه الجداول (والتي يتم تلقيها من خادم قاعدة البيانات). إحدى الطرق السهلة هي استخدام حزمة PEAR::Cache_Lite، والتي توفر لك آلية موثوقة لتحديث بيانات ذاكرة التخزين المؤقت. على وجه الخصوص، يمكنك استخدام فئة Cache_Lite_Function (جزء من حزمة PEAR::Cache_Lite)، والتي تسمح لك بتخزين استدعاءات الوظائف مؤقتًا.
على سبيل المثال، يمكنك إنشاء دالة تؤدي المهام التالية: إنشاء اتصال بقاعدة البيانات، وتنفيذ عبارة تحديد على قاعدة البيانات، والحصول على نتائج البحث، وأخيرًا إرجاع النتائج كمصفوفة. يمكنك بعد ذلك تخزين صفائف النتائج التي ترجعها الوظيفة من خلال أسلوب الاستدعاء لمثيل Cache_Lite_Function بحيث يمكن قراءتها من ذاكرة التخزين المؤقت المحلية بدلاً من قاعدة البيانات الخلفية، مما قد يؤدي إلى تحسين أداء تطبيقك بشكل ملحوظ. بعد ذلك، عندما يتم إعلامك بالتغييرات التي تم إجراؤها على البيانات المخزنة مؤقتًا، ستستخدم طريقة الإسقاط لمثيل Cache_Lite_Function لحذف البيانات منتهية الصلاحية في ذاكرة التخزين المؤقت.
بالعودة إلى المثال الوارد في هذه المقالة، قد ترغب في إنشاء وظيفتين لتطبيقك للتفاعل مع قاعدة البيانات: ستقوم الوظيفة الأولى بالاستعلام عن جدول ORDERS وإرجاع الطلبات بالمعرف المحدد، بينما ستقوم الوظيفة الأخرى بالاستعلام عن ORDER_ITEMS الجدول والعودة إرجاع العناصر لهذا الطلب. تعرض "القائمة 4" البرنامج النصي getOrderFields.php الذي يحتوي على وظيفة getOrderFields، التي تقبل معرف الطلب وترجع مصفوفة ترابطية تحتوي على بعض حقول الطلب المسترد.
القائمة 4. احصل على الحقول بالترتيب المحدد
<?php
//الملف:getOrderFields.php
require_once 'connect.php';
وظيفة getOrderFields($order_no) {
إذا (!$rsConnection = GetConnection()){
عودة كاذبة.
}
$strSQL = "SELECT TO_CHAR(ORDER_DATE) ORDER_DATE, CUSTOMER_ID,
ORDER_TOTAL من الطلبات حيث order_id =:order_no";
$rsStatement = oci_parse($rsConnection,$strSQL);
oci_bind_by_name($rsStatement, ":order_no", $order_no, 12);
إذا (!oci_execute($rsStatement)) {
$err = oci_error();
طباعة $err['message'];
Trigger_error('فشل الاستعلام:' . $err['message']);
عودة كاذبة.
}
$results = oci_fetch_assoc($rsStatement);
إرجاع نتائج $؛
}
?>
"القائمة 5" هي البرنامج النصي getOrderItems.php. يحتوي البرنامج النصي على وظيفة getOrderItems، التي تقبل معرف الطلب وترجع مصفوفة ثنائية الأبعاد تحتوي على صفوف تمثل عناصر الطلب.
القائمة 5. احصل على بنود الترتيب المحدد
<?php
//الملف:getOrderItems.php
require_once 'connect.php';
وظيفة getOrderItems($order_no) {
إذا (!$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);
إذا (!oci_execute($rsStatement)) {
$err = oci_error();
Trigger_error('فشل الاستعلام:' . $err['message']);
عودة كاذبة.
}
$nrows = oci_fetch_all($rsStatement, $results);
صفيف الإرجاع ($nrows، $results)؛
}
?>
لاحظ أن كلتا الوظيفتين المذكورتين أعلاه تتطلبان البرنامج النصي Connect.php، الذي يجب أن يحتوي على وظيفة GetConnection التي تُرجع اتصال قاعدة البيانات. القائمة 6 هي البرنامج النصي Connect.php:
القائمة 6. الحصول على اتصال قاعدة البيانات
<?php
// الملف:connect.php
وظيفة جيتكونيكشن () {
$dbHost = "dbserverhost";
$dbHostPort="1521";
$dbServiceName = "orclR2";
$usr = "oe";
$pswd = "oe";
$dbConnStr = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$dbHost.")
(PORT=".$dbHostPort."))(CONNECT_DATA=(SERVICE_NAME=".$dbServiceName.")))";
إذا(!$dbConn = oci_connect($usr,$pswd,$dbConnStr)) {
$err = oci_error();
Trigger_error('فشل الاتصال' .$err['message']);
عودة كاذبة.
}
إرجاع $dbConn؛
}
?>
الآن بعد أن قمت بإنشاء جميع الوظائف اللازمة للتواصل مع قاعدة البيانات، دعنا نلقي نظرة على كيفية عمل فئة Cache_Lite_Function. القائمة 7 هي البرنامج النصي testCache.php الذي يستخدم فئة Cache_Lite_Function لتخزين نتائج الوظيفة المذكورة أعلاه مؤقتًا.
<?php
باستخدام PEAR::Cache_Lite
//ملف:testCache.php
require_once 'getOrderItems.php'؛
require_once 'getOrderFields.php'؛
require_once 'Cache/Lite/Function.php';
$options = array(
'cacheDir' => '/tmp/',
"مدة الحياة" => 86400
);
إذا (!isset($_GET['order_no'])) {
die("معلمة order_no مطلوبة");
}
$order_no=$_GET['order_no'];
$cache = new Cache_Lite_Function($options);
إذا ($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";
بينما (قائمة(مفتاح $، قيمة $) = كل($orderitems)) {
طباعة "<th>$key</th>n";
}
طباعة "</tr>n";
لـ ($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);
}
?>
يجب استدعاء البرنامج النصي testCache.php الموجود في "القائمة 7" باستخدام معلمة URL order_no (التي تمثل معرف الطلب المخزن في جدول OE.ORDER). على سبيل المثال، لاسترداد المعلومات المتعلقة بالطلب بالمعرف 2408، يمكنك إدخال عنوان URL التالي في متصفحك:
http://webserverhost/phpcache/testCache.php?order_no=2408 ونتيجة لذلك، سيقوم المتصفح بإنشاء المخرجات التالية :
الأمر رقم 2408
التاريخ: 29 يونيو 99 06.59.31.333617 صباحًا
معرف العميل: 166
الإجمالي: 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 الآن
، إذا قمت بالنقر فوق زر إعادة التحميل في المتصفح، فلن يقوم البرنامج النصي testCache.php باستدعاء وظائف getOrderFields وgetOrderItems مرة أخرى. بدلاً من ذلك، سيتم قراءة نتائجها من ذاكرة التخزين المؤقت المحلية. لذلك، سيتم تلبية كل استدعاء getOrderFields أو getOrderItems مع order_no=2108 بواسطة ذاكرة التخزين المؤقت المحلية خلال 24 ساعة من الآن (نظرًا لأنه تم ضبط lifeTime على 86400 ثانية). ومع ذلك، لاحظ أن فئة Cache_Lite_Function لا توفر واجهة برمجة التطبيقات (API) لاختبار ما إذا كانت ذاكرة التخزين المؤقت متاحة لوظيفة معينة مع معلمات معينة. لذلك، قد يكون من الصعب بعض الشيء تحديد ما إذا كان التطبيق يقرأ ذاكرة التخزين المؤقت بالفعل أم أنه لا يزال ينفذ الوظيفة في كل مرة يتم استدعاؤها بنفس المعلمات. على سبيل المثال، في المثال أعلاه، للتأكد من أن آلية التخزين المؤقت تعمل بشكل صحيح، يمكنك تغيير معلومات الاتصال المحددة في البرنامج النصي Connect.php مؤقتًا بحيث لا تتمكن من إنشاء اتصال قاعدة البيانات، على سبيل المثال، تحديد اسم مضيف خادم قاعدة بيانات خاطئ؛ ، ثم استخدم order_no= مرة أخرى 2108 قم بتشغيل البرنامج النصي testCache.php. إذا كان التخزين المؤقت يعمل بشكل صحيح، فيجب أن يكون مخرج المتصفح هو نفسه كما كان من قبل.
بالإضافة إلى ذلك، يمكنك التحقق من دليل ذاكرة التخزين المؤقت الذي تم تمريره إلى مُنشئ فئة Cache_Lite_Function كقيمة خيار CacheDir (/tmp في هذا المثال). ستجد في هذا الدليل ملفين من ملفات ذاكرة التخزين المؤقت التي قمت بإنشائها للتو بأسماء مشابهة لـ: Cache_7b181b55b55aee36ad5e7bd9d5a091ec_3ad04d3024f4cd54296f75c92a359154. لاحظ أنه إذا كنت من مستخدمي 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 = new Cache_Lite_Function($options);
إذا (isset($_GET['order_no'])&& isset($_GET['table'])) {
إذا($_GET['table']=='ORDER_ITEMS'){
$cache->drop('getOrderItems', $_GET['order_no']);
}
إذا ($_GET['table']=='ORDERS'){
$cache->drop('getOrderFields', $_GET['order_no']);
}
}
?>
بعد إنشاء البرنامج النصي dropResult.php، تأكد من صحة عنوان URL المحدد في معالج الإشعارات (الموضح في القائمة 2). بعد ذلك، اتصل كـ OE/OE في SQL*Plus أو أداة مشابهة وقم بتنفيذ عبارات UPDATE التي ستؤثر على نفس الطلبات التي تم الوصول إليها مسبقًا في هذا القسم من خلال البرنامج النصي testCache.php (هنا الترتيب بالمعرف 2408):
UPDATE ORDERS SET order_mode = ' مباشر' حيث order_id=2408;
تحديث كمية مجموعة ORDER_ITEMS = 3 حيث order_id=2408 وline_item_id=1؛
تحديث كمية مجموعة ORDER_ITEMS = 1 حيث order_id=2408 وline_item_id=2؛
يقترف؛
استجابة للتحديث أعلاه، سيقوم معالج الإشعارات الموضح سابقًا في هذه المقالة بتشغيل البرنامج النصي dropResults.php مرتين، باستخدام عناوين URL التالية: http://webserverhost/phpcache/dropResults.php?order_no=2408&table=ORDERS
http://webserverhost/phpcache/dropresults.php?order_no=2408&table=ORDER_ITEMS
من "القائمة 8" يمكنك أن ترى بوضوح أن البرنامج النصي dropResult.php لا يقوم بمسح ذاكرة التخزين المؤقت بعد تلقي إشعار التغيير من خادم قاعدة البيانات. إنه يقوم فقط بحذف ملفات ذاكرة التخزين المؤقت التي تحتوي على بيانات منتهية الصلاحية. لذا، إذا قمت بفحص دليل ذاكرة التخزين المؤقت الآن، سترى أن ملف ذاكرة التخزين المؤقت الذي تم إنشاؤه عند تشغيل البرنامج النصي testCache.php مع order_no=2408 قد اختفى. ما يعنيه هذا بشكل أساسي هو أنه في المرة التالية التي يطلب فيها testCache.php البيانات المتعلقة بمعرف الطلب 2408، فإنه سيحصل على تلك البيانات من قاعدة البيانات الخلفية بدلاً من ذاكرة التخزين المؤقت المحلية.
قد تجد هذه الطريقة مفيدة في المواقف التي من المحتمل أن تتغير فيها مجموعة النتائج التي يطلبها التطبيق قبل أن يستخدمها التطبيق. ولأغراض مثال هذه المقالة، فهذا يعني أن البيانات المتعلقة بترتيب معين قد تتغير عدة مرات قبل وصول testCache.php إلى هذا الطلب. بهذه الطريقة، يقوم التطبيق بالكثير من العمل غير الضروري عن طريق مسح ذاكرة التخزين المؤقت الخاصة به فورًا بعد تلقي إشعارات التغيير من خادم قاعدة البيانات.
ولكن إذا كنت تريد أن يقوم البرنامج النصي dropResult.php بمسح ذاكرة التخزين المؤقت بمجرد إخطاره بالتغيير، فيمكنك استدعاء أسلوب الاستدعاء لمثيل Cache_Lite_Function بعد استدعاء أسلوب الإسقاط، مع تحديد نفس المعلمات لكلا الاستدعاءين. في هذه الحالة، يجب عليك أيضًا التأكد من تضمين البرامج النصية getOrderFields.php وgetOrderItems.php بحيث يمكن لـ dropResults.php استدعاء وظائف getOrderFields وgetOrderItems لتحديث ذاكرة التخزين المؤقت. "القائمة 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/',
"مدة الحياة" => 86400
);
$cache = new Cache_Lite_Function($options);
إذا (isset($_GET['order_no'])&& isset($_GET['table'])) {
إذا($_GET['table']=='ORDER_ITEMS'){
$cache->drop('getOrderItems', $_GET['order_no']);
$cache->call('getOrderItems', $_GET['order_no']);
}
إذا ($_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 على الكائن المرتبط بالطلب المقدم. باستخدام هذه الميزة، لا يتعين عليك تحديث ذاكرة التخزين المؤقت في تطبيقك خلال فترة زمنية محددة. بدلاً من ذلك، يتم تنفيذ العملية فقط إذا تغيرت مجموعة نتائج الاستعلام المسجل.