posts - 297,  comments - 1618,  trackbacks - 0

蜜果私塾:如何进行异构数据库同步(下篇)

版权所有,转载请注明出处:http://www.blogjava.net/amigoxie/archive/2011/07/24/354917.html

文:阿蜜果

日期:2011-7-24

上篇:《如何进行异构数据库同步(上篇)》

1、详细设计

1.1 SQL语句通用解析程序

首先需要一个通用的“SQL语句通用解析程序”,因为异构数据库的大部分表都与另外的表有一一对应的关系,该解析程序用于对这些一一对应的表进行处理。

表与表之间的对应关系基于上篇提到的整理的Excel文档,“SQL语句通用解析程序”如何读取对应关系对收到的INSERTUPDATEDELETE语句进行处理呢?笔者采用的是将对应关系写入XML文档中,当然也可以采用另外的方式。

参考XML格式如下(Oracle 新系统 ->  SQL Server旧系统):

<table name="freephone" partyName="PLAT_FreePhone" fieldCount="8">
     
<field name="Phone" partyName="Phone" primary="true" />
     
<field name="ProductID" type="varchar" partyName="ProductID" partyType="int" />
     
<field name="AreaId" partyName="" />
     
<field name="Effect" partyName="" />
     
<field name="EffectLess" partyName="" />
     
<field name="Addtime" type="varchar" partyName="AddTime" partyType="datetime" partyValue/>
     
<field name="Operator" partyName="Operator" />
     
<field name="Remark" partyName="Remark" />
 
</table>

当一方对freephone表操作的INSERT语句:

insert into freephone (Phone, ProductID, AreaId, Effect, EffectLess, Addtime, Operator, Remark)values(‘13122223333’,‘003’,25,‘20110724000000’,‘20111024235959’,‘20110702409000000’, ‘amigo’, ‘amigo add!’)

根据上面XML配置和通用解析程序的处理,对应对方的新的SQL语句为:

INSERT INTO PLAT_FreePhone(Phone, ProductID, AddTime, Operator, Remark) values(‘13122223333’, 3GETDATE(), ‘amigo’, ‘amigo add!’)

再看一条UPDATE语句:

update freephone set ProductID=004’, AreaId=26 where Phone=13122223333

转换为对方的语句为:

update PLAT_FreePhone set ProductID=4 where Phone=13122223333

另外除了如上所演示的简单的类型不同、字段名称不同,有些字段在对方没有外,有时候有些字段还需要一定的转换,例如在一方存储的limited字符串是二进制方式,例如111111,而对方存储的是二进制对应的十进制的值,再例如,一方存储的是6位的时间(时分秒),而对方存储的只是4位的时间(时分),那么可做一次自定义的substr操作。

看另一个参考的XML实例:

<table name="phonelimited" partyName="PLAT_PhoneLimited" fieldCount="6">
    
<field name="Phonenumber" partyName="Phone" primary="true" />
    
<field name="AreaId" type="int" partyName="AreaID" partyType="int" />
    
<field name="Limited" type="varchar" partyName="Limited" partyType="int" function="binToDec" />
    
<field name="AddTime" type="varchar" partyName="AddTime" partyType="datetime" />
    
<field name="Operator" partyName="Operator" />
    
<field name="Remark" partyName="Remark" />
</table>

其中:function="binToDec"表示需要进行一次二进制到十进制的转换,一方的如下语句:

insert into phonelimited(Phonenumber, AreaId, Limited) values(‘13122223333’, 25, ‘10110’)

转换成对方的INSERT语句如下:

insert into PLAT_PhoneLimited(Phone, AreaID, Limited) values(‘13122223333’, 2522)

需要做取字串操作的参考定义如下:

<field name="StartTime" length="6" partyName="OpenTime" partyLength="4" function="substr" />

另外,还有一些字段本端没有,对端具有并且有点还是必填字段,并且对端的这些字段需要填写固定的值,因此在INSERTUPDATEDELETE语句都需要进行特别的操作,参考XML定义如下:

……
<insert fieldCount="2">
    
<field name="Node" value="0" />
    
<field name="Key" value="" />
</insert>
<update condition="and Node=0 and key=''" />
<delete condition="and Node=0 and key=''" />
……

1.2 SQL语句接收器程序

      异构数据库的SQL语句传过来时,需要一个SQL语句接收器程序,该接收器解析该语句操作的表名(例如phonelimited)、执行的操作名(INSERTUPDATE还是DELETE),根据这些信息读取配置文件信息,决定是调用“1.1 SQL语句通用解析程序”进行处理,如果不是存在一对一对应关系的表,扔给配置的指定业务进行特别处理。

      该程序的主要功能如下:

1)接收SQL语句:只接收需要同步的表的INSERTUPDATEDELETE语句,SELECT语句直接丢弃;

    2)分发SQL语句:将语句分发给不同程序进行处理,解析接收到的SQL语句的表名和操作名称,决定分发给通用解析进行处理还是特定解析程序进行处理。

         需要关注的问题:当多条SQL语句并发发送过来时,是启动多个独立的自动机处理,还是将语句放入队列中,依次出队列进行处理,还是采用其它方式进行处理呢?每条SQL语句启动独立的自动机处理效率最高,但是也存在问题:因为多条语句是竞争操作,如果操作的是同样的记录但做相反操作时怎么办?这些都是开发人员需要考虑到的问题。

1.3 SQL单个表特定解析程序

         在上篇中提到,并不是所有的表在两端有一一对应的表,对于一些本端一个表对应对端数据库多个表,或者本端多个表对应对端一个表的情况,通用解析程序不好处理这些语句,可将这些表采用特定的解析程序进行处理。

         对于一个表对应多个表的情况,可能一条INSERT语句对应对端数据库多条INSERTUPDATE语句。

         对于多个表对应一个表的情况,一条INSERT语句可能对应对方的一条INSERT语句或UPDATE语句。

1.4 带事务的操作

         像注册等流程,要严格保证事务,因此采用新旧系统提供接口(例如http接口或SOAP接口等)的方式,当某一端调用注册流程成功后,调用对端系统提供的注册的接口完成操作。

         因为这种操作并不多,所以并不需要太多的工作量。

1.5 数据校验程序

         要定期(一般是一天)对两边数据进行校验,对一些错误的数据及时的更正,进行数据校验首先要确定哪些东西需要进行数据校验,接着有针对性的进行核对。

2、扩展阅读

2.1 数据同步方法

对象变化是数据同步的基础,它直接决定了数据同步的更新方式和选时方式,所以数据同步常常按照变化捕获的不同进行分类,一般归结于如下集中基本方法:

1)基于快照法:快照是数据库中存储对象在某一时刻的即时映像。通过同步对象定义一个快照或采用类似方法,可以将它的当前映像作为更新副本的内容。

2)基于触发器法:在源数据库为同步对象创建相应的触发器,当同步对象进行INSERTUPDATEDELETEDML命令时,触发器被唤醒,将变化传播到目标数据库。

3)基于日志法:数据库日志作为维护数据库完整性的数据库恢复的重要工具,其中已经包含了全部成功提交的操作记录信息。该方法通过分析数据库日志的信息来捕获同步对象的变化序列。

4)基于API:一些小型的数据库和非关系型数据库没有触发器和日志机制,可以在应用程序和数据库之间引用一层中间件,由它提供一系列API,在API上来完成应用程序对数据库修改的同时,记录同步对象的变化序列。

5)基于影子表法:许多情况下,源程序无须了解同步对象的每一个操作,只要知道最后总共发生了什么变化就够了。因此,可以在初始化时为同步对象表T建立一个影子表S,作为一份当时的拷贝,以后通过在适当时机通过比较当前TS的内容获取净变化信息。

6)基于控制表变化法:就是为每个要同步的表创建一个控制表CC包含了主键字段Pk和一些控制信息字段,当T中某个字段发生改变时,C中同主键Pk的记录也随即被修改。这一过程通常可以通过触发器实现,到时候只需根据C就知道T中的变化信息。

 

3、附录

1)《异构数据库同步问题研究》:

http://wenku.baidu.com/view/d3b283bff121dd36a32d8293.html

posted on 2011-07-24 13:05 阿蜜果 阅读(2230) 评论(2)  编辑  收藏 所属分类: 解决方案


FeedBack:
# re: 如何进行异构数据库同步(下篇)
2011-07-25 22:21 | AlleNny
这样一个个insert如果数据量很大的话,效率非常低的。我曾经这样导出导入过很多上千万条数据的表,结果运行一天一夜都没完成。  回复  更多评论
  
# re: 如何进行异构数据库同步(下篇)
2011-07-25 22:38 | 阿蜜果
@AlleNny
我是打算N个insert是N个自动机去进行的,一次可以启动N个自动机,不过担心操作的数据有冲突。后来你的问题是怎么解决的呢?  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
<2011年7月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

      生活将我们磨圆,是为了让我们滚得更远——“圆”来如此。
      我的作品:
      玩转Axure RP  (2015年12月出版)
      

      Power Designer系统分析与建模实战  (2015年7月出版)
      
     Struts2+Hibernate3+Spring2   (2010年5月出版)
     

留言簿(256)

随笔分类

随笔档案

文章分类

相册

关注blog

积分与排名

  • 积分 - 2186585
  • 排名 - 3

最新评论

阅读排行榜

评论排行榜