java定时同步两台mysql_用java代码来定时增量同步数据库表的实现代码

import java.io.Serializable; import java.util.List; /** * Created by Administrator on 2017/4/19. * 这是基于是单线程来执行同步   千万不允许多线程执行    多线程执行太难写了  放弃吧!!!!! * 这里我们考虑有时间因素、以及mysql mvcc非锁定读的因素。 * 时间因素我们这样解决:1、以主服务器的时间为准。而非本地时间。本地时间快与慢不会影响同步功能 *                       2、主服务器可以调整它的时间,可以向前(改小时间)或向后(改大时间)调整,程序都是支持的。 *                              假设我们的同步时间是1小时同步一次,事物最大超时时间是5分钟(就是没有事物可以超过5分钟)。假设当前主服务器时间 *                              是: 08:00 , 那么上次同步时间是:06:55 *                              2.1、向前调整:假设向前调整5小时,那么是 03:00 ,   当我们同步的时候,获取主服务器的时间是 X ( 03:00 <= X <= 04:00) 因为我们的同步时间间隔是1小时 *                                   假设X=03:56 ,  那么min(06:55+01:00,03:56-01:00-00:05)=02:51   那么我们此次的同步时间将会是:02:51,那么是正确同步时间。 *                                   下次认为的上次同步时间将会是:02:51 *                              2.2、向后调整:假设向后调整5小时,那么是13:00,    当我们同步的时候,获取主服务器的时间是:Y (13:00 <= Y <= 14:00) 同理。 *                                   假设Y=13:56,那么min(06:55+01:00,13:56-01:00-00:05)=07:55   那么我们此次的同步时间将会是:07:55,那么是正确同步时间。 *                                   下次认为的上次同步时间将会是:13:56-01:00-00:05 = 12:51   这个时候时间就一下进步了很多了(跟上时间的步伐)。 * * 是id类型 */ public abstract class BaseSyncUserInfoTaskImpl implements ISyncUserInfoTask{     //同步时间间隔  可以稍微大点(比真实在定时任务的执行中的间隔大,但是千万别小于他,等于定时任务执行间隔最好)     private int sync_time_interval_in_milsecond = 10*60*1000;     //事物处理最长时间  建议同步时间间隔大于此时间     private int tx_time_out_in_milsecond = 5*60*1000;     //上次同步时间     private Long up_sync_time = null;     //本次同步时间     private Long this_sync_time = null;     /**      * 执行总体架构      */     @Override     public final void sync() {         //获取同步时间  与主服务器商定同步时间         long nowSyncTime = getSyncTime();         //开始数据同步         syncDatas(nowSyncTime);         //同步数据仅仅解决更新与插入的问题   这里去解决删除的问题         //有些表不会存在删除操作,这里对那些不需要删除的表直接跳过         if(isNeedDel)             syncDel();         //这个放到最后   怕事物回滚   而时间没有被回滚  导致下次同步时,up_sync_time不正确         updateUpSyncTime();     }     //加synchronized 仅仅是怕jvm优化  导致语句重排   一定要在最后来更新这个时间     protected synchronized  void updateUpSyncTime(){         up_sync_time = this_sync_time;     }     private  void syncDel() {         //1、本地取全部id集合的摘要   MD5,以及记录数   拿去远程比较,相等则啥都不做         CommonKVQuery abstractAndCount = getLocalIdsAbstractAndCount();         boolean isMach = isMachMasterServer(abstractAndCount);         if(isMach)             return ;         //2、把本地的数据按照id进行分页拿到远程去对比,没有则拿回来进行删除 。         DefaultPageRequest pageRequest = new DefaultPageRequest();         pageRequest.setLimit(100);         pageRequest.setPage(1);         List ids = null;         List delIds = null;         do {             ids = listLocalIds(pageRequest);             delIds = getNeedDelIdsFromMasterServer(ids);             deleteLocalByIds(delIds);             pageRequest.setPage(pageRequest.getPage()+1);         } while (ids.size() == pageRequest.getLimit());     }     /**      * 删除本地的数据  通过id集合      * @param delIds      */     protected abstract void deleteLocalByIds(List delIds);     /**      * 去远处匹配  找出需要删除的id集合      * @param ids      * @return      */     protected abstract List getNeedDelIdsFromMasterServer(List ids);     //分页获取本地id集合     protected abstract List listLocalIds(DefaultPageRequest pageRequest);     //去主服务器匹配摘要及记录数     protected abstract boolean isMachMasterServer(CommonKVQuery abstractAndCount);     //获取本地id集合摘要及记录数量     protected abstract  CommonKVQuery getLocalIdsAbstractAndCount() ;     //同步数据   更新时间在指定的时间之后的数据进行更新     protected abstract void syncDatas(long nowSyncTime) ;     private long getSyncTime(){         final long masterServerTime = getMasterServiceTime();         if(up_sync_time == null){             up_sync_time = getLocalMaxUpdateTime() - sync_time_interval_in_milsecond;             //若上次跟新时间为null,表示系统重启,进行第一次同步,那么来一次全量同步 //            this_sync_time = masterServerTime - sync_time_interval_in_milsecond-tx_time_out_in_milsecond; //            return 0l;         } //        min(主服务器时间 - 同步时间间隔(1小时) - 最大事物超时时间(5分钟),上次商定的时间 + 同步时间间隔) //        这里的5分钟我考虑的是最大事物的用时。就是假定所有事物的时间长度不可以超过5分钟。 //        因为我们在程序中经常是先设置更新时间,然后插入数据库,然后再做些别的(浪费了一些时间), //        最后提交了事物。那么根据mvcc模式,非锁定读,是读快照。导致更新时间本应该在本次同步中被同步的,而并没有同步到 //(不可见),而下一次的同步时间又大于了这个更新时间。导致会丢失更新。所以每次同步,都多同步5分钟的数据。 //        就怕丢下这种间隙中的数据。         this_sync_time =  Math.min(up_sync_time + sync_time_interval_in_milsecond,                 masterServerTime-sync_time_interval_in_milsecond-tx_time_out_in_milsecond) ;         final long result = Math.max(0,this_sync_time);         //这里的这一次同步时间取值是 主服务器时间-同步时间间隔-事物最大超时时间         //而舍弃了up_sync_time + sync_time_interval_in_milsecond 这个取值,原因在于让下一次的更新跟上主服务器的时间,不要距离太远         this_sync_time = masterServerTime - sync_time_interval_in_milsecond-tx_time_out_in_milsecond;         return result;     }     /**      * 获取本地记录中的最大更新时间      * @return      */     protected abstract long getLocalMaxUpdateTime() ;     //获取主服务器的当前时间     protected abstract long getMasterServiceTime();     /**      * 表数据是否需要删除操作,不会删除,则可以减少去同步被删的数据      */     private boolean isNeedDel = false;     public void setSync_time_interval_in_milsecond(int sync_time_interval_in_milsecond) {         this.sync_time_interval_in_milsecond = sync_time_interval_in_milsecond;     }     public void setTx_time_out_in_milsecond(int tx_time_out_in_milsecond) {         this.tx_time_out_in_milsecond = tx_time_out_in_milsecond;     }     public void setNeedDel(boolean needDel) {         isNeedDel = needDel;     } }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个用Java代码实现定时增量同步数据库的示例: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class IncrementalSync { private static final String DB_URL = "jdbc:mysql://localhost:3306/mydb"; private static final String DB_USER = "root"; private static final String DB_PASSWORD = "mypassword"; private static final String SOURCE_TABLE = "source_table"; private static final String DESTINATION_TABLE = "destination_table"; private static final String LAST_SYNC_COLUMN = "last_sync"; public static void main(String[] args) { Timer timer = new Timer(); timer.scheduleAtFixedRate(new IncrementalSyncTask(), 0, 60 * 60 * 1000); } private static class IncrementalSyncTask extends TimerTask { public void run() { Connection sourceConn = null; Connection destConn = null; PreparedStatement selectStmt = null; PreparedStatement insertStmt = null; ResultSet rs = null; try { sourceConn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); destConn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); // Get the timestamp of the last sync from the destination table Timestamp lastSync = null; String selectLastSyncSql = "SELECT " + LAST_SYNC_COLUMN + " FROM " + DESTINATION_TABLE; PreparedStatement selectLastSyncStmt = destConn.prepareStatement(selectLastSyncSql); ResultSet lastSyncRs = selectLastSyncStmt.executeQuery(); if (lastSyncRs.next()) { lastSync = lastSyncRs.getTimestamp(1); } lastSyncRs.close(); selectLastSyncStmt.close(); // Select all rows from the source table that have been updated since the last sync String selectSql = "SELECT * FROM " + SOURCE_TABLE + " WHERE last_updated > ?"; selectStmt = sourceConn.prepareStatement(selectSql); selectStmt.setTimestamp(1, lastSync); rs = selectStmt.executeQuery(); // Insert the updated rows into the destination table String insertSql = "INSERT INTO " + DESTINATION_TABLE + " VALUES (?, ?, ?)"; insertStmt = destConn.prepareStatement(insertSql); while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); Timestamp lastUpdated = rs.getTimestamp("last_updated"); insertStmt.setInt(1, id); insertStmt.setString(2, name); insertStmt.setTimestamp(3, lastUpdated); insertStmt.executeUpdate(); } // Update the timestamp of the last sync in the destination table String updateSql = "UPDATE " + DESTINATION_TABLE + " SET " + LAST_SYNC_COLUMN + " = ?"; PreparedStatement updateStmt = destConn.prepareStatement(updateSql); updateStmt.setTimestamp(1, new Timestamp(System.currentTimeMillis())); updateStmt.executeUpdate(); updateStmt.close(); } catch (SQLException e) { e.printStackTrace(); } finally { try { if (rs != null) rs.close(); } catch (SQLException e) { } try { if (selectStmt != null) selectStmt.close(); } catch (SQLException e) { } try { if (insertStmt != null) insertStmt.close(); } catch (SQLException e) { } try { if (sourceConn != null) sourceConn.close(); } catch (SQLException e) { } try { if (destConn != null) destConn.close(); } catch (SQLException e) { } } } } } ``` 该示例使用了Java的Scheduler API来定期执行一个任务,这个任务会连接源数据库和目标数据库,在目标数据库中记录上一次同步的时间戳,然后查询源数据库中有哪些行是在上一次同步之后更新过的,将这些行插入到目标数据库中,并更新目标数据库中的时间戳。可以根据需要修改源数据库、目标数据库名、时间戳列名等参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值