• 【项目经验】数据迁移总结


    在产品迭代初期或者系统重构时期,业务模型的调整带来数据结构的变化,数据迁移不可避免。做好数据迁移需要考虑周全,且准备充分,做好预案,否则如果出现数据不一致问题,纠错成本高,同时核心业务数据的错误,会引起客户/业务方的投诉,团队也会承受巨大的压力。

    本文结合最近一个实际项目的数据数据迁移过程,讲述了踩过的坑,加上自己的一些思考得出的一些方法论,最后给出了数据迁移个脚本的一个实例

    目标

    确保新客户端访问新业务模型时能否正常查询之前的数据,如订单等;不会出现数据不一致。

    原则

    • 影响可控 —— 只对需要迁移对数据做修改,不能影响到其他数据;不到万不得已,不会允许停机迁移数据,因此迁移窗口期越短越好,减少迁移窗口期用户行为带来的数据问题;
    • 可回退 —— 一旦发现迁移数据有问题,可以回退到之前的数据状态;
    • 可追溯 —— 出现问题,能够有日志或者备份数据可查;数据库的binlog,迁移程序的log可以作为依据;
    • 可测试 —— 迁移方案必须可测试,要满足可测试,那么迁移方案必须是通用型的方案。

    思路

    • 先备份,再迁移;
    • 迁移后需要做数据比对,确保数据一致性;
    • 出现问题,考虑是否做回退【并不是所有场景都能直接回退】;
    • 如果业务量大,为避免用户行为和数据迁移产生冲突,考虑停服务迁移。

    步骤

    • 备份 —— 将待迁移数据备份到bak表,任何在迁移过程中会被修改的数据应当被备份,任何在insert场景被当着原数据使用的数据应当被备份;
    • 迁移 —— 迁移脚本 / 程序 只对bak表中的目标数据做操作;
    • 验证 —— 迁移完成后,需要做数据核对,确保数据一致性;
    • 回退 —— 回退脚本同样只对bak表中的目标数据做操作,且行为和迁移脚本行为相反。

    方案的选择

    数据库脚本

    在数据量小,业务场景简单的情况下非常适合,简单轻量级,通过sql脚本完成数据迁移非常合适。但如下几点需要认真思考:

    1. 能否写成通用sql?如果不能放弃;因为为不同环境准备不同的脚本,破坏了‘可测试’这一原则;
    2. 被操作的数据量是否太多?如果过多(通常超过1万条就很多了),可能导致脚本提交超时;
    3. 业务场景是否复杂?如果涉及到的表过多(超过3张),脚本的执行存在先后顺序,这时候通过人为保证,风险会大大增加;
    4. 测试环境和线上环境的sql执行工具/环境是否一致?如果不一致(很多公司的DBA工具会对一些语法和格式作出限制,比如不能有换行,注释中不能有半角分号等),则也会破坏掉‘可测试’这一原则;
    5. 线上sql执行流程是否冗长?如果流程冗长(公司的流程可能要求需要TL和DBA的审批,DBA作为第三方资源依赖不可控),且脚本多,会拉长数据迁移的窗口期,业务风险大大增加,破坏了‘影响可控’的原则。

    迁移程序

    和‘数据库脚本’方法相反,撰写的‘迁移程序’能够避开这些缺点,更适合于业务场景复杂,数据量大的场景。

    方案对比

    脚本

    程序

    备注

    通用性

    不完全

    完全

    如:依赖第三方数据时,脚本无法做到通用

    复杂场景支持

    不适合

    适合

    复杂业务场景脚本不适合,如循环调用,第三方系统数据,多表依赖等

    大数据量支持

    不适合

    适合

    大数据量可能导致脚本提交超时,通常超过1万条不宜使用脚本,大多数dba工具通常也会对操作的数据量做限制

    开发成本随复杂度增长

    指数

    线性

     

    无论采用‘数据库脚本’还是‘迁移程序’,都需要遵循上面的‘原则’和步骤。

    思考

    数据迁移和应用程序发布的先后顺序?

    在业务量大的情况下,数据迁移过程中,数据被用户行为修改了怎么办?

    迁移失败,什么情况下做回退,什么情况下不能做回退?

    踩过的坑

    在转赠2.0项目中,前期对数据迁移的业务复杂度预估不足,选择了‘数据库脚本’方式,踩了不少坑:

    1. 在测试环境测试通过的sql脚本,无法直接在线上环境执行,原因是线上数据库工具对sql格式和内容校验更为严格(不允许有换行等);
    2. 测试过程中发现,需要实现为一个订单循环生成多个券码的场景,虽通过sql间接实现,但是复杂度很高,开发成本增大;
    3. 由于sql较多且复杂度高(如:使用insert select),需要经过TL和DBA的双重审批,拉长了数据迁移窗口。

    迁移脚本示例

    业务场景:将订单表中订单状态为2和3的订单状态更新为4

    backup

    create table order_bak like order;
    insert into order_bak select * from order where status in (2,3);
    注:order为业务表,order_bak为备份表;目标是将订单状态为3的订单更新为4。

    migration

    update order set status = 4 where id in (select id from order_bak);

    注:如果直接对order原表进行操作,一旦错误,无法回滚。

    check

    select count(*) as cont from order where status != 4 and id in (select id from order_bak);

    注:如果cont > 1则需要考虑数据迁移是否成功

    rollbak

    update order o inner join order_bak bak on o.id = bak.id set o.status = bak.status;

    注:如果迁移后-->回滚前,有用户行为更改status状态,则不能直接rollback ,需要具体情况具体分析;实在避免不了,且此类数据很多,则考虑停服务迁移了。

  • 相关阅读:
    常用的STL
    CString,string,char数组的转换
    linux知识
    十一种通用滤波算法(转)
    修复被勒索病毒cl0p损坏的svn代码
    android shell 转发代理shell示例
    3proxy配置
    windbg调试写dmp,随机名字
    nexus6p刷机注意
    mysql语句学习
  • 原文地址:https://www.cnblogs.com/daoqidelv/p/9594910.html
Copyright © 2020-2023  润新知