• 删库跑路系列-------清理线上订单数据


    一。问题由来

    历史订单详情表order_detail 出现大量脏数据,大约10kw行,

    存在数据原因在于,order_detail表的主键order_detail_id用的是UUID【此处不是原始的业务问题哈,是仿效说明问题,而已了(UUID是通过java程序生成,不是数据同步等)】

    ,再重复导入数据时会保证数据不重复,这就造成在查数据大量重复: 

    order_price<sum(price)

    需要对订单详情表数据进行处理,并且在订单详情表增加付款人ID字段,修改订单详情表的order_detail_id

    订单表:order

     原始订单表:order_detail

    需要更新的:order_detail

    二、解决方案

    1、因为订单详情表的数据量很大,所以需要将数据提取一部分处理,进行更新:10w条一次

    方法一:使用with语句

    with test as
    (
    select v1.*,o.user_id
    from 
    (
    select order_detail_id,
    order_id,
    product_num,
    unit,
    price,
    create_time
    from order_detail
    where user_id is null 
    limit 100000
    )v1
    inner join order o
    on(v1.order_id=o.order_id)
    )
    --update语句就不写了,根据自己数据库需要写吧
    update order_detail set user_id = '' 
    where order_detail_id in (select order_detail_id from test
    );

    因为我们用是阿里的ADB For Mysql 3.0(2021年1月8号,要严谨一些的,阿里数据开发人员告诉做,update 用不了inner 语法),不支持这种写法,只能逼着本人,用另一种方案解决了。

    哎:

    方法二:拆分sql进行执行

    步骤一:
    truncate
    table order_detail3; 步骤: INSERT INTO order_detail3 select v1.*,o.user_id from ( select order_detail_id, order_id, product_num, unit, price, create_time from order_detail where user_id is null limit 100000 )v1 inner join order o on(v1.order_id=o.order_id) ; 步骤三: DELETE FROM order_detail WHERE order_detail_id in (select order_detail_id from order_detail3 ); 步骤四: INSERT INTO order_detail select MD5(concat(order_id,product_num,unit,price,user_id,create_time)) as order_detail_id, order_id, product_num, unit, price, create_time, user_id from order_detail3 ;

    上面sql语句初看是不是没有问题那?

    上面sql语句初看是不是没有问题那?

    上面sql语句初看是不是没有问题那?

    上面sql语句初看是不是没有问题那?

    上面sql语句初看是不是没有问题那?

    上面sql语句初看是不是没有问题那?

    上面sql语句初看是不是没有问题那?

    上面sql语句初看是不是没有问题那?

    上面sql语句初看是不是没有问题那?

    上面sql语句初看是不是没有问题那?

    上面sql语句初看是不是没有问题那?

    上面sql语句初看是不是没有问题那?

    单单从sql的层面来说,其实上面的sql语句是有大问题的,而且有大问题:不服看代码

    步骤一:
    truncate table order_detail3;
    步骤二:
    INSERT INTO order_detail3
    select v1.*,o.user_id
    from 
    (
    select order_detail_id,
    order_id,
    product_num,
    unit,
    price,
    create_time
    from order_detail
    where user_id is null
    )v1
    inner join order o
    on(v1.order_id=o.order_id)
    limit 100000 ;
    步骤四: INSERT INTO order_detail select MD5(concat(order_id,product_num,unit,price,user_id,create_time)) as order_detail_id, order_id, product_num, unit, price, create_time, user_id from order_detail3 ;
    步骤三:
    DELETE FROM order_detail WHERE order_detail_id in (select order_detail_id from order_detail3 );

    上面代码改了两处,

    其一:是limit100000 的位置,

    其二是,步骤三和步骤四的位置

    其一原因是,当表order_detail 表中存在order_id 为空的数据的时候是好导致整个SQL,无法做到清理数据的目的,所以要将limit 10000放在外面

    其二原因是,程序是循环执行的,10分钟一次,程序的稳定性,加入数据在指向完步骤三之后突然程序死掉了(链接时长啊,等等莫名其妙的问题),后续数据没有插入进去,10分钟之后,执行步骤一,是不是要删库跑路了啊

    三、执行过程

    执行过程,一定要有监测功能,如果用python,或者shell脚本调用程序,10分钟一次,

     这是还要建一个自依赖,保证任务在执行完之后,才执行下一个任务,如果:如果一个任务没有跑完,另一个任务开始truncate 了,这就又是要删库跑路了啊,

     上图是建立自依赖关系(线上数据库吃性能啊,频繁的读写,会导致SQL执行时间过长)。

    其实上面的,sql执行语句还有优化的空间,

    你还有什么更好的解决方案啊,欢迎交流,

  • 相关阅读:
    codeforces 690C3 C3. Brain Network (hard)(lca)
    codeforces 690C2 C2. Brain Network (medium)(bfs+树的直径)
    codeforces 690C1 C1. Brain Network (easy)(水题)
    codeforces 459E E. Pashmak and Graph(dp+sort)
    bzoj-1296[SCOI2009]粉刷匠(dp)
    codeforces 689E E. Mike and Geometry Problem(组合数学)
    Useful Field of View (UFOV)
    mongodb基础
    node.excel
    犀牛-6对象
  • 原文地址:https://www.cnblogs.com/xiaonantianmen/p/14253034.html
Copyright © 2020-2023  润新知