如何進(jìn)行異構(gòu)數(shù)據(jù)庫同步(上篇)1、簡介
最近一陣子筆者在進(jìn)行完成同樣功能的兩套異構(gòu)數(shù)據(jù)庫系統(tǒng)的同步工作,有一些心得體會分享給大家,歡迎技術(shù)同仁拍磚。 該項目有一個運行若干年(5~10年)的舊系統(tǒng),采用的是SQL Server數(shù)據(jù)庫,因為舊平臺功能較弱,所以所有對數(shù)據(jù)庫的訪問操作都通過存儲過程進(jìn)行操作。 新系統(tǒng)采用筆者公司的平臺,應(yīng)客戶需求采用Oracle數(shù)據(jù)庫,完成的功能與舊系統(tǒng)基本相同,但表設(shè)計與原有系統(tǒng)不同,有些表對應(yīng)舊系統(tǒng)中的一張表,但字段名稱等大都不一樣。另外還有新系統(tǒng)中一張表對應(yīng)舊系統(tǒng)中多張小表的情況,也有新系統(tǒng)中多個表對應(yīng)舊系統(tǒng)中多張表的情況。新系統(tǒng)較少依賴數(shù)據(jù)庫,數(shù)據(jù)庫操作都在業(yè)務(wù)邏輯層完成。 因為舊系統(tǒng)在全國幾十個點上運行,而新系統(tǒng)全部替換舊系統(tǒng)需要比較長的時間,該項目采用的是按地區(qū)進(jìn)行逐步替換的原則,所以涉及到需要在兩種不同數(shù)據(jù)庫類型、不同數(shù)據(jù)庫結(jié)構(gòu)的異構(gòu)數(shù)據(jù)庫進(jìn)行同步。 2、重要術(shù)語 2.1 異構(gòu)數(shù)據(jù)庫 異構(gòu)數(shù)據(jù)庫系統(tǒng)是相關(guān)的多個數(shù)據(jù)庫系統(tǒng)的集合,可以實現(xiàn)數(shù)據(jù)的共享和透明訪問,每個數(shù)據(jù)庫系統(tǒng)在加入異構(gòu)數(shù)據(jù)庫系統(tǒng)之前本身就已經(jīng)存在,擁有自己的DBMS。異構(gòu)數(shù)據(jù)庫的各個組成部分具有自身的自治性,實現(xiàn)數(shù)據(jù)共享的同時,每個數(shù)據(jù)庫系統(tǒng)仍保有自己的應(yīng)用特性、完整性控制和安全性控制。 可以是同為關(guān)系型數(shù)據(jù)庫系統(tǒng)的Oracle、 SQL Server等,也可以是不同數(shù)據(jù)模型的數(shù)據(jù)庫,如關(guān)系、模式、層次、網(wǎng)絡(luò)、面向?qū)ο?,函?shù)型數(shù)據(jù)庫共同組成一個異構(gòu)數(shù)據(jù)庫系統(tǒng)。 2.2 數(shù)據(jù)捕獲 數(shù)據(jù)的捕獲是數(shù)據(jù)庫同步的基礎(chǔ),變化數(shù)據(jù)的捕獲主要有基于快照法、基于觸發(fā)器法、基于日志法、基于API法、影子表法和控制表變化法。基于快照法效率比較低一般不能用于同步,可使用基于觸發(fā)器法、基于日志法或基于API法和控制表變化法進(jìn)行變化數(shù)據(jù)的捕獲。 舊系統(tǒng)的數(shù)據(jù)庫操作都是通過存儲過程,所以可將存儲過程作為數(shù)據(jù)捕獲點。 新系統(tǒng)可采用筆者公司平臺底層提供了同步程序,該程序能將某個Linux用戶本平臺進(jìn)程下所有對指定表(需要同步的表)的所有INSERT、UPDATE和DELETE語句都捕獲到,并同步給另一個用戶下的同步數(shù)據(jù)接收進(jìn)程,該進(jìn)程能指定接收到同步數(shù)據(jù)時進(jìn)行的操作,例如寫文件、調(diào)用指定的業(yè)務(wù)進(jìn)行處理等。 3、同步方案 3.1 需要同步的內(nèi)容 3.1.1 確認(rèn)哪些SQL需要同步在數(shù)據(jù)庫表創(chuàng)建以后,有SELECT、INSERT、UPDATE和DELETE四種操作的語句,因為SELECT語句不會影響表數(shù)據(jù)的改變,所以只需要INSERT、UPDATE和DELETE操作進(jìn)行同步。 3.1.2 確認(rèn)哪些表需要同步并不是所有的表都需要進(jìn)行同步的,例如如下表就不需要同步: (1)在系統(tǒng)創(chuàng)建之初需要導(dǎo)入數(shù)據(jù),后期基本不需要改動或絕少改動的表:這些表的數(shù)據(jù)基本只需要在新系統(tǒng)初期將數(shù)據(jù)導(dǎo)入即可。 (2)一方系統(tǒng)具有,另一方不具有的功能對應(yīng)的表:例如新系統(tǒng)加上了一些額外的功能,而舊系統(tǒng)沒有,這些表不需要同步。 3.1.3 確認(rèn)異構(gòu)數(shù)據(jù)庫之間的表和字段的對應(yīng)這個是異構(gòu)數(shù)據(jù)庫編碼之前最耗費時間的工作,也是最重要的工作,因為只有嚴(yán)格對應(yīng),才能使兩者同步后數(shù)據(jù)庫在同步數(shù)據(jù)后不管用哪套系統(tǒng)都能完成同樣的工作。 首先,要對新舊系統(tǒng)中的近50張表找出對應(yīng)關(guān)系:某一張表在對方有一一對應(yīng)的表?還是對應(yīng)對方多張表?還是只是對應(yīng)對方表的一部分? 接著,需要找出字段的對應(yīng)關(guān)系,字段名稱是否相同?字段類型是否相同?一個字段是否對應(yīng)對方表的多個字段? 筆者在Excel表格中列出了所有表與對方表結(jié)構(gòu)的對應(yīng)關(guān)系,這個表格很重要,是后面無論采用何種同步方案都需要用到的同步的依據(jù)。 3.2 可選方案 3.2.1 編寫觸發(fā)器進(jìn)行同步 當(dāng)數(shù)據(jù)庫為同步對象創(chuàng)建相應(yīng)的觸發(fā)器,當(dāng)對同步對象進(jìn)行INSERT、UPDATE和DELETE等DML(Data Manipulation Language)操作時,觸發(fā)器被喚醒,將變換傳播到目標(biāo)數(shù)據(jù)庫。 采用此種方式時,需要在兩邊的數(shù)據(jù)庫中都創(chuàng)建對需要同步的每個表的INSERT、UPADTE和DELETE操作的三個觸發(fā)器,當(dāng)源表發(fā)生INSERT、UPDATE和DELETE操作時觸發(fā)器被啟動。因此若兩邊都有50個需要同步的表,需要編寫的觸發(fā)器個數(shù)為:(50+50)*3 = 300(個)。 采用該種方式的缺點是: (1) 需要為每個需要同步的表編寫三個觸發(fā)器,工作量巨大; (2) 觸發(fā)器具有不容易排錯、可移植性差、占用資源大等缺點; (3) 代碼可復(fù)用性不好。 3.2.2 按系統(tǒng)操作同步 按系統(tǒng)操作同步就是在所有進(jìn)行數(shù)據(jù)庫更新操作的地方都將其轉(zhuǎn)換成對方的數(shù)據(jù)庫操作進(jìn)行,例如在新系統(tǒng)進(jìn)行注冊操作(可能涉及到5、6個表進(jìn)行操作)時,轉(zhuǎn)換為對方的注冊操作。 這種同步方式的缺點在于: (1)不通用:在每加一個系統(tǒng)操作或做一些小改動時,都需要對代碼進(jìn)行修改; (2)代碼耦合度高:需要在所有操作的地方進(jìn)行處理,轉(zhuǎn)換成對方的SQL語句,代碼耦合度非常高; (3)工作量很大:需要對所有兩邊的操作進(jìn)行一次手工“轉(zhuǎn)譯”操作,工作量很大。 3.2.3 按數(shù)據(jù)庫表操作同步 按表操作同步的“原子”是對單個表的的INSERT、UPDATE和DELETE操作,它并不關(guān)注操作,例如:如果一個注冊操作對應(yīng)5個INSERT操作、2個UPDATE操作,它將其作為7個原子操作依次處理,并不對這些SQL進(jìn)行關(guān)聯(lián)。 這種同步方式的優(yōu)點在于: (1)相對比較通用:有一些比較簡單的對應(yīng)關(guān)系的表,例如只是因為字段名稱、表名和字段個數(shù)等不同而需要進(jìn)行同步的表可交給“SQL語句解析器通用程序”進(jìn)行處理,對于某些復(fù)雜的表才需要進(jìn)行單獨編寫業(yè)務(wù)來進(jìn)行轉(zhuǎn)換處理; (2)代碼耦合度比較低:只需要捕獲對同步的表的INSERT、UPDATE和DELETE操作的語句,基本不需要在代碼中加入對同步的處理。舊系統(tǒng)中不需要在上層進(jìn)行處理,在存儲過程中相關(guān)語句前處理同步即可。新系統(tǒng)只需要在同步接收進(jìn)程中指定需要處理的業(yè)務(wù)即可。 推薦使用該同步方式。 3.3 難點問題 3.3.1 自增主鍵當(dāng)表的主鍵為自增序列號時,在插入時并不指定該字段的值,在某一方插入后,轉(zhuǎn)換為對方的SQL語句后,插入對方的數(shù)據(jù)庫,很大可能兩邊的這條記錄的主鍵ID不一致。在根據(jù)自增序列號進(jìn)行這條記錄的update和delete操作時,因為兩邊同一條記錄的id不一樣,很大可能導(dǎo)致刪除或更新的記錄并不是想要進(jìn)行刪除或更新的記錄。 因此,在系統(tǒng)中盡量少用自增序列號主鍵,若能找到某幾個字段作為復(fù)合主鍵,可進(jìn)行修改,萬一找不到,可采用字符類型的唯一標(biāo)識號,例如:時間+自動機(jī)號+若干位隨機(jī)數(shù)數(shù),在INSERT操作時指定該主鍵的值。 不過,一些只進(jìn)行INSERT操作的表,例如未接來電表采用自增序列號暫時也不用遇到什么問題。在筆者所遇到的平臺中,新系統(tǒng)基本去除了自增主鍵,舊系統(tǒng)涉及自增主鍵的表并不太多,而且基本都能找到表中其它的2、3個字段作為唯一主鍵。 3.3.2 事務(wù)問題無法實現(xiàn)一些帶事務(wù)的操作。例如注冊等流程,因為采用按照數(shù)據(jù)庫操作進(jìn)行同步,注冊操作被分解成多個原子操作,只能當(dāng)成單個多條SQL語句單獨進(jìn)行處理。 需要事務(wù)的操作并不多,可將這些操作改成采用“按系統(tǒng)操作同步”,例如當(dāng)舊系統(tǒng)進(jìn)行注冊流程中,調(diào)用新系統(tǒng)提供的接口,由接口程序也進(jìn)行一個在新Oracle庫的注冊流程。 3.3.3 定期數(shù)據(jù)校驗 數(shù)據(jù)校驗也是異構(gòu)數(shù)據(jù)庫的一個重要問題,進(jìn)行一段時間的同步后,怎么能保證兩邊的數(shù)據(jù)庫是同步的?數(shù)據(jù)校驗的周期如何,是一天,幾天,還是? 進(jìn)行數(shù)據(jù)校驗首先要確定校驗指標(biāo),最簡單的校驗指標(biāo)是重要表的數(shù)據(jù)量是否相等,另外就是檢查表里面的數(shù)據(jù)是否一致,是否能保證能完成同樣的功能,可采用抽查機(jī)制等,這些工作不可能靠手工完成,因此需要提供數(shù)據(jù)校驗的程序。數(shù)據(jù)校驗的周期應(yīng)該是可配置的。 3.3.4 日志記錄在進(jìn)行同步的過程中,有可能因為各種原因?qū)е罗D(zhuǎn)換為對方的數(shù)據(jù)庫語句后執(zhí)行失敗,為了日后進(jìn)行處理和分析,進(jìn)行錯誤日志的記錄也是非常必要的。 |
|