关于跨DB增量(增、改)同步两张表的数据小技巧
有些場(chǎng)景下,需要隔離不同的DB,彼此DB之間不能互相訪問,但實(shí)際的業(yè)務(wù)場(chǎng)景又需要從A DB訪問B DB的情形,這時(shí)怎么辦?我認(rèn)為有如下常規(guī)的三種方案:
1.雙方提供RESET API,需要訪問不同DB數(shù)據(jù)時(shí),可以通過(guò)API來(lái)獲取指定數(shù)據(jù);
這種方案優(yōu)點(diǎn)是隔離性、定制性強(qiáng),統(tǒng)一出入口,只能通過(guò)指定的API訪問指定的數(shù)據(jù);缺點(diǎn)與優(yōu)點(diǎn)是對(duì)立的,也就是定制性太強(qiáng),導(dǎo)致每次業(yè)務(wù)發(fā)生變更,需要訪問不同數(shù)據(jù)的時(shí)候,需要雙方更改API的入?yún)⒒蚍祬?#xff0c;降低了開發(fā)效率;而且無(wú)法使用表JOIN,這樣在某些情況下也會(huì)導(dǎo)致查詢數(shù)據(jù)效率變低。目前主流的方案都是建議使用API方案
2.利用DB的同步技術(shù)(如:SQL SERVER的訂閱復(fù)制、MYSQL的主從復(fù)制腳本等)來(lái)實(shí)現(xiàn)不同DB的數(shù)據(jù)同步共享
這種方案優(yōu)點(diǎn)是可以在同一個(gè)DB訪問到另一個(gè)DB中所需表的數(shù)據(jù),可以直接JOIN,把原來(lái)的跨DB訪問變成了同一個(gè)DB的事情;缺點(diǎn)是依賴DB的同步技術(shù),而且兩臺(tái)DB服務(wù)器的網(wǎng)絡(luò)必需互通,沒有完全的隔離,且往往同步過(guò)來(lái)的表不允許直接修改,或需修改仍然需要跨DB修改或使用方案1的API來(lái)進(jìn)行修改。
3.通過(guò)程序代碼實(shí)現(xiàn)兩個(gè)DB的數(shù)據(jù)同步(增、刪、改、查),如:可以定時(shí)輪詢?cè)碊B的A表,然后獲取變更的記錄(一般是:增、刪、改的記錄),再通過(guò)程序代碼把源DB的A表的變更記錄批量更新(若是新增、則是插入,若是修改,則是更新,若是刪除,則是刪除)到目的DB的A表中。
這種方案的優(yōu)點(diǎn)是:可以根據(jù)實(shí)際情況靈活定制同步的表數(shù)據(jù),不局限于某一張表或某一個(gè)DB,可以保證不同DB間同步表的數(shù)據(jù)一致性,讓本來(lái)跨DB操作表變成了同一個(gè)DB的事情,而且可以增、刪、改、查,功能不受限;缺點(diǎn)是靈活性太強(qiáng),程序代碼實(shí)現(xiàn)可靠的跨DB的實(shí)時(shí)同步邏輯的實(shí)現(xiàn)復(fù)雜度較高,對(duì)于開發(fā)人員的要求較高,如果寫的同步邏輯無(wú)法保證實(shí)時(shí)、可靠、高可用,那對(duì)于業(yè)務(wù)來(lái)講是災(zāi)難性的。
上述三種方案,第1、2方案基本都是定制化的常規(guī)方案,我(夢(mèng)在旅途,http://www.zuowenjun.cn)今天要分享的是第3種方案:跨DB增量(增、改)同步兩張表的數(shù)據(jù),注意是增量同步,其中刪除這個(gè)我沒有說(shuō)明,原因是如果DB表中記錄是物理刪除(即:真實(shí)的DELETE),那就無(wú)法簡(jiǎn)單的通過(guò)程序代碼獲取到刪除的記錄,除非在DB中加入DELETE觸發(fā)器記錄刪除記錄的主鍵到臨時(shí)表或開啟更改追蹤(CHANGE_TRACKING)或DB日志分析,故本文講的是不給表、DB增加額外負(fù)擔(dān)的情況實(shí)時(shí)增量同步,至于刪的同步這個(gè)我認(rèn)為最好是邏輯標(biāo)記刪除(過(guò)期最后清理【真實(shí)刪除】),而不要物理刪除。
關(guān)于程序代碼實(shí)現(xiàn)跨DB同步表數(shù)據(jù)方案,之前已有總結(jié)過(guò),詳見:https://www.cnblogs.com/zuowj/p/6264711.html? ---》4.利用BCP(sqlbulkcopy)來(lái)實(shí)現(xiàn)兩個(gè)不同數(shù)據(jù)庫(kù)之間進(jìn)行數(shù)據(jù)差異傳輸(即:數(shù)據(jù)同步)
?之前的文章同步主要是基于TranFlag標(biāo)記字段 或觸發(fā)器來(lái)實(shí)現(xiàn)同步,這種方式必需對(duì)表數(shù)據(jù)的增、刪、改邏輯都有要求與規(guī)范,也就是增、改必需更改TranFlag=0,刪必需記錄表刪除臨進(jìn)表中,這樣才能實(shí)現(xiàn)同步邏輯,而今天是在這個(gè)同步基礎(chǔ)上(BCP),不給表、DB增加額外負(fù)擔(dān)的情況實(shí)時(shí)增量同步,對(duì)數(shù)據(jù)源的插入、改動(dòng)沒有要求。
代碼如下:(以下同步適用于SQL SERVER?不同DB的表增量同步)
try{SqlConnection obConnSrc = new SqlConnection(connLMSStr);SqlConnection obConnDest = new SqlConnection(mconnCCSStr);string lastTamp = ClsDatabase.gGetFieldValue(obConnSrc, "update TS_SyncUptime set UPTime=GETDATE() OUTPUT (deleted.LastUPstamp) as oldtamp FROM TS_CCSUptime WHERE TableName=N'tableNameA'", "oldtamp");string selectSql = @"SELECT id,aaa,bbb,ccc,ddd,eee,fff FROM tableNameA WHERE 其它同步過(guò)濾查詢條件 AND CONVERT(bigint,sys_tamp)>{0}";selectSql = string.Format(selectSql, lastTamp);master.TransferBulkCopy(selectSql, obConnSrc,"tableNameA", obConnDest,(stable) =>{var colMaps = new Dictionary<string, string>();foreach (DataColumn col in stable.Columns){colMaps.Add(col.ColumnName, col.ColumnName);}return colMaps;},(tempTableName, stable, destConn, srcConn) =>{StringBuilder saveSqlBuilder = new StringBuilder("begin tran" + Environment.NewLine);string IUSql = master.BuildInsertOrUpdateToDestTableSql("tableNameA", tempTableName, new[] { "id" }, stable.ExtendedProperties[master.MapDestColNames_String], 2);saveSqlBuilder.Append(IUSql);saveSqlBuilder.AppendLine("commit");ClsDatabase.gExecCommand(destConn, saveSqlBuilder.ToString());ClsDatabase.gExecCommand(srcConn, "update TS_SyncUptime set UPTime=GETDATE(),LastUPstamp=CONVERT(bigint,sys_tamp) FROM TS_SyncUptime WHERE TableName=N'tableNameA'");return false;});}catch (Exception ex){writeLog(ex);//記錯(cuò)誤日志}上述同步代碼邏輯很簡(jiǎn)單,可以參照之前的文章,這里主要是說(shuō)明幾個(gè)重要點(diǎn):
1.TS_SyncUptime表用于記錄與管理同步任務(wù)的信息,主要包含如下幾個(gè)字段:
?
TableName:要同步的表名,UPTime每一次同步的觸發(fā)時(shí)間點(diǎn)(可更改),sys_tamp行變更時(shí)間戳(不可更改),LastUPstamp行最后有效變量時(shí)間戳(可以更新)
2.具體關(guān)鍵同步邏輯如下:
2.1先更新TS_SyncUptime表,以便觸發(fā)sys_tamp行變更時(shí)間戳發(fā)生改變(相當(dāng)于記錄同步觸發(fā)時(shí)間點(diǎn)),在更改的同時(shí)取出LastUPstamp行最后有效變更時(shí)間戳(相當(dāng)于上次同步的觸發(fā)時(shí)間點(diǎn))
2.2使用LastUPstamp作為過(guò)濾條件,查詢>源DB的源表中時(shí)間戳字段,這樣就可以查詢出自上一次同步觸發(fā)點(diǎn)到當(dāng)前時(shí)間待同步的記錄(增、改)
2.3利作BCP執(zhí)行同步(詳見之前文章說(shuō)明)
2.4確保同步成功后,再次更新TS_SyncUptime表,并把sys_tamp行變更時(shí)間戳(當(dāng)前觸發(fā)時(shí)間點(diǎn))更新到LastUPstamp行最后有效變量時(shí)間戳(記住本次觸發(fā)時(shí)間點(diǎn))
如上步驟即可實(shí)現(xiàn)可靠的同步,有人可能有疑問,這樣就能實(shí)現(xiàn)可靠同步嗎?我這里解釋一下:
3.1同步觸發(fā)時(shí)記錄當(dāng)前觸發(fā)時(shí)間點(diǎn),并取得上一次的觸發(fā)時(shí)間點(diǎn)(這里的上一次觸發(fā)時(shí)間點(diǎn)是指上一次開始準(zhǔn)備同步的記錄時(shí)間點(diǎn),確保從上一次查詢到同步完成之間的時(shí)間點(diǎn)都包括其中,防止漏數(shù)據(jù))
3.2如果同步的任一環(huán)節(jié)失敗(只要最終沒有同步成功),那么再次同步觸發(fā)時(shí)均取到的是同?一個(gè)時(shí)間點(diǎn)(LastUPstamp),而且即使重復(fù)執(zhí)行同步邏輯,也不會(huì)出現(xiàn)重復(fù)(因?yàn)榇嬖趧t更新不存在則插入原則),保證冪等,這樣就確保了同步的可靠性
3.3當(dāng)然如果某個(gè)時(shí)間點(diǎn)的數(shù)據(jù)或某個(gè)DB有問題,導(dǎo)致一直同不不成功,可能會(huì)出現(xiàn)一直同步不過(guò)去的情況,這種情況可以加上預(yù)警+人工干預(yù),這個(gè)是概率的事情。
好了,如果大家有什么好的意見或建議歡迎下方留言評(píng)論,謝謝!
轉(zhuǎn)載于:https://www.cnblogs.com/zuowj/p/9473984.html
總結(jié)
以上是生活随笔為你收集整理的关于跨DB增量(增、改)同步两张表的数据小技巧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue 引用 vue-resource步
- 下一篇: [USACO2009 OPEN] 滑雪课