多主机数据库表数据同步 | 程序小兵

多主机数据库表数据同步

前言

在知识局限的我们,有时候,方法的高效性,真的很重要。

问题

项目中有个表的数据要从另一个数据库中同步,同步的机制为,若表中的某条数据某个字段更新了,则更新此字段,若干字段更新,则更新若干字段,对表没更新的字段,则略过…

分析

假设本地表为A,远程表为B,从需要从B同步更新的数据到A,正常操作流程为:

  • 判断数据字段是否有更新
  • 忽略掉那些没更新的记录(因为待同步的表数据量很大,全表更新慢…)
  • 从代码层,对比一个有N条数据M个字段的表的操作

方案1

原本的做法是定义2个对象,一个查询远程表所有记录,一个查询本地表所有记录,然后同步一个字段一个字段的判断是否相同,从而判断是否更新本地记录。

例如

Table tableA;
Tabel tableB;
List<tableA> tableAList = tableADAO.findAll();//取出远程记录
List<tableB> tableBList = tableBDAO.findAll();//取出本地记录
for(Table a : tableAList){
    for(Tabel b: tableBList){
        if(b.getX1() == a.getX1()){
            //则更新
        }
     if(b.getX2() == a.getX2()){
            //则更新
        }
    .......
    }
}

说明

这方案就是个巨坑……

方案2

数据源在远程服务器端,因此,本地的数据是可以进行增删改查而不会影响系统的正常运行,所以,进行同步时,最简便的方法为:
先删除本地记录,再把远程表对应的数据insert进本地表里。“先delete,再insert

说明

这方案,在允许删除数据的前提下,操作简便快捷,推荐。

方案3

方案2的可行性还是值得推荐的,但是,有一定的前提,而且,写起代码来,也有一定的代码量,有无更简便的方法呢,例如一行代码就解决的?脑中出现这个疑惑(没办法,谁叫我懒),经查询,发现了个Oracle9i以上都支持的sql方法merge into。(现在想想,我们现在能想到的问题,别人,特别是大公司,也肯定能想到做到)。于是乎,普及了下merge into的使用,豁然开朗,还真能解决我一行代码搞定的事:

merge into 是oracle9i新增的语法,用来合并updateinsert语句。通过merge语句,根据一张表或者子查询的连接条件对另一个表进行查询,连接条件匹配上的进行update,无法匹配的进行insert。这个语法仅需要完成一次全表扫描就完成了全部工作,执行效率高于insert+ update

语法:

merge [into [schema .] table [t_alias]
using [schema .] {table | view | subquery} [t_alias]
on (condition)
when matched then merge_update_clause
when not matched then merge_insert_clause;

有了此方法,我写好sql,通过DAO调用,瞬间完成同步功能。吊炸天了。又一次被我偷懒感动了。
下面是我的一个例子:

-- create table
create table merc_termconvert
{
slt_termcode char(8) not null, --1
slt_merccode char(15) not null, --2
merctype char(2) not null, --3
ispcode char(3) default 000 not null, --4
termcode char(8) not null,
--todo 
}

其中1,2,3,4为联合主键(这点很重要,因为主键的值是不能更新的,所以再merge into的语句里,是不能出现在when matched then后的update语句中的。

merge into merc_termconvert2 t2
using merc_termconvert t
on(  t2.slt_termcode = t.slt_termcode and t2.slt_merccode = t.slt_merccode and t2.merctype = t.merctype and t2.ispcode = t.ispcode) --1
when not matched then --2
    insert(xxx,xxx,xxx,xxx,xxx) values(yyy, yyy, yyy, yyy...)
when matched then --3
    update 
        set t2.termcode = t.termcode,
            xxx = yyy,
            xxx = yyy, 
            xxx = yyy,
            xxx = yyy,
            -- todo

说明
是需要将merc_termconvert的数据同步更新到 merc_termconvert2的远程表中。
1、没有匹配到记录时,实现的insert语句,数据的来源于本地表merc_termconvert
2、粉色箭头,指示的是这个表的4个联合主键,需要全部进行赋值在on的语句里。
3、匹配到的记录时,实现的update语句,数据来源于本地表merc_termconvert,而且,主键是不允许设置在此出现的。

具体的做法,参考上面的代码。

文章目录
  1. 1. 前言
  2. 2. 问题
  3. 3. 分析
    1. 3.1. 方案1
      1. 3.1.1. 说明
    2. 3.2. 方案2
      1. 3.2.1. 说明
    3. 3.3. 方案3
,