這篇文章主要講解了“DBus數(shù)據(jù)庫(kù)表結(jié)構(gòu)變更處理方法是什么”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“DBus數(shù)據(jù)庫(kù)表結(jié)構(gòu)變更處理方法是什么”吧!
創(chuàng)新互聯(lián)成立十余年來(lái),這條路我們正越走越好,積累了技術(shù)與客戶資源,形成了良好的口碑。為客戶提供網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、網(wǎng)站策劃、網(wǎng)頁(yè)設(shè)計(jì)、域名申請(qǐng)、網(wǎng)絡(luò)營(yíng)銷(xiāo)、VI設(shè)計(jì)、網(wǎng)站改版、漏洞修補(bǔ)等服務(wù)。網(wǎng)站是否美觀、功能強(qiáng)大、用戶體驗(yàn)好、性價(jià)比高、打開(kāi)快等等,這些對(duì)于網(wǎng)站建設(shè)都非常重要,創(chuàng)新互聯(lián)通過(guò)對(duì)建站技術(shù)性的掌握、對(duì)創(chuàng)意設(shè)計(jì)的研究為客戶提供一站式互聯(lián)網(wǎng)解決方案,攜手廣大客戶,共同發(fā)展進(jìn)步。對(duì)于感知表結(jié)構(gòu)變更,Oracle已經(jīng)通過(guò)DDL trigger為我們提供了很好的支持,接下來(lái)我們要考慮的是如何讓DBus感知到表結(jié)構(gòu)變更? 我們討論出以下兩種方案:
在DDL trigger中調(diào)用DBus提供的REST服務(wù),將表結(jié)構(gòu)變更事件發(fā)送給DBus。
該方案思路簡(jiǎn)單容易實(shí)現(xiàn),但也有一些明顯的弊端,比如DBus需要提供高可用、低延時(shí)的REST服務(wù),否則可能會(huì)使數(shù)據(jù)庫(kù)中的DDL操作變得緩慢甚至執(zhí)行出現(xiàn)錯(cuò)誤; DBus 的REST服務(wù)器對(duì)有數(shù)據(jù)實(shí)時(shí)同步需求的所有數(shù)據(jù)庫(kù)都必須開(kāi)通防火墻策略,這將給DBus的部署帶來(lái)很大的麻煩。
在DDL trigger中將表結(jié)構(gòu)變更事件存儲(chǔ)到一張Event表里,然后通過(guò)OGG實(shí)時(shí)的從日志中將數(shù)據(jù)同步到Kafka,從而感知表結(jié)構(gòu)變更事件。
該方案實(shí)現(xiàn)相對(duì)復(fù)雜但具有很多優(yōu)點(diǎn),比如對(duì)數(shù)據(jù)庫(kù)的侵入性相對(duì)較小,DDL執(zhí)行時(shí)只是將數(shù)據(jù)寫(xiě)入到Event表中,相對(duì)網(wǎng)絡(luò)通信來(lái)說(shuō),其延時(shí)更低、可靠性更高;更明顯的優(yōu)勢(shì)是這種方案基于數(shù)據(jù)庫(kù)日志實(shí)現(xiàn),能夠使用Event表的數(shù)據(jù),嚴(yán)格的將表結(jié)構(gòu)變更前后的數(shù)據(jù)區(qū)分開(kāi)。
舉例來(lái)說(shuō),對(duì)于表:test來(lái)說(shuō),依次執(zhí)行insert → alter → insert 三個(gè)操作,因?yàn)镺GG讀取數(shù)據(jù)庫(kù)日志存在延時(shí),如果利用RPC方案,可能出現(xiàn)這樣的一種情況:DBus REST服務(wù)接收到alter事件之后,第一個(gè)insert的記錄才被OGG捕獲并發(fā)送給DBus,此時(shí)DBus會(huì)認(rèn)為這條數(shù)據(jù)中包含alter變化后的數(shù)據(jù)。這是一個(gè)很?chē)?yán)重的問(wèn)題,而OGG實(shí)時(shí)同步方案無(wú)論數(shù)據(jù)還是時(shí)間均通過(guò)OGG讀取日志的方案實(shí)現(xiàn),可以完美的避免這種問(wèn)題的發(fā)生。
對(duì)比兩種方案OGG實(shí)時(shí)同步方案優(yōu)勢(shì)明顯,最終我們采用此方案。
然而,采用這種方案也并非一帆風(fēng)順,按照該方案的總體思路實(shí)現(xiàn)以后,我們遇到了一個(gè)很奇怪的問(wèn)題:通過(guò)DDL trigger寫(xiě)到Event表中的數(shù)據(jù)無(wú)法被OGG讀取,在經(jīng)歷多番嘗試無(wú)解之后,我們?cè)噲D到OGG的文檔中尋找答案,而最終的結(jié)果卻是:DML or DDL operations performed from within a DDL trigger are not captured.
這個(gè)答案讓問(wèn)題變得更棘手,但這是最佳方案,我們沒(méi)有理由放棄。于是我們開(kāi)始嘗試在DDL trigger中調(diào)用存儲(chǔ)過(guò)程,在存儲(chǔ)過(guò)程中執(zhí)行Event表的insert操作,但由于存儲(chǔ)過(guò)程和DDL trigger仍然屬于同一個(gè)事務(wù),因此Event表的數(shù)據(jù)依然不能被OGG捕獲,但通過(guò)這個(gè)嘗試我們覺(jué)得只要在另外一個(gè)事務(wù)中寫(xiě)Event表就能解決我們面臨的問(wèn)題,于是我們又想到了RPC,但RPC缺點(diǎn)太過(guò)明顯。那么有沒(méi)有其他可以替代的方案呢?
實(shí)際上oracle數(shù)據(jù)庫(kù)里可以使用多種語(yǔ)言來(lái)編寫(xiě)存儲(chǔ)過(guò)程,Oracle 8i開(kāi)始支持java編寫(xiě)存儲(chǔ)過(guò)程,于是我們立即開(kāi)始實(shí)現(xiàn)java存儲(chǔ)過(guò)程,通過(guò)JDBC連接數(shù)據(jù)庫(kù)實(shí)現(xiàn)Event表的寫(xiě)入并提交事務(wù),最終通過(guò)實(shí)踐驗(yàn)證了這種辦法的可行性,OGG成功的獲取到了DDL trigger調(diào)用java存儲(chǔ)過(guò)程寫(xiě)入到Event表的數(shù)據(jù)。
然而,這種實(shí)現(xiàn)并不算完美。當(dāng)我們?cè)谏a(chǎn)環(huán)境部署DDL trigger的時(shí)候,發(fā)現(xiàn)數(shù)據(jù)庫(kù)服務(wù)器中并沒(méi)有安裝執(zhí)行java所需要的組件,每次部署都需要DBA同學(xué)安裝執(zhí)行java存儲(chǔ)過(guò)程所需要的組件,我們?cè)噲D找到一個(gè)不使用java存儲(chǔ)過(guò)程的方案。這里要感謝韓鋒老師對(duì)我們的幫助,韓老師在聽(tīng)了我 們的實(shí)現(xiàn)原理之后,啟發(fā)我們自治事務(wù)應(yīng)該可以解決這個(gè)問(wèn)題,我們即刻動(dòng)手開(kāi)始改造DDL trigger,使之支持自治事務(wù),經(jīng)過(guò)改造之后該方案才算完美,最終實(shí)現(xiàn)邏輯如圖1所示:
DBus已經(jīng)具備通過(guò)事件方式感知表結(jié)構(gòu)變更的能力,接下來(lái)詳細(xì)說(shuō)明一下表結(jié)構(gòu)變更事件該如何處理。
下圖描述了Event的完整處理流程:
Event中描述了發(fā)生結(jié)構(gòu)變更的表名、該表所屬的schema以及元數(shù)據(jù)版本號(hào),DBus接受并解析Event之后,根據(jù)表名、schema以及版本號(hào)調(diào)用元數(shù)據(jù)抓取模塊獲取該表的元數(shù)據(jù)(包括表的字段類(lèi)型、長(zhǎng)度以及注釋等)信息,實(shí)際上DDL trigger和alter語(yǔ)句在一個(gè)事務(wù)中執(zhí)行,這樣在trigger執(zhí)行過(guò)程中無(wú)法從oracle的數(shù)據(jù)字典里獲取到修改之后表結(jié)構(gòu)元數(shù)據(jù),我們寫(xiě)入到meta_history表中的元數(shù)據(jù)只是執(zhí)行alter語(yǔ)句之前的元數(shù)據(jù)信息(因此我們給這個(gè)表取名為table_meta_his),要得到完整的元數(shù)據(jù)信息需要聯(lián)合table_meta_his和數(shù)據(jù)字典進(jìn)行查詢,示意SQL如下:
這個(gè)SQL的結(jié)果有兩種可能:
1)只包含all_tab_cols視圖中的數(shù)據(jù)
2)既包含all_tab_cols視圖中的數(shù)據(jù)又包含table_meta_his表的數(shù)據(jù)(is_current字段的作用是區(qū)別該字段的來(lái)源)
結(jié)果A表明在table_meta_his表中沒(méi)有找到數(shù)據(jù),這說(shuō)明在生成表結(jié)構(gòu)變更Event至元數(shù)據(jù)抓取程序成功獲取元數(shù)據(jù)期間沒(méi)有再次發(fā)生表結(jié)構(gòu)變更,結(jié)果B則說(shuō)明在此期間又發(fā)生過(guò)一次或多次表結(jié)構(gòu)變更。
為什么要使用union all?
單獨(dú)使用上圖中的兩個(gè)SQL可能導(dǎo)致元數(shù)據(jù)獲取程序獲取到錯(cuò)誤的結(jié)果,例如:接到表結(jié)構(gòu)變更Event 1后,我們調(diào)用SQL 1 查詢table_meta_his結(jié)果集為空,在調(diào)用SQL 2之前表結(jié)構(gòu)再次發(fā)生變更(命名為Event 2),這種情況下我們通過(guò)SQL 2 查詢到的結(jié)果實(shí)際上是再次變更后的結(jié)果,使用這個(gè)結(jié)果產(chǎn)生的元數(shù)據(jù)去解析Event 1和Event 2之間的數(shù)據(jù),如果兩次表結(jié)構(gòu)變更是不兼容的,那么必然會(huì)導(dǎo)致解析失敗。
感謝各位的閱讀,以上就是“DBus數(shù)據(jù)庫(kù)表結(jié)構(gòu)變更處理方法是什么”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)DBus數(shù)據(jù)庫(kù)表結(jié)構(gòu)變更處理方法是什么這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!