• 请不要在回答技术问题时复制粘贴 AI 生成的内容
pengyOne
V2EX  ›  程序员

Java 刚入职,做数据迁移,之前没接触过,现在有个需求,想了好久还是没有解决,能不能求大佬们帮忙看看,谢谢

  •  
  •   pengyOne · Jun 20, 2019 · 4255 views
    This topic created in 2528 days ago, the information mentioned may be changed or developed.

    项目要求是这样的:

    数据库中有几十个表,现在我要给其中大约一半的表增加两个字段,一个最后修改时间 LAST_CHANGE_TIME 和同步状态 SYNC_STATUS(0 或 1 同步过后变为 1).现在要求这些表每进行插入跟新操作,就同步更新同条记录的最后修改时间 LAST_CHANGE_TIME 和同步状态 SYNC_STATUS 变为 0.
    
    因为这是一个老项目,所以其他部分的增删改查都已经写好了.但公司不让我对原代码进行修改,而且也不能用触发器进行同步的修改操作.这就是我烦躁的原因.
    
    公司给出的方案是用 druid 的 filter 来操作,具体没有写.....
    
    然后我就尝试改写 druid 的 filter 里的 statementExecuteAfter 动态获取表名再进行修改操作,但是操作后发现,这种改写不能动态引入主键 ID 值来针对一条数据(我在外部定义可变 ID 进行修改,然后在重写的方法里引入,然而这个 ID 不管怎么改变,重写的方法里的 ID 都只会是第一个值).废了,不知道有没有大佬知道 druid 有什么针对这种的解决方案.....
    
    也尝试过 AOP 来解决,但是这些包扫描是个大问题,因为这个数据库可能有上百个表,而我这里只要修改不到二分之一的表而已,即使扫描全部,joinpointer 倒是可以获取传入的修改条件即 ID,但我却不知道怎么获取此次操作针对的是哪个表? 所以也陷入僵局...
    
    我很菜,这种需求我各种搜索也没找到解决的方法....求各位大佬帮忙看看怎么解决,给个思路,即使不是 druid 的 fiter 方案也好啊...我快被逼疯了
    
    Supplement 1  ·  Jun 20, 2019
    公司不让用触发器是因为担心出现问题.......这个项目要求是能承受 2w 个并发,不知道这种需求,用触发器会有问题吗?
    32 replies    2020-02-17 10:34:16 +08:00
    Cooky
        1
    Cooky  
       Jun 20, 2019 via Android
    不能改代码,不能用触发器,那还同步个鸡巴?
    难不成一直扫描数据库?
    zhangalong69
        2
    zhangalong69  
       Jun 20, 2019
    把这些表先都找找出来,用 python 脚本执行添加属性的操作,然后对单个表用小工具代码添加字段,比如打个 java 工程直接在生产环境添加,一张表一次取 1000 个数据,单线程多线程都可以
    pengyOne
        3
    pengyOne  
    OP
       Jun 20, 2019
    @Cooky 同步数据是每天定时同步.....最主要的就是原数据库那块同步状态的修改问题,因为可能对已有数据进行修改,然后就要改变它的状态从 1 变 0.....
    新增数据,我就直接给时间和状态设置默认值了,但修改数据的时候这两个字段的修改真的是......不会
    我也觉得很烦躁,这边还给我个思路说,中途拦截 sql 然后修改 sql 再继续执行.....而这我也不会啊,druid 有这种操作吗?
    securityCoding
        4
    securityCoding  
       Jun 20, 2019
    订阅 binlog?
    pengyOne
        5
    pengyOne  
    OP
       Jun 20, 2019
    @zhangalong69 emmmmm 字段添加很快就完成了.....我的疑惑是怎么更新的问题
    lazyfighter
        6
    lazyfighter  
       Jun 20, 2019
    LAST_CHANGE_TIME 可以在字段表达式完成 同步状态感觉没啥用,完全可以根据时间进行同步
    rockyou12
        7
    rockyou12  
       Jun 20, 2019
    看你有 aop 应该是 java+spring boot,可以在 dao 层的 insert、save 这些方法入手做 aop,直接把对象拿出来,反射获取字段 LAST_CHANGE_TIME 和 SYNC_STATUS 然后修改字段的值
    xxxy
        8
    xxxy  
       Jun 20, 2019 via Android
    在原代码和数据库间加一层代理?
    pengyOne
        9
    pengyOne  
    OP
       Jun 20, 2019
    @rockyou12 这应该不行,因为源代码那边的对象是没有我新增的这些字段的....而且这项目有些用 xml,有些直接用 @
    query,好像还有 hibernate????
    pengyOne
        10
    pengyOne  
    OP
       Jun 20, 2019
    @lazyfighter 判定时间确实可以耶,不过领导说要状态就用状态了吧........字段表达式是啥?可以做到在进行跟新操作后对该条数据修改吗?
    tomczhen
        11
    tomczhen  
       Jun 20, 2019
    这不就是 CDC 么。
    Finest
        12
    Finest  
       Jun 20, 2019
    用 canal 订阅 binlog 应该可以解决
    endershadow
        13
    endershadow  
       Jun 20, 2019
    canal 完美解决你的问题
    lazyfighter
        14
    lazyfighter  
       Jun 20, 2019
    @pengyOne `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    lazyfighter
        15
    lazyfighter  
       Jun 20, 2019
    刚刚百度了一下 mybatis 可以写拦截器修改 sql,那你的标志位也就解决了
    rqxiao
        16
    rqxiao  
       Jun 20, 2019
    hibenate 有个 listener ?
    x66
        17
    x66  
       Jun 20, 2019
    数据库 update time 字段设置成 update 的时候自动更新不就行了吗?然后根据 update time 捕捉变化数据
    EasyProgramming
        18
    EasyProgramming  
       Jun 20, 2019
    emmm,看需求描述,好像不是数据迁移呀?
    LuVx
        19
    LuVx  
       Jun 20, 2019
    如果不使用的 mysql 呢, ON UPDATE CURRENT_TIMESTAMP 也就没效果了, 最有效的感觉还是 lazyfighter 提出的拦截改写 sql, 或者用 canal(实时性要求不高的话)
    pengyOne
        20
    pengyOne  
    OP
       Jun 20, 2019
    @hand515
    @endershadow 我这用的是 oracle 能用这 canal 吗?我看百度好像说这是操作 mysql 的,而且也没什么示范的实例
    pengyOne
        21
    pengyOne  
    OP
       Jun 20, 2019
    @EasyProgramming 应该说是数据同步才是.....现在这个就是同步之前的状态更改问题,每天定时同布
    LuVx
        22
    LuVx  
       Jun 20, 2019
    @pengyOne 开源版本不支持 oracle, 考虑用 binlog 订阅的话, 尝试 OGG
    https://github.com/alibaba/canal
    ps. 目前内部版本已经支持 mysql 和 oracle 部分版本的日志解析,当前的 canal 开源版本支持 5.7 及以下的版本(阿里内部 mysql 5.7.13, 5.6.10, mysql 5.5.18 和 5.1.40/48)
    pengyOne
        23
    pengyOne  
    OP
       Jun 20, 2019
    @lazyfighter
    @LuVx 是的,我这用的是 Oracle......而且这用的是 Spring Data JPA,这好像是基于 hibernate 的吧?这拦截好像也不能用了,也不知道这 JPA 能不能做到拦截
    canal 的话,可以操作 Oracle?可以的话,我又得好好研究这新东西了....哭
    rqxiao
        24
    rqxiao  
       Jun 20, 2019
    spingdatajpa 有个 PreUpdateEventListener
    rqxiao
        25
    rqxiao  
       Jun 20, 2019
    @rqxiao hibernate 和 springdatajpa 都可以用这个
    endershadow
        26
    endershadow  
       Jun 20, 2019
    @pengyOne oracle 的话 用 阿里 的 yugong , 数据库相关找阿里就完事了
    endershadow
        27
    endershadow  
       Jun 20, 2019
    迁移到 阿里云 rds 一劳永逸
    limuyan44
        28
    limuyan44  
       Jun 21, 2019
    重写 preparedStatement_execute,拿到 statement 还不是随便你怎么写 sql
    ricky077
        29
    ricky077  
       Jan 9, 2020
    请问最后是怎么解决这个问题的?
    pengyOne
        30
    pengyOne  
    OP
       Jan 9, 2020
    @ricky077 继承 FilterEventAdapter,然后重写 connection_prepareStatement,
    这个方法带三个参数,connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql)
    这个 sql 就是 druid 带来的原 sql,用正则表达式识别并修改这个方法的 sql
    ricky077
        31
    ricky077  
       Feb 7, 2020 via iPhone
    @pengyOne 你这还涉及 DDL 语句的操作么?我也是定时同步,但是每次同步前会检查两边 DDL 是否相同
    pengyOne
        32
    pengyOne  
    OP
       Feb 17, 2020
    @ricky077 emmmm,我没有让每次同步的时候都检查 ddl,不需要也太频繁
    只在添加新的表同步和修改表同步信息的时候会检查一遍,操作人修改表结构的是注意就好了。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1641 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 124ms · UTC 16:31 · PVG 00:31 · LAX 09:31 · JFK 12:31
    ♥ Do have faith in what you're doing.