摘 要: 根據當前數據庫應用需求和技術發展現狀,研究了數據庫管理系統" title="管理系統">管理系統觸發器機制實現的關鍵技術問題,并以GKD-Base" title="GKD-Base">GKD-Base為原型,在已有的GKD-Base PL/SQL引擎基礎上實現了數據庫的觸發器功能。
關鍵詞: PL/SQL引擎 Rete網絡 雙Hash結構 觸發器
數據庫管理系統作為信息系統的核心部件,在信息化時代所充當的角色是其它任何軟件所不能替代的。當前數據庫應用的一個普遍要求是數據庫管理系統能夠在一些數據庫相關事件發生時觸發預先定義的操作,實現信息管理的自動化,因此引進了觸發器機制。觸發器可以增強引用完整性,加強復雜業務的規則,或者監控數據庫的變動,并執行一定的數據操作。
觸發器機制實現主要涉及觸發事件的檢測以及觸發條件的判決等關鍵技術問題,以及對觸發器的編譯存儲和調用執行等具體操作。
本文以國產數據庫管理系統GKD-Base為原型,在兼容Oracle 規范的PL/SQL引擎基礎上,提出一套解決方案,對觸發器的關鍵技術問題進行了探討,并設計實現了數據庫的觸發器機制,擴展了數據庫管理系統GKD-Base的功能。
1 GKD-Base PL/SQL 引擎
GKD-BASE數據庫是一個具有自主知識產權的數據庫管理系統,具有兼容SQL89標準的SQL引擎,能夠為用戶提供一個統一、有效的數據庫訪問接口(XAPI),實現對數據庫的各種操作。為了融合SQL語言強大的集合數據處理能力" title="處理能力">處理能力和第三代語言(3GL)靈活的過程處理能力,在GKD-Base上已初步實現了兼容Oarcle PL/SQL V.23的PL/SQL引擎。
GKD-Base PL/SQL引擎包括編譯器、解釋器和異常處理三個模塊。在編譯階段,根據PL/SQL語言兼有過程式語句和SQL語句的特點,采取分而治之策略,把過程語句和SQL語句分開處理。對于SQL語句,編譯器首先建立SQL語句結點,進行相應的變量綁定和語法檢查;檢查無誤后產生語法樹形式的中間代碼。對于過程語句,編譯器將對語句成分進行語法分析,對聲明的變量和數據類型建立相應的符號表,最終產生語法樹形式的中間代碼。解釋器的作用是對編譯器生成的中間代碼進行解釋執行。解釋器與編譯器對應,具有相對獨立的SQL語句解釋模塊和過程語句解釋模塊。另外,解釋器還包括執行狀態堆棧的管理、與GKD-Base SQL引擎的調用接口。異常處理模塊主要實現程序運行時的錯誤檢查和報告,并支持用戶自定義異常和預定義異常的檢查和處理。
GKD-Base PL/SQL引擎可以實現對過程式語句、SQL語句與游標、存儲子程序及包的編譯和解釋執行。
2 觸發器實現的關鍵問題
觸發器定義了當某些數據庫相關事件發生時數據庫應采取的動作。觸發器可增強引用完整性,加強復雜業務的規則,或者監控數據庫的變動,其實現主要涉及到觸發事件的檢測以及觸發條件的判決等關鍵技術問題。
2.1 觸發器的事件檢測機制
觸發器事件檢測機制包括對事件的檢測和存儲,是實現觸發器的關鍵。觸發器檢測的事件類型比較簡單,基本事件主要包括對數據的插入、刪除以及更新等。GKD-Base的觸發器在對事件檢測時,直接在相關事件發生的前后調用檢測函數截獲并分析事件消息,以確定是否對觸發器點火。
觸發器事件檢測機制實現的關鍵在于對觸發事件的存儲。觸發事件具有時間順序,因此存儲時也必須按照嚴格的時間順序進行存儲。綜合比較各個商用和實驗數據庫系統的事件表存儲機制,選擇了Starburst的雙" title="的雙">的雙HASH鏈表存儲機制,如圖1。
這里,變遷表分為兩種類型:NEW和OLD,分別對應于觸發器行級別操作中的NEW值和OLD值。變遷表中存儲了事件類型、當前數據表以及事件作用的元組。系統可以通過這個駐留內存的雙HASH鏈表實現數據庫變遷的快速定位和跟蹤處理。
2.2 觸發器的條件判決機制
觸發器的條件判決機制是觸發器的核心,根據SQL99標準的定義,可以將觸發器分為前觸發、約束判定和后觸發三種類型。這三種類型觸發器的判決順序策略如圖2。
觸發器的條件評估是影響觸發器機制的最關鍵因素。在數據庫環境中,大多數數據修改行為只能影響數據庫的一小部分內容,因此沒必要每次都從頭開始評估觸發器規則條件,Rete和TREAT網絡等增量條件評估方法已經被證明是觸發器條件評估(Condition Evaluation)的有效處理手段。
以Rete網絡為例(圖3),它是一個左深度二叉樹,其基本元素包括:
根結點:根結點接收插入/刪除(+/-)記號(tokens),并將其傳遞給每一個后繼結點;
t-const結點:記號到達這些結點后,將根據該結點上的條件謂詞進行判決,那些通過測試的記號將繼續傳播下去,沒有通過測試的記號則被丟棄掉;
α-存儲結點:通過t-const結點測試的記號將存儲到這個結點中,存儲在α-存儲結點中的每一個記號都將同時被傳遞給該結點的后繼結點;
AND(連接)結點:這些結點有兩個輸入,到達其中任意一個輸入結點的記號都要通過AND結點進行測試,看它是否需要與另外一個輸入進行連接操作。如果是,則連接兩個輸入的記號對,將它們合并成一個組合記號后再傳遞給后繼的β-存儲結點;
β-存儲結點:存儲連接結點的輸出,并將輸出同時傳遞給后繼結點;
P-結點(規則結點):+記號到達這里表明應該喚醒一個與該記號相關聯的規則實例;-記號到達這里表明與其中的標簽對象相關聯的已經進入待執行隊列的規則實例應該被刪除。
Rete網絡只支持兩路連接,對于一個有多個關系參與的規則定義,不同的連接順序可以得到不同的Rete網絡,根據數據字典信息可以選擇最優的執行順序。圖3是對應于規則條件“A.color =“BULE”AND A.x < B.x AND B.x < C.x”的Rete網絡示意圖。
3 觸發器實現算法
觸發器的具體實現可以分為觸發器創建和調用,此外還包括觸發器的修改、刪除等操作。其中觸發器的創建包括觸發器的編譯與存儲操作,觸發器的調用包括對觸發器事件的檢測和觸發器動作的執行。
3.1創建觸發器
觸發器的創建包括觸發器的編譯和存儲。觸發器的編譯涉及到觸發器的命名、觸發器事件的正確性檢查、觸發器引用表的合法性檢查以及觸發器主體的語法檢查。觸發器創建之前首先要檢查用戶是否有創建觸發器的權限,以及觸發器名是否已經在存儲觸發器的數據字典中被使用。觸發事件部分在觸發器創建時要進行檢查,需要檢查的內容包括語法檢查、觸發器引用的表和列是否存在,以及用戶是否有針對這個表創建觸發器的權限。表和列的存在與否可以先調用GKD-Base的XAPI函數分析出DML語句中表和列的信息,然后根據這些信息檢查數據字典;權限的檢查也要到數據字典中查詢。觸發器的語法檢查通過調用PL/SQL引擎的編譯器實現;PL/SQL引擎編譯器對觸發器過程語句塊進行編譯,并生成包含觸發器所有必要信息的語法樹形式的中間代碼。
保存觸發器相關信息的數據結構" title="數據結構">數據結構最終需要保存在數據字典中。因為觸發器使用單獨的命名空間,可以設計一個單獨的系統表作為存儲觸發器的數據字典。數據字典應該保存觸發器調用過程中必須的信息,類似于Oracle sys.trigger$表。觸發器主體是一個語句塊,對它可以當作一個存儲過程來處理,單獨保存在一個系統表中,通過觸發器主體的ID號與存儲在USER_TRIGGERS表中的其它觸發器信息相關聯。在觸發器調用過程中,根據觸發器中的ID來調用。
創建觸發器算法如下:
(1)合法性驗證。如當前用戶無權執行該操作,或者用戶給出的表不存在,轉(6);否則轉(2)。
(2)存在性檢查。如當前定義的觸發器與當前表以往定義的觸發器重名或同類型,轉(6);否則轉(3)。
(3)語法檢查。調用PL/SQL引擎編譯器對觸發器語句進行編譯,如出現語法或語義錯誤,轉(6);否則轉(4)。
(4)將觸發器信息寫入外存,然后返回觸發器標識ID。
(5)在數據庫表結構的系統表中將(4)中所得標識與觸發器名填入其中,然后將觸發器定義的表項插入到USER_TRIGGERS相應的系統表項中,轉(7)。
(6)釋放所占資源,報錯退出。
(7)釋放資源,正常退出。
3.2 觸發器的調用
觸發器的調用首先要從外存中讀取觸發器的信息,并寫入內存相應的數據結構中。觸發器的內存形式是為了更方便地進行觸發器約束條件的檢查而設立的。為了在觸發事件發生時,能立即判斷當前被處理對象是否滿足觸發約束條件,通過調用PL/SQL引擎編譯器將外存中存放觸發器約束源代碼轉換為其內存表示,存放在相應觸發器的內存結構中。
在觸發器被調用前,系統將被同一觸發事件所觸發的所有活躍的觸發器組織成四條鏈,如圖4。
根據這個數據結構,觸發器調用算法如下:
(1)將與觸發事件相關的觸發器按類型分別記入SB、SA、RB和RA四條鏈中;如沒有某種類型的觸發器,則相應鏈置空。
(2)如SB不為空,則轉SB鏈觸發操作算法。
(3)如RB不為空,則轉RB鏈觸發操作算法。
(4)對當前數據對象進行觸發事件所規定的DML操作。
(5)如RA不為空,則轉RA鏈觸發操作算法。
(6)判斷觸發事件所作用的數據記錄是否都被處理完畢,如是,轉(7);否則,取出下一條記錄作為當前的數據對象,轉(3)。
(7)如SA不為空,則轉SA鏈觸發操作算法。
(8)釋放所占的資源,結束觸發器調用的處理。
對給定觸發器鏈操作算法如下:
(1)根據觸發器調用算法檢測,當前觸發器鏈不為空,取鏈首觸發器。
(2)將待處理數據對象的相關信息代入觸發條件判斷,
如果條件為真,轉(3);否則轉(4)。
(3)啟動一個PL/SQL解釋執行器,對當前觸發器動作鏈中所記錄的動作進行解釋執行。
(4)取鏈中下一個觸發器為鏈首,判斷是否為空,如是,轉(5);否則轉(1)。
(5)完成當前觸發器鏈操作,返回觸發器調用算法繼續。
觸發器的更新操作是對一個觸發器進行編譯后,替換已存在的作用在同一個表上的同名觸發器,基本操作與觸發器的創建是一致的;觸發器的刪除操作步驟主要是在數據字典中對指定的觸發器進行查詢并刪除。這里不再詳述。
參考文獻
1 唐 揚,熊 偉,陳宏盛等. GKD-Base PL/SQL引擎實現關鍵技術研究. 電子技術應用, 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.