用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 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/weixin_43668066/article/details/83961663
今日推荐