1. 程式人生 > >用SyncNavigator實現資料庫資料定期同步實現

用SyncNavigator實現資料庫資料定期同步實現

WWW.SyncNavigator.CN    資料同步的軟體

SyncNavigator是一款專門用於SqlServer、Mysql資料同步的軟體,由國內頂級開發團隊開發完成,經歷8年逐步完善,目前具備強大的資料同步功能,國內很多大型連鎖超市,企業,公司都在用SyncNavigator資料同步軟體進行著資料同步服務。

它可以為我們提供智慧化資料同步,對您重要的資料庫進行實時同步操作,也可以設定定時任務傳輸,即使您的來源資料庫和目標資料庫版本不一樣,表結構不一樣,甚至是欄位不一樣,SyncNavigator也可以輕鬆幫您實現高效傳輸同步。

如果來源資料庫和目標資料庫表結構,欄位一樣,那麼全部保持預設設定即可,如果是異構資料庫,只需要動動滑鼠,輕鬆繫結來源資料庫表名和欄位,一一匹配,就能完成異構資料庫實時同步。

SyncNavigator可將資料庫同步到不同版本的資料庫上,無論你的資料庫是SqlServer 2000、還是SqlServer2008,還是SqlServer2014等,或者Mysql ,SyncNavigator都能輕鬆在他們之間無縫同步。

SyncNavigator資料庫同步軟體支援斷點續傳同步功能,第一次安裝配置好基本引數之後,就完全不用管,系統會在後臺執行,開關機也不影響資料同步,系統會在下次聯網的時候繼續上次未完成的作業,在資料庫同步的過程中出現故障,也能繼續同步資料庫,並確保資料完整性。

SyncNavigator同步是採用增量資料完成的,所以同步效率很高,每次只同步新資料或者新修改的資料,實時同步基本響應速度是毫秒級的,能迅速將源資料庫產生的新資料,或者修改的資料同步到目標資料庫上,確保資料完整性。

SyncNavigator有完善的日誌、報告郵件傳送功能,能保留每一步同步的步驟,供使用者查閱,郵件提醒功能能實時提醒傳輸進度。

SyncNavigator資料庫傳輸工具可以設定每張表的傳輸順序,以免有些表對別的邊的依賴性,先傳輸導致錯誤。

SyncNavigator資料庫傳輸工具可以設定傳輸開始或者結束後執行指定指令碼或者程式碼,能實現複雜的互動功能,讓使用者更靈活的實現自己需求。

支援分散式資料同步,可以把多個數據庫資料傳輸過來進行整合,也可以同時執行多個傳輸程序。

功能特色
SyncNavigator資料庫同步軟體特點:
1.能夠快速,持續,穩定的同步所需資料庫資料。在來源資料庫資料增加,修改或者刪除後自動同步到目標資料庫。
2.完整支援 Microsoft SQL Server。完整支援 Microsoft SQL Server 2000 2005 2008 2012 2014資料庫型別。並能在不同資料庫版本之間相互穩定高效同步資料,而不會出現問題。
3.完美支援 Mysql 4.1 以上版本。支援 Mysql 4.1 5.0 5.1 5.4 5.5   6.X。並能在不同資料庫版本之間相互同步資料,也可以將SqlServer 資料庫和Mysql資料庫之間進行同步,支援同構,異構資料庫同步。
4.只需要建立一個執行計劃就能在指定時間自動進行資料庫同步。輕鬆管理同步時間以及頻率,可以按天,或者按周,實時同步等,輕鬆設定,一鍵無憂。
5.不編寫SQL語句,不使用資料庫管理工具。與同類產品相比所需資料庫經驗知識最少,傻瓜式的同步設定,大多數情況下只需要設定來源資料庫地址,帳號密碼,目標資料庫地址,帳號密碼,然後其他保持預設,點選開始同步,就能完美完成資料同步需求。

實現這個需求,首先想到的是直接通過sql 進行同步,表之間資料同步無非是三種操作:更新,刪除,插入,假設兩個表 dst,src,dst中有id,name,auth三個欄位,src中有id,name,dsc三個欄位,需要將src 中的id,name同步到dst中去,如圖所示:


在dst和src中都存在的資料,只需要按照src中的資料,批量更新dst中的資料即可,sql語句可能是這樣:

update dst, src set dst.id=src.id,dst.name=src.name where src.id=dst.id;
1
更新完成之後,需要向dst表中插入在src存在,而dst中不存在的資料,簡單的sql可能是這樣:

insert dst (id,name,auth) select src.id,src.name,'1' from src where not exists(select dst.id from dst where src.id=dst.id);
1
再接著是刪除,將dst中存在src中不存在的資料稱從dst中刪除,sql如下:

delete from dst where not exists(select src.id from src where src.id=dst.id );
1
注意:如果是用的mysql上述同步刪除語句中的dst表明不能簡寫

有了這三條語句,寫個定時任務,依次執行即可,如果是用的spring,通常會用@Scheduled具體使用可以google一下,非常方便。如果需要事務可以使用@Transactional,這些是spring通過aop整合好的,可以宣告式使用,但是提供的粒度不夠靈活,使用也會有些限制,如果想更靈活點話,可以使用程式設計式事務。而如果資料庫開啟了autocommit功能,其本身就會有事務,不需要邏輯程式碼中再加事務(不是絕對的,當然要看自己需要,要記住autocommit只保證每一條sql是一個事務)。如果要看看自己的資料庫是否開啟了autocommit,可以用下面的sql:

show variables like 'autocommit'
1
這種方式的特點就是思路很簡單。不需要寫太多的java程式碼(定時任務都可以直接用spring封裝好的註解,只需要寫個類,寫個函式,如果使用orm的話,然後實現mybatis或hibernate相關的dao和service)。而這種實現的問題也很明顯,就是你對整個同步過程可控的東西很有限,最多通過事務保證如果同步失敗了,整體回滾。而且當同步邏輯比較複雜的時候,比如說表中欄位比較多,而且同步部分欄位,同步的欄位需要join其他表才能決定需不需要同步,這些邏輯全部寫在sql中會導致sql很臃腫,而且更容易出錯,更嚴重的是出錯了你卻什麼都做不了,也不知道具體哪裡同步出錯了。腫麼辦?那就一條一條的來唄。

要想對同步過程擁有足夠的控制,就只能將需要同步的資料全部load到記憶體,然後通過寫程式進行遍歷。具體過程應該是這樣的: 
 1. 將src中的資料全部load到記憶體中,如果資料量比較大(通常都是這樣,記憶體一次性放不下),就進行分頁load,sql語句如下:

select * from src limit 'pageSize' offset 'offset'  
1
其中'pageSize'通過程式設定,而'offset'就是pageSize*pageNo,比如說每頁100條資料,取第一頁的資料就是select * from src limit 100 offset 100*1

對取出來的資料進行迴圈遍歷,java程式簡寫如下:

private void syncData(){
    Date curTime = new Date();
    List<MyData> datas = myDataDao.getDatas(pageNo,pageSize);//訪問的是src表
    for(MyData data : datas){
        if(needToUpdate(data))//src表中的資料在dst中已經存在就update,否則就insert
            update(data);
        else insert(data);
    }
    deleteDatasFromNow(curTime); //刪除當前同步時間之前的資料
}
1
2
3
4
5
6
7
8
9
10
那麼needToUpdate做的就是判斷一下data是否在dst中存在,這裡需要一個唯一標識來確定當前data,通常是一個欄位或幾個聯合確定唯一的data。所以needToUpdate可能如下:

private boolean needToUpdate(MyData data){
    Optional<MyData> myData = myDataDao.findByName(data.getName);//這裡訪問的是dst表
    if(myData.isPresent()){
        return true;
    }
    else return false;
}
1
2
3
4
5
6
7
update和insert都會改變dst中的updateTime,所以在刪除的時候就可以通過updateTime是否晚於curTime來判斷當前資料是否更新過或新插入的,如果不是,那就是需要刪除的資料,所以deleteDatasFromNow()如下:

private void deleteDatasFromNow(Date curTime){
    List<MyData> datasNeedToDel = myDataDao.getDatasNeedToDel(curTime);
    for(MyData data : datasNeedToDel){
        delete(data);
    }
}
1
2
3
4
5
6
這樣整個同步過程就完成了,如果想要列印同步日誌或將同步過程記錄下來,就可以在update(),insert(),delete()中插入日誌操作就行了,就拿update()來說的話,可能像下面的情況:

private void update(MyData data){
    try{
        myDataDao.update(data);
    }
    catch(Exception e){
        logger.error("資料"+data.getName()+"同步出錯");//這裡是列印日誌,如果需要也可以儲存到資料庫
        return;
    }
    logger.info("資料"+data.getName()+"同步成功");
}
1
2
3
4
5
6
7
8
9
10
通過日誌檔案分析(如果將操作儲存到資料庫的話也可以直接查詢資料庫),可以清晰的知道哪些資料進行了更新,哪些資料是新插入的,哪些是刪除了的,然後還可以進行統計,共更新了多少資料,多少成功了,多少失敗了。業務層面就可以瞭解更多有關資料同步的資訊。而且這種操作使sql非常簡單,也不太容易出錯。但是一個很明顯的問題也暴露出來了,那就是效率問題,如果通過這種方式,勢必要遍歷每一條資料,對需要update,insert,delete的資料需要一個一個地進行訪問資料庫,而且對於needToUpdate(MyData data)中也額外訪問了一次資料庫,親測這個效率真是低驚人。而且這種實現中會導致,即便什麼資料都不更新,也會完全遍歷一遍資料,訪問同樣多的資料庫,所需的時間還是那麼久,這是在業務層面無法容忍的。於是就有了思路三。

既然上述方法的主要問題就是訪問資料庫過多導致效率底下,那麼就必須儘可能減少資料庫的訪問和遍歷的次數。那就需要緊貼業務需求,針對具體的需求進行改善。我遇到的需求就是每次資料同步的過程中,大部分資料都是不變的,只有少部分新增和刪除,針對這個需求進行了下面的優化: 
  * 不再每次將所有的src中的資料取出來,而是將需要刪除的和需要更新的,以及需要新插入的分別取出來,這樣資料取來之後就可以直接進行update,insert,delete了,不需要再進行額外的比較判斷的了 
  * 大部分資料不變,因此進行update的時候不再單條進行更新,直接進行分頁批量更新,比如說每次更新100條或者更多,以提高更新的效率。 
  通過這些優化大副提高了同步的效率,其中需要注意的是當寫稍微複雜點的sql的時候一定要注意,雖然都能得到相同的查詢結果,可能效率相差十萬八千里,在實現這個資料同步是,就因為join位置放的不對,導致查詢需要插入的資料時灰常慢,所以好好學學sql優化還是很有必要的,網上有很多大牛介紹,可以多看看,或者用的時候再學(我通常是這樣。。。)
--------------------- 
作者:浮生未央跡浮萍 
來源:CSDN 
原文:https://blog.csdn.net/xyjawq1/article/details/73703944 
版權宣告:本文為博主原創文章,轉載請附上博文連結!