這篇文章主要講解了“DBus數據庫表結構變更處理方法是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“DBus數據庫表結構變更處理方法是什么”吧!
對于感知表結構變更,Oracle已經通過DDL trigger為我們提供了很好的支持,接下來我們要考慮的是如何讓DBus感知到表結構變更? 我們討論出以下兩種方案:
在DDL trigger中調用DBus提供的REST服務,將表結構變更事件發送給DBus。
該方案思路簡單容易實現,但也有一些明顯的弊端,比如DBus需要提供高可用、低延時的REST服務,否則可能會使數據庫中的DDL操作變得緩慢甚至執行出現錯誤; DBus 的REST服務器對有數據實時同步需求的所有數據庫都必須開通防火墻策略,這將給DBus的部署帶來很大的麻煩。
在DDL trigger中將表結構變更事件存儲到一張Event表里,然后通過OGG實時的從日志中將數據同步到Kafka,從而感知表結構變更事件。
該方案實現相對復雜但具有很多優點,比如對數據庫的侵入性相對較小,DDL執行時只是將數據寫入到Event表中,相對網絡通信來說,其延時更低、可靠性更高;更明顯的優勢是這種方案基于數據庫日志實現,能夠使用Event表的數據,嚴格的將表結構變更前后的數據區分開。
舉例來說,對于表:test來說,依次執行insert → alter → insert 三個操作,因為OGG讀取數據庫日志存在延時,如果利用RPC方案,可能出現這樣的一種情況:DBus REST服務接收到alter事件之后,第一個insert的記錄才被OGG捕獲并發送給DBus,此時DBus會認為這條數據中包含alter變化后的數據。這是一個很嚴重的問題,而OGG實時同步方案無論數據還是時間均通過OGG讀取日志的方案實現,可以完美的避免這種問題的發生。
對比兩種方案OGG實時同步方案優勢明顯,最終我們采用此方案。
然而,采用這種方案也并非一帆風順,按照該方案的總體思路實現以后,我們遇到了一個很奇怪的問題:通過DDL trigger寫到Event表中的數據無法被OGG讀取,在經歷多番嘗試無解之后,我們試圖到OGG的文檔中尋找答案,而最終的結果卻是:DML or DDL operations performed from within a DDL trigger are not captured.
這個答案讓問題變得更棘手,但這是最佳方案,我們沒有理由放棄。于是我們開始嘗試在DDL trigger中調用存儲過程,在存儲過程中執行Event表的insert操作,但由于存儲過程和DDL trigger仍然屬于同一個事務,因此Event表的數據依然不能被OGG捕獲,但通過這個嘗試我們覺得只要在另外一個事務中寫Event表就能解決我們面臨的問題,于是我們又想到了RPC,但RPC缺點太過明顯。那么有沒有其他可以替代的方案呢?
實際上oracle數據庫里可以使用多種語言來編寫存儲過程,Oracle 8i開始支持java編寫存儲過程,于是我們立即開始實現java存儲過程,通過JDBC連接數據庫實現Event表的寫入并提交事務,最終通過實踐驗證了這種辦法的可行性,OGG成功的獲取到了DDL trigger調用java存儲過程寫入到Event表的數據。
然而,這種實現并不算完美。當我們在生產環境部署DDL trigger的時候,發現數據庫服務器中并沒有安裝執行java所需要的組件,每次部署都需要DBA同學安裝執行java存儲過程所需要的組件,我們試圖找到一個不使用java存儲過程的方案。這里要感謝韓鋒老師對我們的幫助,韓老師在聽了我 們的實現原理之后,啟發我們自治事務應該可以解決這個問題,我們即刻動手開始改造DDL trigger,使之支持自治事務,經過改造之后該方案才算完美,最終實現邏輯如圖1所示:
DBus已經具備通過事件方式感知表結構變更的能力,接下來詳細說明一下表結構變更事件該如何處理。
下圖描述了Event的完整處理流程:
Event中描述了發生結構變更的表名、該表所屬的schema以及元數據版本號,DBus接受并解析Event之后,根據表名、schema以及版本號調用元數據抓取模塊獲取該表的元數據(包括表的字段類型、長度以及注釋等)信息,實際上DDL trigger和alter語句在一個事務中執行,這樣在trigger執行過程中無法從oracle的數據字典里獲取到修改之后表結構元數據,我們寫入到meta_history表中的元數據只是執行alter語句之前的元數據信息(因此我們給這個表取名為table_meta_his),要得到完整的元數據信息需要聯合table_meta_his和數據字典進行查詢,示意SQL如下:
這個SQL的結果有兩種可能:
1)只包含all_tab_cols視圖中的數據
2)既包含all_tab_cols視圖中的數據又包含table_meta_his表的數據(is_current字段的作用是區別該字段的來源)
結果A表明在table_meta_his表中沒有找到數據,這說明在生成表結構變更Event至元數據抓取程序成功獲取元數據期間沒有再次發生表結構變更,結果B則說明在此期間又發生過一次或多次表結構變更。
為什么要使用union all?
單獨使用上圖中的兩個SQL可能導致元數據獲取程序獲取到錯誤的結果,例如:接到表結構變更Event 1后,我們調用SQL 1 查詢table_meta_his結果集為空,在調用SQL 2之前表結構再次發生變更(命名為Event 2),這種情況下我們通過SQL 2 查詢到的結果實際上是再次變更后的結果,使用這個結果產生的元數據去解析Event 1和Event 2之間的數據,如果兩次表結構變更是不兼容的,那么必然會導致解析失敗。
感謝各位的閱讀,以上就是“DBus數據庫表結構變更處理方法是什么”的內容了,經過本文的學習后,相信大家對DBus數據庫表結構變更處理方法是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。