摘 要: 根據(jù)當前數(shù)據(jù)庫應用需求和技術(shù)發(fā)展現(xiàn)狀,研究了數(shù)據(jù)庫管理系統(tǒng)" title="管理系統(tǒng)">管理系統(tǒng)觸發(fā)器機制實現(xiàn)的關(guān)鍵技術(shù)問題,并以GKD-Base" title="GKD-Base">GKD-Base為原型,在已有的GKD-Base PL/SQL引擎基礎(chǔ)上實現(xiàn)了數(shù)據(jù)庫的觸發(fā)器功能。
關(guān)鍵詞: PL/SQL引擎 Rete網(wǎng)絡 雙Hash結(jié)構(gòu) 觸發(fā)器
數(shù)據(jù)庫管理系統(tǒng)作為信息系統(tǒng)的核心部件,在信息化時代所充當?shù)慕巧瞧渌魏诬浖荒芴娲?。當前?shù)據(jù)庫應用的一個普遍要求是數(shù)據(jù)庫管理系統(tǒng)能夠在一些數(shù)據(jù)庫相關(guān)事件發(fā)生時觸發(fā)預先定義的操作,實現(xiàn)信息管理的自動化,因此引進了觸發(fā)器機制。觸發(fā)器可以增強引用完整性,加強復雜業(yè)務的規(guī)則,或者監(jiān)控數(shù)據(jù)庫的變動,并執(zhí)行一定的數(shù)據(jù)操作。
觸發(fā)器機制實現(xiàn)主要涉及觸發(fā)事件的檢測以及觸發(fā)條件的判決等關(guān)鍵技術(shù)問題,以及對觸發(fā)器的編譯存儲和調(diào)用執(zhí)行等具體操作。
本文以國產(chǎn)數(shù)據(jù)庫管理系統(tǒng)GKD-Base為原型,在兼容Oracle 規(guī)范的PL/SQL引擎基礎(chǔ)上,提出一套解決方案,對觸發(fā)器的關(guān)鍵技術(shù)問題進行了探討,并設(shè)計實現(xiàn)了數(shù)據(jù)庫的觸發(fā)器機制,擴展了數(shù)據(jù)庫管理系統(tǒng)GKD-Base的功能。
1 GKD-Base PL/SQL 引擎
GKD-BASE數(shù)據(jù)庫是一個具有自主知識產(chǎn)權(quán)的數(shù)據(jù)庫管理系統(tǒng),具有兼容SQL89標準的SQL引擎,能夠為用戶提供一個統(tǒng)一、有效的數(shù)據(jù)庫訪問接口(XAPI),實現(xiàn)對數(shù)據(jù)庫的各種操作。為了融合SQL語言強大的集合數(shù)據(jù)處理能力" title="處理能力">處理能力和第三代語言(3GL)靈活的過程處理能力,在GKD-Base上已初步實現(xiàn)了兼容Oarcle PL/SQL V.23的PL/SQL引擎。
GKD-Base PL/SQL引擎包括編譯器、解釋器和異常處理三個模塊。在編譯階段,根據(jù)PL/SQL語言兼有過程式語句和SQL語句的特點,采取分而治之策略,把過程語句和SQL語句分開處理。對于SQL語句,編譯器首先建立SQL語句結(jié)點,進行相應的變量綁定和語法檢查;檢查無誤后產(chǎn)生語法樹形式的中間代碼。對于過程語句,編譯器將對語句成分進行語法分析,對聲明的變量和數(shù)據(jù)類型建立相應的符號表,最終產(chǎn)生語法樹形式的中間代碼。解釋器的作用是對編譯器生成的中間代碼進行解釋執(zhí)行。解釋器與編譯器對應,具有相對獨立的SQL語句解釋模塊和過程語句解釋模塊。另外,解釋器還包括執(zhí)行狀態(tài)堆棧的管理、與GKD-Base SQL引擎的調(diào)用接口。異常處理模塊主要實現(xiàn)程序運行時的錯誤檢查和報告,并支持用戶自定義異常和預定義異常的檢查和處理。
GKD-Base PL/SQL引擎可以實現(xiàn)對過程式語句、SQL語句與游標、存儲子程序及包的編譯和解釋執(zhí)行。
2 觸發(fā)器實現(xiàn)的關(guān)鍵問題
觸發(fā)器定義了當某些數(shù)據(jù)庫相關(guān)事件發(fā)生時數(shù)據(jù)庫應采取的動作。觸發(fā)器可增強引用完整性,加強復雜業(yè)務的規(guī)則,或者監(jiān)控數(shù)據(jù)庫的變動,其實現(xiàn)主要涉及到觸發(fā)事件的檢測以及觸發(fā)條件的判決等關(guān)鍵技術(shù)問題。
2.1 觸發(fā)器的事件檢測機制
觸發(fā)器事件檢測機制包括對事件的檢測和存儲,是實現(xiàn)觸發(fā)器的關(guān)鍵。觸發(fā)器檢測的事件類型比較簡單,基本事件主要包括對數(shù)據(jù)的插入、刪除以及更新等。GKD-Base的觸發(fā)器在對事件檢測時,直接在相關(guān)事件發(fā)生的前后調(diào)用檢測函數(shù)截獲并分析事件消息,以確定是否對觸發(fā)器點火。
觸發(fā)器事件檢測機制實現(xiàn)的關(guān)鍵在于對觸發(fā)事件的存儲。觸發(fā)事件具有時間順序,因此存儲時也必須按照嚴格的時間順序進行存儲。綜合比較各個商用和實驗數(shù)據(jù)庫系統(tǒng)的事件表存儲機制,選擇了Starburst的雙" title="的雙">的雙HASH鏈表存儲機制,如圖1。
這里,變遷表分為兩種類型:NEW和OLD,分別對應于觸發(fā)器行級別操作中的NEW值和OLD值。變遷表中存儲了事件類型、當前數(shù)據(jù)表以及事件作用的元組。系統(tǒng)可以通過這個駐留內(nèi)存的雙HASH鏈表實現(xiàn)數(shù)據(jù)庫變遷的快速定位和跟蹤處理。
2.2 觸發(fā)器的條件判決機制
觸發(fā)器的條件判決機制是觸發(fā)器的核心,根據(jù)SQL99標準的定義,可以將觸發(fā)器分為前觸發(fā)、約束判定和后觸發(fā)三種類型。這三種類型觸發(fā)器的判決順序策略如圖2。
觸發(fā)器的條件評估是影響觸發(fā)器機制的最關(guān)鍵因素。在數(shù)據(jù)庫環(huán)境中,大多數(shù)數(shù)據(jù)修改行為只能影響數(shù)據(jù)庫的一小部分內(nèi)容,因此沒必要每次都從頭開始評估觸發(fā)器規(guī)則條件,Rete和TREAT網(wǎng)絡等增量條件評估方法已經(jīng)被證明是觸發(fā)器條件評估(Condition Evaluation)的有效處理手段。
以Rete網(wǎng)絡為例(圖3),它是一個左深度二叉樹,其基本元素包括:
根結(jié)點:根結(jié)點接收插入/刪除(+/-)記號(tokens),并將其傳遞給每一個后繼結(jié)點;
t-const結(jié)點:記號到達這些結(jié)點后,將根據(jù)該結(jié)點上的條件謂詞進行判決,那些通過測試的記號將繼續(xù)傳播下去,沒有通過測試的記號則被丟棄掉;
α-存儲結(jié)點:通過t-const結(jié)點測試的記號將存儲到這個結(jié)點中,存儲在α-存儲結(jié)點中的每一個記號都將同時被傳遞給該結(jié)點的后繼結(jié)點;
AND(連接)結(jié)點:這些結(jié)點有兩個輸入,到達其中任意一個輸入結(jié)點的記號都要通過AND結(jié)點進行測試,看它是否需要與另外一個輸入進行連接操作。如果是,則連接兩個輸入的記號對,將它們合并成一個組合記號后再傳遞給后繼的β-存儲結(jié)點;
β-存儲結(jié)點:存儲連接結(jié)點的輸出,并將輸出同時傳遞給后繼結(jié)點;
P-結(jié)點(規(guī)則結(jié)點):+記號到達這里表明應該喚醒一個與該記號相關(guān)聯(lián)的規(guī)則實例;-記號到達這里表明與其中的標簽對象相關(guān)聯(lián)的已經(jīng)進入待執(zhí)行隊列的規(guī)則實例應該被刪除。
Rete網(wǎng)絡只支持兩路連接,對于一個有多個關(guān)系參與的規(guī)則定義,不同的連接順序可以得到不同的Rete網(wǎng)絡,根據(jù)數(shù)據(jù)字典信息可以選擇最優(yōu)的執(zhí)行順序。圖3是對應于規(guī)則條件“A.color =“BULE”AND A.x < B.x AND B.x < C.x”的Rete網(wǎng)絡示意圖。
3 觸發(fā)器實現(xiàn)算法
觸發(fā)器的具體實現(xiàn)可以分為觸發(fā)器創(chuàng)建和調(diào)用,此外還包括觸發(fā)器的修改、刪除等操作。其中觸發(fā)器的創(chuàng)建包括觸發(fā)器的編譯與存儲操作,觸發(fā)器的調(diào)用包括對觸發(fā)器事件的檢測和觸發(fā)器動作的執(zhí)行。
3.1創(chuàng)建觸發(fā)器
觸發(fā)器的創(chuàng)建包括觸發(fā)器的編譯和存儲。觸發(fā)器的編譯涉及到觸發(fā)器的命名、觸發(fā)器事件的正確性檢查、觸發(fā)器引用表的合法性檢查以及觸發(fā)器主體的語法檢查。觸發(fā)器創(chuàng)建之前首先要檢查用戶是否有創(chuàng)建觸發(fā)器的權(quán)限,以及觸發(fā)器名是否已經(jīng)在存儲觸發(fā)器的數(shù)據(jù)字典中被使用。觸發(fā)事件部分在觸發(fā)器創(chuàng)建時要進行檢查,需要檢查的內(nèi)容包括語法檢查、觸發(fā)器引用的表和列是否存在,以及用戶是否有針對這個表創(chuàng)建觸發(fā)器的權(quán)限。表和列的存在與否可以先調(diào)用GKD-Base的XAPI函數(shù)分析出DML語句中表和列的信息,然后根據(jù)這些信息檢查數(shù)據(jù)字典;權(quán)限的檢查也要到數(shù)據(jù)字典中查詢。觸發(fā)器的語法檢查通過調(diào)用PL/SQL引擎的編譯器實現(xiàn);PL/SQL引擎編譯器對觸發(fā)器過程語句塊進行編譯,并生成包含觸發(fā)器所有必要信息的語法樹形式的中間代碼。
保存觸發(fā)器相關(guān)信息的數(shù)據(jù)結(jié)構(gòu)" title="數(shù)據(jù)結(jié)構(gòu)">數(shù)據(jù)結(jié)構(gòu)最終需要保存在數(shù)據(jù)字典中。因為觸發(fā)器使用單獨的命名空間,可以設(shè)計一個單獨的系統(tǒng)表作為存儲觸發(fā)器的數(shù)據(jù)字典。數(shù)據(jù)字典應該保存觸發(fā)器調(diào)用過程中必須的信息,類似于Oracle sys.trigger$表。觸發(fā)器主體是一個語句塊,對它可以當作一個存儲過程來處理,單獨保存在一個系統(tǒng)表中,通過觸發(fā)器主體的ID號與存儲在USER_TRIGGERS表中的其它觸發(fā)器信息相關(guān)聯(lián)。在觸發(fā)器調(diào)用過程中,根據(jù)觸發(fā)器中的ID來調(diào)用。
創(chuàng)建觸發(fā)器算法如下:
(1)合法性驗證。如當前用戶無權(quán)執(zhí)行該操作,或者用戶給出的表不存在,轉(zhuǎn)(6);否則轉(zhuǎn)(2)。
(2)存在性檢查。如當前定義的觸發(fā)器與當前表以往定義的觸發(fā)器重名或同類型,轉(zhuǎn)(6);否則轉(zhuǎn)(3)。
(3)語法檢查。調(diào)用PL/SQL引擎編譯器對觸發(fā)器語句進行編譯,如出現(xiàn)語法或語義錯誤,轉(zhuǎn)(6);否則轉(zhuǎn)(4)。
(4)將觸發(fā)器信息寫入外存,然后返回觸發(fā)器標識ID。
(5)在數(shù)據(jù)庫表結(jié)構(gòu)的系統(tǒng)表中將(4)中所得標識與觸發(fā)器名填入其中,然后將觸發(fā)器定義的表項插入到USER_TRIGGERS相應的系統(tǒng)表項中,轉(zhuǎn)(7)。
(6)釋放所占資源,報錯退出。
(7)釋放資源,正常退出。
3.2 觸發(fā)器的調(diào)用
觸發(fā)器的調(diào)用首先要從外存中讀取觸發(fā)器的信息,并寫入內(nèi)存相應的數(shù)據(jù)結(jié)構(gòu)中。觸發(fā)器的內(nèi)存形式是為了更方便地進行觸發(fā)器約束條件的檢查而設(shè)立的。為了在觸發(fā)事件發(fā)生時,能立即判斷當前被處理對象是否滿足觸發(fā)約束條件,通過調(diào)用PL/SQL引擎編譯器將外存中存放觸發(fā)器約束源代碼轉(zhuǎn)換為其內(nèi)存表示,存放在相應觸發(fā)器的內(nèi)存結(jié)構(gòu)中。
在觸發(fā)器被調(diào)用前,系統(tǒng)將被同一觸發(fā)事件所觸發(fā)的所有活躍的觸發(fā)器組織成四條鏈,如圖4。
根據(jù)這個數(shù)據(jù)結(jié)構(gòu),觸發(fā)器調(diào)用算法如下:
(1)將與觸發(fā)事件相關(guān)的觸發(fā)器按類型分別記入SB、SA、RB和RA四條鏈中;如沒有某種類型的觸發(fā)器,則相應鏈置空。
(2)如SB不為空,則轉(zhuǎn)SB鏈觸發(fā)操作算法。
(3)如RB不為空,則轉(zhuǎn)RB鏈觸發(fā)操作算法。
(4)對當前數(shù)據(jù)對象進行觸發(fā)事件所規(guī)定的DML操作。
(5)如RA不為空,則轉(zhuǎn)RA鏈觸發(fā)操作算法。
(6)判斷觸發(fā)事件所作用的數(shù)據(jù)記錄是否都被處理完畢,如是,轉(zhuǎn)(7);否則,取出下一條記錄作為當前的數(shù)據(jù)對象,轉(zhuǎn)(3)。
(7)如SA不為空,則轉(zhuǎn)SA鏈觸發(fā)操作算法。
(8)釋放所占的資源,結(jié)束觸發(fā)器調(diào)用的處理。
對給定觸發(fā)器鏈操作算法如下:
(1)根據(jù)觸發(fā)器調(diào)用算法檢測,當前觸發(fā)器鏈不為空,取鏈首觸發(fā)器。
(2)將待處理數(shù)據(jù)對象的相關(guān)信息代入觸發(fā)條件判斷,
如果條件為真,轉(zhuǎn)(3);否則轉(zhuǎn)(4)。
(3)啟動一個PL/SQL解釋執(zhí)行器,對當前觸發(fā)器動作鏈中所記錄的動作進行解釋執(zhí)行。
(4)取鏈中下一個觸發(fā)器為鏈首,判斷是否為空,如是,轉(zhuǎn)(5);否則轉(zhuǎn)(1)。
(5)完成當前觸發(fā)器鏈操作,返回觸發(fā)器調(diào)用算法繼續(xù)。
觸發(fā)器的更新操作是對一個觸發(fā)器進行編譯后,替換已存在的作用在同一個表上的同名觸發(fā)器,基本操作與觸發(fā)器的創(chuàng)建是一致的;觸發(fā)器的刪除操作步驟主要是在數(shù)據(jù)字典中對指定的觸發(fā)器進行查詢并刪除。這里不再詳述。
參考文獻
1 唐 揚,熊 偉,陳宏盛等. GKD-Base PL/SQL引擎實現(xiàn)關(guān)鍵技術(shù)研究. 電子技術(shù)應用, 2004;30(8)
2 Tom Portfolio. PL/SQL User′s Guide and Reference. Release 8.1.6, Oracle Corporation. 1999
3 J.Widom,S.Finkelstein. Set Oriented Production Rules in Relational Database Systems. In Proc. ACM SIGMOD, 1990
4 Doorenbos, R. B., Matching 100,000 learned rules. In Proceedings of the Eleventh National Conference on Artificial Intelligence, pages 290~296, 1993
5 C.-L. Forgy. Rete: a Fast Algorithm for the Many Pattern/Many Object Pattern Match Problem. Artificial Intelligence, 1982
6 Miranker, D. P. TREAT: A NEW and Efficient Match Algo-rithm for AI Production Systems. Morgan Kaufmann, San Mateo, CA.