有些场景下,需要隔离不同的DB,彼此DB之间不能互相访问,但实际的业务场景又需要从A DB访问B DB的情形,这时怎么办?我认为有如下常规的三种方案:

1.双方提供RESET API,需要访问不同DB数据时,可以通过API来获取指定数据;

这种方案优点是隔离性、定制性强,统一出入口,只能通过指定的API访问指定的数据;缺点与优点是对立的,也就是定制性太强,导致每次业务发生变更,需要访问不同数据的时候,需要双方更改API的入参或返参,降低了开发效率;而且无法使用表JOIN,这样在某些情况下也会导致查询数据效率变低。目前主流的方案都是建议使用API方案

2.利用DB的同步技术(如:SQL SERVER的订阅复制、MYSQL的主从复制脚本等)来实现不同DB的数据同步共享

这种方案优点是可以在同一个DB访问到另一个DB中所需表的数据,可以直接JOIN,把原来的跨DB访问变成了同一个DB的事情;缺点是依赖DB的同步技术,而且两台DB服务器的网络必需互通,没有完全的隔离,且往往同步过来的表不允许直接修改,或需修改仍然需要跨DB修改或使用方案1的API来进行修改。

3.通过程序代码实现两个DB的数据同步(增、删、改、查),如:可以定时轮询源DB的A表,然后获取变更的记录(一般是:增、删、改的记录),再通过程序代码把源DB的A表的变更记录批量更新(若是新增、则是插入,若是修改,则是更新,若是删除,则是删除)到目的DB的A表中。

这种方案的优点是:可以根据实际情况灵活定制同步的表数据,不局限于某一张表或某一个DB,可以保证不同DB间同步表的数据一致性,让本来跨DB操作表变成了同一个DB的事情,而且可以增、删、改、查,功能不受限;缺点是灵活性太强,程序代码实现可靠的跨DB的实时同步逻辑的实现复杂度较高,对于开发人员的要求较高,如果写的同步逻辑无法保证实时、可靠、高可用,那对于业务来讲是灾难性的。

上述三种方案,第1、2方案基本都是定制化的常规方案,我(梦在旅途,http://www.zuowenjun.cn)今天要分享的是第3种方案:跨DB增量(增、改)同步两张表的数据,注意是增量同步,其中删除这个我没有说明,原因是如果DB表中记录是物理删除(即:真实的DELETE),那就无法简单的通过程序代码获取到删除的记录,除非在DB中加入DELETE触发器记录删除记录的主键到临时表或开启更改追踪(CHANGE_TRACKING)或DB日志分析,故本文讲的是不给表、DB增加额外负担的情况实时增量同步,至于删的同步这个我认为最好是逻辑标记删除(过期最后清理【真实删除】),而不要物理删除。

关于程序代码实现跨DB同步表数据方案,之前已有总结过,详见:https://www.cnblogs.com/zuowj/p/6264711.html  ---》4.利用BCP(sqlbulkcopy)来实现两个不同数据库之间进行数据差异传输(即:数据同步)

之前的文章同步主要是基于TranFlag标记字段 或触发器来实现同步,这种方式必需对表数据的增、删、改逻辑都有要求与规范,也就是增、改必需更改TranFlag=0,删必需记录表删除临进表中,这样才能实现同步逻辑,而今天是在这个同步基础上(BCP),不给表、DB增加额外负担的情况实时增量同步,对数据源的插入、改动没有要求。

代码如下:(以下同步适用于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 其它同步过滤查询条件 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);//记错误日志}

 上述同步代码逻辑很简单,可以参照之前的文章,这里主要是说明几个重要点:

1.TS_SyncUptime表用于记录与管理同步任务的信息,主要包含如下几个字段:

TableName:要同步的表名,UPTime每一次同步的触发时间点(可更改),sys_tamp行变更时间戳(不可更改),LastUPstamp行最后有效变量时间戳(可以更新)

2.具体关键同步逻辑如下:

2.1先更新TS_SyncUptime表,以便触发sys_tamp行变更时间戳发生改变(相当于记录同步触发时间点),在更改的同时取出LastUPstamp行最后有效变更时间戳(相当于上次同步的触发时间点)

2.2使用LastUPstamp作为过滤条件,查询>源DB的源表中时间戳字段,这样就可以查询出自上一次同步触发点到当前时间待同步的记录(增、改)

2.3利作BCP执行同步(详见之前文章说明)

2.4确保同步成功后,再次更新TS_SyncUptime表,并把sys_tamp行变更时间戳(当前触发时间点)更新到LastUPstamp行最后有效变量时间戳(记住本次触发时间点)

如上步骤即可实现可靠的同步,有人可能有疑问,这样就能实现可靠同步吗?我这里解释一下:

3.1同步触发时记录当前触发时间点,并取得上一次的触发时间点(这里的上一次触发时间点是指上一次开始准备同步的记录时间点,确保从上一次查询到同步完成之间的时间点都包括其中,防止漏数据)

3.2如果同步的任一环节失败(只要最终没有同步成功),那么再次同步触发时均取到的是同 一个时间点(LastUPstamp),而且即使重复执行同步逻辑,也不会出现重复(因为存在则更新不存在则插入原则),保证幂等,这样就确保了同步的可靠性

3.3当然如果某个时间点的数据或某个DB有问题,导致一直同不不成功,可能会出现一直同步不过去的情况,这种情况可以加上预警+人工干预,这个是概率的事情。

好了,如果大家有什么好的意见或建议欢迎下方留言评论,谢谢!

转载于:https://www.cnblogs.com/zuowj/p/9473984.html

关于跨DB增量(增、改)同步两张表的数据小技巧相关推荐

  1. MySQL同步两张表数据

    一.背景 项目中客户需要一个发布/编辑的功能,数据要存档. 我的方案设计是新建两张表,一张主表用于查询,一张临时表用于增删改. 增删改操作的表命名为XXX_temp,后台管理操作.后台操作完成后需要把 ...

  2. oracle两张表 比较好,比较Oracle两张表的数据是否一样

    比较Oracle两张表的数据是否一样 爱搞机 2008-10-21 11:00 在某些情况下,我们会需要比较两张表的数据是否一样. 假设有两张表A与表B他的字段相同,但是当中的数据可能不同,而且有些字 ...

  3. 对比两张表的数据并筛选出数据不同的

    描述: 表A和表B的主键A1和B1是相同的,现在需要A2和B2比较,A3和B3比较,将A2不等于B2和A3不等于B3的数据从表A中筛选出来.这样的SQL语句怎么写? SQL语句对比两张表的数据并筛选出 ...

  4. 比较两张表的数据是否相同

    在某些情况下,我们会需要比较两张表的数据是否一样. 假设有两张表A与表B他的字段相同,但是当中的数据可能不同,而且有些字段的数据还有可能为空 方法一(手动):把需要比较的两张表的数据按照某种规则排序后 ...

  5. sqlserver如何把两张表的数据合并为一张表

    今天在公司做项目的时候遇到一个情况,有两张临时表A(inco varchar(50)).表B(qty varchar(50)) 需要将这个两个表的数据插入到一张临时表中C(inco varchar(5 ...

  6. Oracle 对比两张表的数据是否一致

    使用 minus 关键字(minus:差别,缺少) 有两张表CHECK_CITY_1和CHECK_CITY_2,现在要互相对比一下,两个表数据的差异,(即A中有哪些B里没有,B中有哪些A中没有) se ...

  7. 如何删除有外键关系的两张表的数据

    文章目录 外键的定义 如何删除外键关系的两张表(父表 子表)的数据 方式一 方式二 两张表互为外键约束,删除任何一张表都会出错 为了保证数据完整 ,有一种方式就是两张表设置外键foreign key. ...

  8. 同时删除两张表的数据_把数据表中对应工作表的数据首先删除,然后导入数据...

    大家好,我们今日继续讲解VBA数据库解决方案的第28讲内容:利用VBA,把数据表中对应工作表的数据首先删除,然后向数据表中导入工作表数据.数据库的讲解已经持续一段时间了,从对简单数据库的认识到利用VB ...

  9. 对比数据库中两张表的数据

    背景:有一张总表,多张其他表,筛选出主表中有其他表中没有的数据 1. 在 总表中添加一个标记字段 biaoji 2. 用 inner jion 内连接两个表 找出两个表交叉的数据 SELECT a.* ...

最新文章

  1. c语言实现数码管显示qq号,各位大神,如何用C语言实现在数码管上实现1234同时亮...
  2. oracle exp导出分区表,【实验】【PARTITION】exp导出分区表数据
  3. Web 服务器 之 安装 Apache 2 和 Tomcat 5.5
  4. go http 处理w.write 错误_Go语言中的异常和错误处理简介
  5. 逻辑智力题【更新中】
  6. 1.1 Python 安装
  7. 【Elasticsearch】用ElasticSearch实现基于标签的兴趣推荐
  8. select系统调用
  9. Testbench编写
  10. 2022全新【趣盒】iapp源码带后台非常好看
  11. 网页多种资源下载插件
  12. 单双面打印价格一样吗_正式合同应该打印单面还是双面?
  13. 带你理清:ROS机器人导航功能实现、解析、以及参数说明
  14. 设计师的配色理论:你真懂颜色了吗?
  15. 重磅!腾讯优图20篇论文入选CVPR 2021
  16. 微信图片去除马赛克_微信怎么把图片加上马赛克_微信如何将照片打码的方法介绍_3DM手游...
  17. 计算机视觉、图像处理学习资料汇总
  18. 09静态资源虚拟主机
  19. 专访《突破》作者刘朋:程序员快速提升领导力的15个模式!
  20. 一级计算机B理论知识和答案,计算机一级B试题+理论答案 10秋06

热门文章

  1. C++纯虚函数和抽象类
  2. Eclipse reports rendering library more recent than
  3. Struts2 注解中跳转 action
  4. FreeRTOS 的命名规则
  5. Linux系统调用及用户编程接口(API)学习
  6. 【译】ICO 2.0 — The Advent of What Crypto-Fund Raising Should Really Look Like
  7. 深入了解以太坊虚拟机
  8. 一个关于binder的debug技巧
  9. 基于机器学习的web异常检测
  10. 【问链财经-EOS公开课】 第十九课 EOS存储之IPFS