MySQL同步两张表数据

一、背景

项目中客户需要一个发布/编辑的功能,数据要存档。

我的方案设计是新建两张表,一张主表用于查询,一张临时表用于增删改。

增删改操作的表命名为XXX_temp,后台管理操作。后台操作完成后需要把临时表数据同步到主表中。

二、解决方案

初始方案:根据条件查询临时表所有数据,java程序中判断主表中是否有数据,有数据进行更新,无数据插入。后来嫌判断麻烦,还需要写更新语句,索性重置主表数据,重新插入。

表结构:

请添加图片描述

  /**
     * 同步数据 BO.java
     * @param request
     * @return
     * @throws ServiceException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResponse syncPromotion(CommonRequest request) throws ServiceException {
        UserPromotionListReqDto reqDto = new UserPromotionListReqDto();
        CommonResponse response = new CommonResponse(request);
        reqDto.setConsumerSign(false);
        // 查询所有列表
        UserPromotionListResDto resTempDto = promotionService.getUserPromotionList(reqDto);
        // 初始化主表数据
        promotionService.initPromotion();
        // 插入
        promotionService.insertPromotionBatch()
        return response;
    }

这样逻辑比较清晰,但是重复的查询、更新和插入,若数据量比较大、请求多必会引起阻塞。而且逻辑处理写在bo层,增删查改需要到dto层操作,初始化、查询、插入都需要建立dto,显得很麻烦。

解决方案:

Oracle中有 merge into 语句,能够合并两张表数据,

示例(原文链接:https://blog.csdn.net/qq_44772660/article/details/112285088):

MERGE A表 AS a 
USING ( SELECT x.id, x.field_2, x.field_3,x.field_4 FROM B表 x )//查询有用的字段
AS b
 ON a.id= b.id  //匹配条件
WHEN MATCHED THEN //当匹配时执行update
UPDATE 
	SET a.field_2 = b.field_2
WHEN NOT MATCHED  THEN  //当不匹配时执行insert
	INSERT (id,field_2,field_3,field_4) VALUES (b.id,b.field_2,b.field_3,b.field_4);

当A表中有数据时执行update,无数据执行insert

mysql 中无merge into 语法,可以改为 ON DUPLICATE KEY 实现

INSERT INTO promotion_info ( promotion_id) SELECT
promotion_id,
FROM promotion_info_temp 
ON DUPLICATE KEY UPDATE promotion_id = VALUES ( promotion_id )

同步多个字段,以及有条件同步

INSERT INTO promotion_info ( promotion_id, image, NAME, position, certificate, qr_code, sort, delete_flag, release_flag ) 
SELECT promotion_id,image,NAME,position,certificate,qr_code,sort,delete_flag,release_flag 
FROM promotion_info_temp 
WHERE release_flag = 'N' 
AND delete_flag = 'N' 
ON DUPLICATE KEY 
UPDATE promotion_id = VALUES( promotion_id ),
	image = VALUES( image ),NAME = VALUES( NAME ),
	position = VALUES( position ),certificate = VALUES( certificate ),
	qr_code = VALUES( qr_code ),
	sort = VALUES( sort ),
	delete_flag = VALUES( delete_flag ),
	release_flag = VALUES(release_flag)

注意:

若不想主表中数据重复,操作的字段中需要某字段有唯一索引,不然执行完后会出现同样的数据。且要避免多个唯一索引,例如如果

where a=1 OR b=2

匹配多个行,只有一个行被更新

三、深入思考

1.优点

简化java处理逻辑,避免重复查询,满足大多数需求。

2.缺点

①性能带来开销,尤其是系统比较大的时候。

②在高并发的情况下会出现错误,可能需要利用事务保证安全。

3.执行完成,影响行数2

请添加图片描述
官方手册说明
请添加图片描述

插入行为1 ,更新行为2,未更新为0

四、参考资料:

【ON DUPLICATE KEY UPDATE 用法与说明】https://blog.csdn.net/qq_43279637/article/details/92797641

【java 对两张表进行数据同步】https://blog.csdn.net/qq_44772660/article/details/112285088

【mysql手册】https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html

仅供参考,欢迎讨论。若有错误,恳请指正

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值