Diketahui bahwa menyimpan hasil kueri basis data secara signifikan dapat mengurangi waktu eksekusi skrip dan meminimalkan beban pada server basis data. Teknik ini bekerja sangat baik jika data yang Anda proses pada dasarnya bersifat statis. Hal ini karena banyak permintaan data ke database jarak jauh pada akhirnya dapat dipenuhi dari cache lokal, sehingga menghilangkan kebutuhan untuk menyambung ke database, menjalankan kueri, dan mendapatkan hasilnya.
Namun menyimpan kumpulan hasil basis data dalam cache sering kali merupakan ide bagus ketika basis data yang Anda gunakan berada di komputer yang berbeda dari server Web. Namun, menentukan strategi caching terbaik untuk situasi Anda bisa jadi sulit. Misalnya, untuk aplikasi yang memerlukan kumpulan hasil database terbaru, pendekatan caching yang dipicu waktu (umumnya digunakan oleh sistem caching yang berasumsi bahwa cache dibuat ulang setiap kali stempel waktu kedaluwarsa tercapai) mungkin bukan solusi yang memuaskan. . Dalam hal ini, Anda memerlukan mekanisme yang akan memberi tahu aplikasi setiap kali data database yang perlu di-cache oleh aplikasi berubah, sehingga aplikasi dapat menjaga data kedaluwarsa yang di-cache tetap konsisten dengan database. Dalam hal ini menggunakan "Pemberitahuan Perubahan Basis Data" akan sangat mudah.
Memulai Notifikasi Perubahan Basis Data
Penggunaan fitur Notifikasi Perubahan Basis Data sangat sederhana: Buat pengendali notifikasi yang menjalankan notifikasi – prosedur tersimpan PL/SQL atau fungsi panggilan balik OCI klien. Kemudian, daftarkan kueri terhadap objek database yang ingin Anda terima notifikasi perubahannya, sehingga pengendali notifikasi dipanggil setiap kali transaksi mengubah objek apa pun di dalamnya dan dilakukan. Biasanya, pengendali notifikasi mengirimkan nama tabel yang telah diubah, jenis perubahan yang dilakukan, dan secara opsional ID baris dari baris yang diubah ke pendengar klien sehingga aplikasi klien dapat melakukan tindakan yang sesuai dalam menangani respons.
Untuk memahami cara kerja fitur Pemberitahuan Perubahan Basis Data, perhatikan contoh berikut. Asumsikan aplikasi PHP Anda mengakses pesanan yang disimpan di tabel OE.ORDERS dan item pesanan disimpan di OE.ORDER_ITEMS. Mengingat informasi tentang pesanan yang ditempatkan jarang berubah, Anda mungkin ingin aplikasi Anda menyimpan kumpulan hasil kueri dalam cache terhadap tabel ORDERS dan ORDER_ITEMS. Untuk menghindari akses data lama, Anda dapat menggunakan Pemberitahuan Perubahan Basis Data, yang memungkinkan aplikasi Anda dengan mudah diberi tahu tentang perubahan pada data yang disimpan dalam dua tabel di atas.
Anda harus memberikan izin sistem CHANGE NOTIFICATION dan izin EXECUTE ON DBMS_CHANGENOTIFICATION kepada pengguna OE sebelum Anda dapat mendaftarkan kueri untuk tabel ORDERS dan ORDER_ITEMS untuk menerima pemberitahuan dan merespons perubahan DML atau DDL pada tabel ini. Untuk melakukannya, jalankan perintah berikut dari alat baris perintah SQL seperti SQL*Plus.
MENGHUBUNGKAN/SEBAGAI SYSDBA;
HIBAH PEMBERITAHUAN PERUBAHAN KEPADA oe;
GRANT EXECUTE PADA DBMS_CHANGE_NOTIFICATION KEPADA oe;
Pastikan parameter init.ora job_queue_processes diatur ke nilai bukan nol untuk menerima notifikasi PL/SQL. Alternatifnya, Anda dapat menggunakan perintah ALTER SYSTEM berikut:
ALTER SYSTEM SET "job_queue_processes"=2; Kemudian, setelah terhubung sebagai OE/OE, Anda dapat membuat pengendali notifikasi. Namun pertama-tama, Anda harus membuat objek database yang akan digunakan oleh penangan notifikasi. Misalnya, Anda mungkin ingin membuat satu atau beberapa tabel database tempat pengendali notifikasi mencatat perubahan registri. Dalam contoh berikut, Anda membuat tabel nfresults untuk mencatat tanggal dan waktu perubahan terjadi, nama tabel yang diubah, dan pesan yang menunjukkan apakah pengendali notifikasi berhasil mengirim pesan notifikasi ke klien.
HUBUNGKAN oe/oe;
BUAT TABEL hasil (
dioperasikanDATE,
namatbl VARCHAR2(60),
rslt_msg VARCHAR2(100)
);
Dalam skenario dunia nyata, Anda mungkin perlu membuat lebih banyak tabel untuk mencatat informasi seperti peristiwa notifikasi dan ID baris dari baris yang diubah, namun untuk tujuan artikel ini, tabel nfresults sudah cukup.
Menggunakan UTL_HTTP untuk mengirim notifikasi ke klien
Anda juga dapat membuat satu atau lebih prosedur tersimpan PL/SQL dan memanggil prosedur tersimpan ini dari pengendali notifikasi, sehingga mencapai solusi yang lebih mudah dipelihara dan fleksibel. Misalnya, Anda mungkin ingin membuat prosedur tersimpan yang mengimplementasikan pengiriman pesan notifikasi ke klien. "Listing 1" adalah prosedur PL/SQL sendNotification. Proses ini menggunakan paket UTL_HTTPPL untuk mengirimkan pemberitahuan perubahan ke aplikasi klien.
Listing 1. Kirim notifikasi ke klien menggunakan UTL_HTTPCREATE
OR REPLACE PROCEDURE sendNotification(url IN VARCHAR2,
tblname DI VARCHAR2, order_id DI VARCHAR2) IS
req UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
err_msg VARCHAR2(100);
tblVARCHAR(60);
MULAI
tbl:=SUBSTR(namatbl, INSTR(namatbl, '.', 1, 1)+1, 60);
MULAI
req := UTL_HTTP.BEGIN_REQUEST(url||order_id||'&'||'table='||tbl);
resp := UTL_HTTP.GET_RESPONSE(persyaratan);
MASUKKAN KE NILAI nfresults(SYSDATE, tblname, resp.reason_phrase);
UTL_HTTP.END_RESPONSE(jawaban);
PENGECUALIAN KETIKA ORANG LAIN LALU
err_msg := SUBSTR(SQLERRM, 1, 100);
MASUKKAN KE NILAI nfresults(SYSDATE, tblname, err_msg);
AKHIR;
MELAKUKAN;
AKHIR;
/
Seperti yang ditunjukkan pada "Listing 1", sendNotification mengirimkan pesan notifikasi ke klien dalam bentuk permintaan HTTP yang dikeluarkan oleh fungsi UTL_HTTP.BEGIN_REQUEST. URL ini berisi order_id dari baris yang diubah di tabel ORDERS. Kemudian menggunakan UTL_HTTP.GET_RESPONSE untuk mendapatkan informasi respons yang dikirim oleh klien. Faktanya, sendNotification tidak perlu memproses seluruh respons yang dikembalikan oleh klien, tetapi hanya memperoleh pesan singkat (menjelaskan kode status) yang disimpan di bidang Reason_phrase pada catatan RESP.
Membuat Pengendali Notifikasi
Sekarang Anda dapat membuat pengendali notifikasi yang akan mengirimkan notifikasi perubahan ke klien dengan bantuan prosedur sendNotification yang dijelaskan di atas. Mari kita lihat prosedur PL/SQL order_nf_callback di "Listing 2".
Listing 2. Pengendali notifikasi yang menangani notifikasi perubahan pada tabel OE.ORDERS
CREATE OR REPLACE PROCEDURE order_nf_callback (ntfnds IN SYS.CHNF$_DESC) IS
namatbl VARCHAR2(60);
tabel angka NOMOR;
tipe_acara NUMBER;
baris_id VARCHAR2(20);
angka NOMOR;
ord_id VARCHAR2(12);
url VARCHAR2(256) := 'http://webserverhost/phpcache/dropResults.php?order_no=';
MULAI
tipe_acara := ntfnds.tipe_acara;
nomor tabel := ntfnds.jumlah tabel;
JIKA (event_type = DBMS_CHANGE_NOTIFICATION.EVENT_OBJCHANGE) MAKA
UNTUK saya DALAM 1..numtables LOOP
namatbl := ntfnds.table_desc_array(i).nama_tabel;
JIKA (bitand(ntfnds.table_desc_array(i).opflags,
DBMS_CHANGE_NOTIFICATION.ALL_ROWS) = 0) LALU
angka := ntfnds.table_desc_array(i).angka baris;
KALAU TIDAK
angka :=0;
AKHIR JIKA;
JIKA (tblname = 'OE.ORDERS') MAKA
UNTUK j DALAM 1..angka LOOP
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
PILIH order_id KE ord_id DARI pesanan WHERE rowid = row_id;
sendNotification(url, namatbl, ord_id);
LOOP AKHIR;
AKHIR JIKA;
LOOP AKHIR;
AKHIR JIKA;
MELAKUKAN;
AKHIR;
/
Seperti yang ditunjukkan pada "Daftar 2", pengendali notifikasi ini menggunakan objek SYS.CHNF$_DESC sebagai parameter dan kemudian menggunakan propertinya untuk mendapatkan detail perubahan. Dalam contoh ini, pengendali notifikasi ini hanya akan menangani notifikasi yang diposting oleh database sebagai respons terhadap perubahan DML atau DDL pada objek yang terdaftar (yaitu, hanya jika jenis notifikasinya adalah EVENT_OBJCHANGE), dan mengabaikan informasi tentang kejadian database lain seperti startup instance atau misalnya shutdown) pemberitahuan. Dimulai dengan versi di atas, handler dapat menangani pemberitahuan perubahan yang dikeluarkan untuk setiap baris yang terpengaruh dalam tabel OE.ORDERS. Nanti di artikel ini, di bagian "Menambahkan tabel ke registrasi yang sudah ada", Anda akan menambahkan beberapa baris kode ke handler sehingga dapat menangani notifikasi untuk baris yang diubah di tabel OE.ORDER_ITEMS.
Membuat registrasi untuk notifikasi perubahan
Setelah Anda membuat pengendali notifikasi, Anda harus membuat registrasi kueri untuknya. Untuk contoh ini, Anda harus melakukan kueri pada tabel OE.ORDER selama proses registrasi dan menentukan order_nf_callback sebagai pengendali notifikasi. Anda juga perlu menentukan opsi QOS_ROWIDS dalam paket DBMS_CHANGE_NOTIFICATION untuk mengaktifkan perincian tingkat ROWID dalam pesan notifikasi. "Listing 3" adalah blok PL/SQL yang membuat registrasi kueri untuk pengendali notifikasi order_nf_callback.
Listing 3. Buat registrasi queryDECLARE
untuk pengendali notifikasi
REGDS SYS.CHNF$_REG_INFO;
NOMOR Registrasi;
ord_id NOMOR;
qosflag NOMOR;
MULAI
qosflags := DBMS_CHANGE_NOTIFICATION.QOS_RELIABLE +
DBMS_CHANGE_NOTIFICATION.QOS_ROWIDS;
REGDS := SYS.CHNF$_REG_INFO('orders_nf_callback', qosflags, 0,0,0);
reid := DBMS_CHANGE_NOTIFICATION.NEW_REG_START (REGDS);
PILIH order_id KE ord_id DARI pesanan DI MANA ROWNUM<2;
DBMS_CHANGE_NOTIFICATION.REG_END;
AKHIR;
/
Contoh ini membuat registrasi terhadap tabel ORDERS dan menggunakan order_nf_callback sebagai pengendali notifikasi. Sekarang, jika Anda menggunakan pernyataan DML atau DDL untuk mengubah tabel ORDERS dan melakukan transaksi, fungsi order_nf_callback dipanggil secara otomatis. Misalnya, Anda mungkin menjalankan pernyataan UPDATE berikut terhadap tabel ORDERS dan melakukan transaksi:
UPDATE ORDERS SET order_mode = 'direct' WHERE order_id=2421;
PERBARUI PESANAN SET order_mode = 'direct' WHERE order_id=2422;
MELAKUKAN;
Untuk memastikan bahwa database memposting notifikasi sebagai respons terhadap transaksi di atas, Anda dapat memeriksa tabel nfresults:
SELECT TO_CHAR(operdate, 'dd-mon-yy hh:mi:ss') operdate,
tblname, rslt_msg DARI nfresults;
Hasilnya akan terlihat seperti ini:
OPERDATE TBLNAME RSLT_MSG
--------------------- ---------- ---------
02-mar-06 04:31:28 OE.PESANAN Tidak Ditemukan
02-mar-06 04:31:29 OE.PESANAN Tidak Ditemukan
Dari hasil di atas terlihat jelas bahwa order_nf_callback sudah berfungsi tetapi skrip klien tidak ditemukan. Hal ini biasa terjadi dalam contoh ini karena Anda tidak membuat skrip dropResults.php yang ditentukan dalam URL. Untuk petunjuk tentang skrip dropResults.php, lihat bagian Membangun Klien nanti di artikel ini.
Menambahkan tabel ke registrasi yang sudah ada
Bagian sebelumnya menunjukkan cara menggunakan Layanan Pemberitahuan Perubahan agar database memberi tahu Anda ketika objek registrasi (dalam contoh di atas, tabel ORDERS) berubah. Namun dari sudut pandang kinerja, aplikasi klien mungkin lebih memilih untuk menyimpan kumpulan hasil kueri tabel ORDER_ITEMS daripada tabel ORDERS itu sendiri, karena aplikasi klien hanya perlu mengambil satu baris dari tabel ORDERS setiap kali mengakses pesanan, tetapi pada saat yang sama pada saat yang sama Beberapa baris harus diambil dari tabel ORDER_ITEMS. Pada kenyataannya, sebuah pesanan mungkin berisi lusinan atau bahkan ratusan item baris.
Karena Anda telah mendaftarkan kueri terhadap tabel ORDERS, Anda tidak perlu membuat registrasi untuk mendaftarkan kueri terhadap tabel ORDER_ITEMS. Sebagai gantinya, Anda dapat menggunakan registrasi yang sudah ada. Untuk melakukan ini, Anda harus terlebih dahulu mengambil ID pendaftaran yang ada. Anda dapat menjalankan query berikut untuk mencapai hal ini:
SELECT regid, table_name FROM user_change_notification_regs Hasilnya mungkin terlihat seperti ini:
REGID TABLE_NAME
----- --------------
241 OE. PESANAN
Setelah mendapatkan ID registrasi, Anda dapat menambahkan objek baru pada registrasi menggunakan fungsi DBMS_CHANGE_NOTIFICATION.ENABLE_REG sebagai berikut:
DECLARE
ord_id NOMOR;
MULAI
DBMS_CHANGE_NOTIFICATION.ENABLE_REG(241);
PILIH order_id KE ord_id DARI order_items DI MANA ROWNUM < 2;
DBMS_CHANGE_NOTIFICATION.REG_END;
AKHIR;
/
Selesai! Mulai sekarang, database akan menghasilkan notifikasi sebagai respons terhadap setiap perubahan yang dilakukan pada ORDERS dan ORDER_ITEMS, dan memanggil prosedur order_nf_callback untuk menangani notifikasi tersebut. Oleh karena itu, langkah selanjutnya adalah mengedit order_nf_callback agar dapat menangani notifikasi yang dihasilkan oleh operasi DML pada tabel ORDER_ITEMS. Namun sebelum membuat ulang prosedur order_nf_callback, Anda perlu membuat tipe tabel berikut yang akan direferensikan selama proses pembaruan:
CREATE TYPE rdesc_tab AS TABLE OF SYS.CHNF$_RDESC Kemudian, kembali ke Listing 2, setelah baris berikut kode:
IF (tblname = 'OE.ORDERS') THEN
UNTUK j DALAM 1..angka LOOP
row_id := ntfnds.table_desc_array(i).row_desc_array(j).row_id;
PILIH order_id KE ord_id DARI pesanan WHERE rowid = row_id;
sendNotification(url, namatbl, ord_id);
LOOP AKHIR;
AKHIR JIKA;
Masukkan kode berikut:
IF (tblname = 'OE.ORDER_ITEMS') THEN
UNTUK rec IN (PILIH BERBEDA(o.order_id) o_id DARI
TABEL(CAST(ntfnds.table_desc_array(i).row_desc_array AS rdesc_tab)) t,
pesanan o, pesanan_barang d DIMANA t.row_id = d.rowid DAN d.order_id=o.order_id)
LINGKARAN
sendNotification(url, tblname, rec.o_id);
LOOP AKHIR;
AKHIR JIKA;
Setelah membuat ulang order_nf_callback, Anda perlu menguji apakah itu berfungsi dengan benar. Untuk melakukan hal ini, Anda dapat menjalankan pernyataan UPDATE berikut terhadap tabel ORDER_ITEMS dan melakukan transaksi:
UPDATE ORDER_ITEMS SET quantity = 160 WHERE order_id=2421 AND line_item_id=1;
UPDATE ORDER_ITEMS SET kuantitas = 160 DIMANA order_id=2421 DAN line_item_id=2;
MELAKUKAN;
Kemudian periksa tabel nfresults sebagai berikut:
SELECT TO_CHAR(operdate, 'dd-mon-yy hh:mi:ss') operdate,
rslt_msg FROM nfresults WHERE tblname = 'OE.ORDER_ITEMS'; Outputnya mungkin terlihat seperti ini:
OPERDATE RSLT_MSG
-----------------------------------
03-mar-06 12:32:27 Tidak Ditemukan
Anda mungkin bertanya-tanya mengapa hanya satu baris yang dimasukkan ke dalam tabel nfresults – lagipula, Anda memperbarui dua baris dalam tabel ORDER_ITEMS. Faktanya, dua baris yang diperbarui memiliki order_id yang sama - yaitu keduanya termasuk dalam pesanan yang sama. Di sini, kami berasumsi bahwa aplikasi klien akan menggunakan satu pernyataan untuk memilih semua item baris pesanan, sehingga tidak perlu mengetahui secara pasti item baris pesanan mana yang telah diubah. Sebaliknya, klien perlu mengetahui ID pesanan tempat setidaknya satu item baris diubah, dihapus, atau disisipkan.
Membangun klien
Sekarang Anda telah membuat registrasi untuk tabel ORDERS dan ORDER_ITEMS, mari kita lihat bagaimana pemberitahuan perubahan digunakan oleh aplikasi klien yang mengakses pesanan dan item barisnya yang disimpan dalam tabel ini. Untuk melakukan ini, Anda dapat membangun aplikasi PHP yang akan menyimpan hasil kueri terhadap tabel di atas dalam cache dan mengambil tindakan yang sesuai sebagai respons terhadap pemberitahuan tentang perubahan pada tabel ini (yang diterima dari server database). Cara mudahnya adalah dengan menggunakan paket PEAR::Cache_Lite, yang memberi Anda mekanisme andal untuk selalu memperbarui data cache. Secara khusus, Anda dapat menggunakan kelas Cache_Lite_Function (bagian dari paket PEAR::Cache_Lite), yang memungkinkan Anda melakukan cache panggilan fungsi.
Misalnya, Anda bisa membuat fungsi yang melakukan tugas-tugas berikut: membuat koneksi database, mengeksekusi pernyataan pemilihan terhadap database, memperoleh hasil pencarian, dan akhirnya mengembalikan hasilnya sebagai array. Anda kemudian dapat meng-cache array hasil yang dikembalikan oleh fungsi melalui metode panggilan instance Cache_Lite_Function sehingga array tersebut dapat dibaca dari cache lokal dan bukan dari database back-end, yang dapat meningkatkan kinerja aplikasi Anda secara signifikan. Kemudian, ketika Anda diberitahu tentang perubahan pada data cache, Anda akan menggunakan metode drop dari instance Cache_Lite_Function untuk menghapus data kadaluarsa di cache.
Kembali ke contoh dalam artikel ini, Anda mungkin ingin membuat dua fungsi agar aplikasi Anda dapat berinteraksi dengan database: fungsi pertama akan menanyakan tabel ORDERS dan mengembalikan pesanan dengan ID yang ditentukan, sedangkan fungsi lainnya akan menanyakan ORDER_ITEMS table and return Mengembalikan item baris untuk pesanan ini. "Listing 4" menunjukkan skrip getOrderFields.php yang berisi fungsi getOrderFields, yang menerima ID pesanan dan mengembalikan array asosiatif yang berisi beberapa bidang pesanan yang diambil.
Listing 4. Dapatkan field dengan urutan yang ditentukan
<?php
//File:getOrderFields.php
require_once 'connect.php';
fungsi getOrderFields($order_no) {
jika (!$rsConnection = GetConnection()){
kembali salah;
}
$strSQL = "PILIH TO_CHAR(ORDER_DATE) ORDER_DATE, CUSTOMER_ID,
ORDER_TOTAL DARI PESANAN DI MANA order_id =:order_no";
$rsStatement = oci_parse($rsConnection,$strSQL);
oci_bind_by_name($rsStatement, ":order_no", $order_no, 12);
jika (!oci_execute($rsStatement)) {
$err = oci_error();
cetak $err['pesan'];
trigger_error('Permintaan gagal:' .$err['pesan']);
kembali salah;
}
$hasil = oci_fetch_assoc($rsStatement);
kembalikan $hasil;
}
?>
"Listing 5" adalah skrip getOrderItems.php. Skrip berisi fungsi getOrderItems, yang menerima ID pesanan dan mengembalikan array dua dimensi yang berisi baris yang mewakili item baris pesanan.
Listing 5. Dapatkan item baris dari pesanan yang ditentukan
<?php
//File:getOrderItems.php
require_once 'connect.php';
fungsi getOrderItems($order_no) {
jika (!$rsConnection = GetConnection()){
kembali salah;
}
$strSQL = "PILIH * DARI ORDER_ITEMS DIMANA
order_id =:order_no ORDER BERDASARkan line_item_id";
$rsStatement = oci_parse($rsConnection,$strSQL);
oci_bind_by_name($rsStatement, ":order_no", $order_no, 12);
jika (!oci_execute($rsStatement)) {
$err = oci_error();
trigger_error('Permintaan gagal:' .$err['pesan']);
kembali salah;
}
$nrows = oci_fetch_all($rsStatement, $hasil);
mengembalikan array ($sekarang, $hasil);
}
?>
Perhatikan bahwa kedua fungsi di atas memerlukan skrip connect.php, yang harus berisi fungsi GetConnection yang mengembalikan koneksi database. Listing 6 adalah skrip connect.php:
Listing 6. Dapatkan koneksi database
<?php
//File:connect.php
fungsi DapatkanKoneksi() {
$dbHost = "dbserverhost";
$dbHostPort="1521";
$dbServiceName = "orclR2";
$usr = "oe";
$pswd = "oe";
$dbConnStr = "(DESKRIPSI=(ALAMAT=(PROTOCOL=TCP)(HOST=".$dbHost.")
(PORT=".$dbHostPort."))(CONNECT_DATA=(SERVICE_NAME=".$dbServiceName.")))";
if(!$dbConn = oci_connect($usr,$pswd,$dbConnStr)) {
$err = oci_error();
trigger_error('Gagal menghubungkan ' .$err['pesan']);
kembali salah;
}
kembalikan $dbConn;
}
?>
Sekarang Anda telah membuat semua fungsi yang diperlukan untuk berkomunikasi dengan database, mari kita lihat cara kerja kelas Cache_Lite_Function. Listing 7 adalah skrip testCache.php yang menggunakan kelas Cache_Lite_Function untuk menyimpan hasil fungsi di atas dalam cache.
<?php
menggunakan PEAR::Cache_Lite
//File:testCache.php
require_once 'getOrderItems.php';
require_once 'getOrderFields.php';
require_once 'Cache/Lite/Function.php';
$pilihan = array(
'cacheDir' => '/tmp/',
'Seumur Hidup' => 86400
);
jika (!isset($_GET['tidak_pesanan'])) {
die('Parameter order_no diperlukan');
}
$pesanan_tidak=$_GET['tidak_pesanan'];
$cache = Cache_Lite_Function baru($pilihan);
if ($orderfields = $cache->call('getOrderFields', $order_no)){
print "<h3>PESANAN #$jumlah_pesanan</h3>n";
cetak "<tabel>";
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>";
cetak "</tabel>";
} kalau tidak {
print "Terjadi masalah saat mengambil kolom pesanan!n";
$cache->jatuhkan('getOrderFields', $order_no);
}
if (daftar($nrows, $orderitems) = $cache->panggilan('getOrderItems', $order_no)){
//print "<h3>ITEM LINE DALAM PESANAN #$order_no</h3>";
print "<batas tabel=1>";
cetak "<tr>n";
while (daftar($kunci, $nilai) = masing-masing($barang pesanan)) {
print "<th>$key</th>n";
}
cetak "</tr>n";
untuk ($i = 0; $i < $nrows; $i++) {
cetak "<tr>";
cetak "<td>".$orderitems['ORDER_ID'][$i]."</td>";
cetak "<td>".$orderitems['LINE_ITEM_ID'][$i]."</td>";
cetak "<td>".$orderitems['PRODUK_ID'][$i]."</td>";
print "<td>".$orderitems['UNIT_PRICE'][$i]."</td>";
print "<td>".$orderitems['QUANTITY'][$i]."</td>";
cetak "</tr>";
}
cetak "</tabel>";
} kalau tidak {
print "Terjadi masalah saat mengambil item baris pesanan";
$cache->jatuhkan('getOrderItems', $order_no);
}
?>
Skrip testCache.php di "Listing 7" harus dipanggil dengan parameter URL order_no (mewakili ID pesanan yang disimpan dalam tabel OE.ORDER). Misalnya, untuk mengambil informasi terkait pesanan dengan ID 2408, Anda akan memasukkan URL berikut ke browser Anda:
http://webserverhost/phpcache/testCache.php?order_no=2408 Hasilnya, browser akan menghasilkan output berikut :
PESANAN #2408
TANGGAL: 29-JUN-99 06.59.31.333617 pagi
CUST_ID: 166
TOTAL: 309
ORDER_ID LINE_ITEM_ID PRODUK_ID UNIT_HARGA JUMLAH
2408 1 2751 61 3
2408 2 2761 26 1
2408 3 2783 10 10Sekarang
, jika Anda mengklik tombol muat ulang di browser, skrip testCache.php tidak akan memanggil fungsi getOrderFields dan getOrderItems lagi. Sebaliknya, ia akan membaca hasilnya dari cache lokal. Oleh karena itu, setiap panggilan getOrderFields atau getOrderItems dengan order_no=2108 akan dipenuhi oleh cache lokal dalam waktu 24 jam dari sekarang (karena lifeTime disetel ke 86400 detik). Namun perlu diperhatikan bahwa kelas Cache_Lite_Function tidak menyediakan API untuk menguji apakah cache tersedia untuk fungsi tertentu dengan parameter tertentu. Oleh karena itu, mungkin agak sulit untuk menentukan apakah aplikasi benar-benar membaca cache atau masih menjalankan fungsi tersebut setiap kali dipanggil dengan parameter yang sama. Misalnya, dalam contoh di atas, untuk memastikan mekanisme caching berfungsi dengan baik, Anda dapat mengubah sementara informasi koneksi yang ditentukan dalam skrip connect.php sehingga tidak dapat membuat koneksi database, misalnya menentukan nama host server database yang salah , lalu gunakan order_no= lagi 2108 Jalankan skrip testCache.php. Jika caching berfungsi dengan baik, output browser akan sama seperti sebelumnya.
Selain itu, Anda dapat memeriksa direktori cache yang diteruskan ke konstruktor kelas Cache_Lite_Function sebagai nilai opsi cacheDir (/tmp dalam contoh ini). Di direktori itu Anda akan menemukan dua file cache yang baru saja Anda buat dengan nama yang mirip dengan: cache_7b181b55b55aee36ad5e7bd9d5a091ec_3ad04d3024f4cd54296f75c92a359154. Perhatikan bahwa jika Anda pengguna Windows, Anda mungkin ingin menggunakan direktori %SystemDrive%temp untuk menyimpan file cache. Jika demikian, opsi cacheDir harus disetel ke /temp/.
Setelah memverifikasi bahwa mekanisme caching berfungsi dengan baik, Anda kemudian dapat membuat PHP untuk menangani notifikasi perubahan yang diterima dari server database. "Listing 8" adalah skrip dropResult.php. Server database akan memanggil skrip ini sebagai respons terhadap perubahan pada tabel ORDERS dan ORDER_ITEMS.
Listing 8. Menangani notifikasi perubahan yang diterima dari server database
<?php
//File:dropResults.php
require_once 'Cache/Lite/Function.php';
$pilihan = array(
'cacheDir' => '/tmp/'
);
$cache = Cache_Lite_Function baru($pilihan);
if (isset($_GET['tidak_pesanan'])&& isset($_GET['tabel'])) {
if($_GET['tabel']=='ORDER_ITEMS'){
$cache->jatuhkan('getOrderItems', $_GET['order_no']);
}
if ($_GET['tabel']=='PESANAN'){
$cache->jatuhkan('getOrderFields', $_GET['order_no']);
}
}
?>
Setelah membuat skrip dropResult.php, pastikan URL yang ditentukan dalam pengendali notifikasi (ditunjukkan pada Listing 2) sudah benar. Kemudian, sambungkan sebagai OE/OE di SQL*Plus atau alat serupa dan jalankan pernyataan UPDATE yang akan mempengaruhi pesanan yang sama yang diakses sebelumnya di bagian ini melalui skrip testCache.php (di sini pesanan dengan ID 2408):
UPDATE ORDERS SET order_mode = ' langsung' WHERE order_id=2408;
UPDATE ORDER_ITEMS SET kuantitas = 3 DIMANA order_id=2408 DAN line_item_id=1;
UPDATE ORDER_ITEMS SET kuantitas = 1 DIMANA order_id=2408 DAN line_item_id=2;
MELAKUKAN;
Menanggapi pembaruan di atas, pengendali notifikasi yang dijelaskan sebelumnya dalam artikel ini akan menjalankan skrip dropResults.php dua kali, menggunakan URL berikut: http://webserverhost/phpcache/dropResults.php?order_no=2408&table=ORDERS
http://webserverhost/phpcache/dropresults.php?order_no=2408&table=ORDER_ITEMS
Dari "Listing 8" Anda dapat melihat dengan jelas bahwa skrip dropResult.php tidak membersihkan cache setelah menerima pemberitahuan perubahan dari server database. Itu hanya menghapus file cache yang berisi data kadaluwarsa. Jadi jika Anda memeriksa direktori cache sekarang, Anda akan melihat bahwa file cache yang dibuat saat menjalankan skrip testCache.php dengan order_no=2408 telah hilang. Artinya pada saat testCache.php meminta data terkait ID pesanan 2408, data tersebut akan diambil dari database backend, bukan dari cache lokal.
Anda mungkin menemukan metode ini berguna dalam situasi di mana kumpulan hasil yang diminta oleh aplikasi kemungkinan besar akan berubah sebelum aplikasi menggunakannya. Untuk keperluan contoh artikel ini, ini berarti bahwa data yang terkait dengan pesanan tertentu dapat berubah beberapa kali sebelum testCache.php mengakses pesanan tersebut. Dengan cara ini, aplikasi melakukan banyak pekerjaan yang tidak perlu dengan mengosongkan cache segera setelah menerima pemberitahuan perubahan dari server database.
Namun jika Anda ingin skrip dropResult.php mengosongkan cache segera setelah perubahan diberitahukan, Anda dapat memanggil metode panggilan dari instance Cache_Lite_Function setelah memanggil metode drop, dengan menentukan parameter yang sama untuk kedua panggilan. Dalam hal ini, Anda juga harus memastikan untuk menyertakan skrip getOrderFields.php dan getOrderItems.php sehingga dropResults.php dapat memanggil fungsi getOrderFields dan getOrderItems untuk menyegarkan cache. "Listing 9" adalah skrip dropResult.php yang dimodifikasi.
Listing 9. Segera bersihkan cache setelah menerima notifikasi perubahan
<?php
//File:dropResults.php
require_once 'Cache/Lite/Function.php';
require_once 'getOrderItems.php';
require_once 'getOrderFields.php';
$pilihan = array(
'cacheDir' => '/tmp/',
'Seumur Hidup' => 86400
);
$cache = Cache_Lite_Function baru($pilihan);
if (isset($_GET['tidak_pesanan'])&& isset($_GET['tabel'])) {
if($_GET['tabel']=='ORDER_ITEMS'){
$cache->jatuhkan('getOrderItems', $_GET['order_no']);
$cache->panggilan('getOrderItems', $_GET['order_no']);
}
if ($_GET['tabel']=='PESANAN'){
$cache->jatuhkan('getOrderFields', $_GET['order_no']);
$cache->panggilan('getOrderFields', $_GET['order_no']);
}
}
?>
Pendekatan di atas mungkin berguna jika data yang disimpan dalam tabel ORDERS dan ORDER_ITEMS jarang berubah dan aplikasi sering mengaksesnya.
Ringkasan
Jika aplikasi PHP Anda berinteraksi dengan Oracle Database 10g Rilis 2, Anda dapat memanfaatkan fitur Pemberitahuan Perubahan Basis Data, yang memungkinkan aplikasi Anda menerima pemberitahuan sebagai respons terhadap perubahan DML pada objek yang terkait dengan permintaan yang dibuat. Dengan menggunakan fitur ini, Anda tidak perlu memperbarui cache di aplikasi Anda selama jangka waktu tertentu. Sebaliknya, operasi dilakukan hanya jika kumpulan hasil kueri terdaftar telah berubah.