V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
pengyOne
V2EX  ›  程序员

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

  •  
  •   pengyOne · 2019-06-20 11:26:13 +08:00 · 3783 次点击
    这是一个创建于 2018 天前的主题,其中的信息可能已经有所发展或是发生改变。

    项目要求是这样的:

    数据库中有几十个表,现在我要给其中大约一半的表增加两个字段,一个最后修改时间 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 方案也好啊...我快被逼疯了
    
    第 1 条附言  ·  2019-06-20 13:05:58 +08:00
    公司不让用触发器是因为担心出现问题.......这个项目要求是能承受 2w 个并发,不知道这种需求,用触发器会有问题吗?
    32 条回复    2020-02-17 10:34:16 +08:00
    Cooky
        1
    Cooky  
       2019-06-20 11:33:42 +08:00 via Android
    不能改代码,不能用触发器,那还同步个鸡巴?
    难不成一直扫描数据库?
    zhangalong69
        2
    zhangalong69  
       2019-06-20 11:39:08 +08:00
    把这些表先都找找出来,用 python 脚本执行添加属性的操作,然后对单个表用小工具代码添加字段,比如打个 java 工程直接在生产环境添加,一张表一次取 1000 个数据,单线程多线程都可以
    pengyOne
        3
    pengyOne  
    OP
       2019-06-20 11:42:23 +08:00
    @Cooky 同步数据是每天定时同步.....最主要的就是原数据库那块同步状态的修改问题,因为可能对已有数据进行修改,然后就要改变它的状态从 1 变 0.....
    新增数据,我就直接给时间和状态设置默认值了,但修改数据的时候这两个字段的修改真的是......不会
    我也觉得很烦躁,这边还给我个思路说,中途拦截 sql 然后修改 sql 再继续执行.....而这我也不会啊,druid 有这种操作吗?
    securityCoding
        4
    securityCoding  
       2019-06-20 11:49:45 +08:00
    订阅 binlog?
    pengyOne
        5
    pengyOne  
    OP
       2019-06-20 11:56:41 +08:00
    @zhangalong69 emmmmm 字段添加很快就完成了.....我的疑惑是怎么更新的问题
    lazyfighter
        6
    lazyfighter  
       2019-06-20 12:02:52 +08:00
    LAST_CHANGE_TIME 可以在字段表达式完成 同步状态感觉没啥用,完全可以根据时间进行同步
    rockyou12
        7
    rockyou12  
       2019-06-20 12:12:21 +08:00
    看你有 aop 应该是 java+spring boot,可以在 dao 层的 insert、save 这些方法入手做 aop,直接把对象拿出来,反射获取字段 LAST_CHANGE_TIME 和 SYNC_STATUS 然后修改字段的值
    xxxy
        8
    xxxy  
       2019-06-20 12:14:39 +08:00 via Android
    在原代码和数据库间加一层代理?
    pengyOne
        9
    pengyOne  
    OP
       2019-06-20 12:34:53 +08:00
    @rockyou12 这应该不行,因为源代码那边的对象是没有我新增的这些字段的....而且这项目有些用 xml,有些直接用 @
    query,好像还有 hibernate????
    pengyOne
        10
    pengyOne  
    OP
       2019-06-20 12:46:45 +08:00
    @lazyfighter 判定时间确实可以耶,不过领导说要状态就用状态了吧........字段表达式是啥?可以做到在进行跟新操作后对该条数据修改吗?
    tomczhen
        11
    tomczhen  
       2019-06-20 13:37:19 +08:00
    这不就是 CDC 么。
    hand515
        12
    hand515  
       2019-06-20 13:38:17 +08:00
    用 canal 订阅 binlog 应该可以解决
    endershadow
        13
    endershadow  
       2019-06-20 13:39:32 +08:00
    canal 完美解决你的问题
    lazyfighter
        14
    lazyfighter  
       2019-06-20 13:49:19 +08:00
    @pengyOne `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    lazyfighter
        15
    lazyfighter  
       2019-06-20 13:51:55 +08:00
    刚刚百度了一下 mybatis 可以写拦截器修改 sql,那你的标志位也就解决了
    rqxiao
        16
    rqxiao  
       2019-06-20 13:54:29 +08:00
    hibenate 有个 listener ?
    x66
        17
    x66  
       2019-06-20 13:59:45 +08:00
    数据库 update time 字段设置成 update 的时候自动更新不就行了吗?然后根据 update time 捕捉变化数据
    EasyProgramming
        18
    EasyProgramming  
       2019-06-20 14:05:29 +08:00
    emmm,看需求描述,好像不是数据迁移呀?
    LuVx
        19
    LuVx  
       2019-06-20 14:30:25 +08:00
    如果不使用的 mysql 呢, ON UPDATE CURRENT_TIMESTAMP 也就没效果了, 最有效的感觉还是 lazyfighter 提出的拦截改写 sql, 或者用 canal(实时性要求不高的话)
    pengyOne
        20
    pengyOne  
    OP
       2019-06-20 14:58:33 +08:00
    @hand515
    @endershadow 我这用的是 oracle 能用这 canal 吗?我看百度好像说这是操作 mysql 的,而且也没什么示范的实例
    pengyOne
        21
    pengyOne  
    OP
       2019-06-20 15:04:47 +08:00
    @EasyProgramming 应该说是数据同步才是.....现在这个就是同步之前的状态更改问题,每天定时同布
    LuVx
        22
    LuVx  
       2019-06-20 15:05:00 +08:00
    @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
       2019-06-20 15:12:03 +08:00
    @lazyfighter
    @LuVx 是的,我这用的是 Oracle......而且这用的是 Spring Data JPA,这好像是基于 hibernate 的吧?这拦截好像也不能用了,也不知道这 JPA 能不能做到拦截
    canal 的话,可以操作 Oracle?可以的话,我又得好好研究这新东西了....哭
    rqxiao
        24
    rqxiao  
       2019-06-20 15:45:01 +08:00
    spingdatajpa 有个 PreUpdateEventListener
    rqxiao
        25
    rqxiao  
       2019-06-20 15:46:13 +08:00
    @rqxiao hibernate 和 springdatajpa 都可以用这个
    endershadow
        26
    endershadow  
       2019-06-20 15:51:46 +08:00
    @pengyOne oracle 的话 用 阿里 的 yugong , 数据库相关找阿里就完事了
    endershadow
        27
    endershadow  
       2019-06-20 15:52:47 +08:00
    迁移到 阿里云 rds 一劳永逸
    limuyan44
        28
    limuyan44  
       2019-06-21 01:20:16 +08:00
    重写 preparedStatement_execute,拿到 statement 还不是随便你怎么写 sql
    ricky077
        29
    ricky077  
       2020-01-09 00:09:16 +08:00
    请问最后是怎么解决这个问题的?
    pengyOne
        30
    pengyOne  
    OP
       2020-01-09 09:07:11 +08:00
    @ricky077 继承 FilterEventAdapter,然后重写 connection_prepareStatement,
    这个方法带三个参数,connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql)
    这个 sql 就是 druid 带来的原 sql,用正则表达式识别并修改这个方法的 sql
    ricky077
        31
    ricky077  
       2020-02-07 14:25:10 +08:00 via iPhone
    @pengyOne 你这还涉及 DDL 语句的操作么?我也是定时同步,但是每次同步前会检查两边 DDL 是否相同
    pengyOne
        32
    pengyOne  
    OP
       2020-02-17 10:34:16 +08:00
    @ricky077 emmmm,我没有让每次同步的时候都检查 ddl,不需要也太频繁
    只在添加新的表同步和修改表同步信息的时候会检查一遍,操作人修改表结构的是注意就好了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2723 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 05:54 · PVG 13:54 · LAX 21:54 · JFK 00:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.