Mysql服务不停止迁移分表数据

一、问题产生原因

1. 随着业务数据的增长,原有的表,单表数据量增加过快。
2. 数据增长超出初期预测数据量,且初期没考虑分表
3. 生产环境业务在持续运行,需要热切到分表

二、解决方案

1.借助mysql触发器的特性,在逻辑表(即原表)上建立触发器,当表内数据触发插入后,同时插入到物理分表中。
备注:如果逻辑表还有删除(更新)操作,保证数据准确性,可再配合更新触发器
2.将触发器生效后,之前逻辑表中数据迁移到分表中,可以借助市面上etl工具,或者线下通过程序导入。
3.修改项目分表相关规则,目前使用的是基于jdbc层的shadingsphere,所以配置分表规则即可。上线程序。
4.待上线后,数据不再落到逻辑表中后,即可删除逻辑表触发器。

流程图如下:

 

 

 

 

 三、实战

接下来,进入实施流程:

1. 准备分表

可以参考之前的随笔存储过程实现。

传送门:复制表存储过程

2. 建立触发器

CREATE TRIGGER `trg_paper_question_insert` AFTER INSERT ON `qs_qd_paper_question` FOR EACH ROW begin
    set @shard := mod(new.paper_id, 2);
    case @shard
    when 0 then insert into qs_qd_paper_question0 (`paper_question_id`, `paper_part_id`, `paper_id`, `question_id`, `parent_id`, `question_score`, `sequence`, `is_valid`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) values (new.paper_question_id, new.paper_part_id, new.paper_id, new.question_id, new.parent_id, new.question_score, new.sequence, new.is_valid, new.create_by, new.create_time, new.update_by, new.update_time, new.remark);
    when 1 then insert into qs_qd_paper_question1 (`paper_question_id`, `paper_part_id`, `paper_id`, `question_id`, `parent_id`, `question_score`, `sequence`, `is_valid`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`) values (new.paper_question_id, new.paper_part_id, new.paper_id, new.question_id, new.parent_id, new.question_score, new.sequence, new.is_valid, new.create_by, new.create_time, new.update_by, new.update_time, new.remark);
END CASE;
end;

补充说明:

mysql触发器new old:"NEW . column_name"或者"OLD . column_name".在技术上处理(NEW | OLD . column_name)新和旧的列名属于创建了过渡变量("transition variables")。

对于INSERT语句,只有NEW是合法的;

对于DELETE语句,只有OLD才合法;

而UPDATE语句可以在和NEW以及OLD同时使用。

3. (非主流程)更新触发器

如果有更新需求,可以再配合更新触发器

CREATE TRIGGER `trg_paper_question_update` AFTER UPDATE ON `qs_qd_paper_question` FOR EACH ROW begin
    select paper_part_id, paper_id, question_id, parent_id, question_score, sequence, is_valid, create_by, create_time, update_by, update_time, remark into @paperPartId, @paperId, @questionId, @parentId, @questionScore, @Sequence, @isValid, @createBy, @createTime, @updateBy, @updateTime, @remark from qs_qd_paper_question where paper_question_id = old.paper_question_id;
    set @shard := mod(@paperId, 32);
    case @shard
    when 0 then update qs_qd_paper_question0 set paper_part_id = @paperPartId, paper_id = @paperId, question_id = @questionId, parent_id = @parentId, question_score = @questionScore, sequence = @Sequence, is_valid = @isValid, create_by = @createBy, create_time = @createTime, update_by = @updateBy, update_time = @updateTime, remark = @remark where paper_question_id = old.paper_question_id;
    when 1 then update qs_qd_paper_question1 set paper_part_id = @paperPartId, paper_id = @paperId, question_id = @questionId, parent_id = @parentId, question_score = @questionScore, sequence = @Sequence, is_valid = @isValid, create_by = @createBy, create_time = @createTime, update_by = @updateBy, update_time = @updateTime, remark = @remark where paper_question_id = old.paper_question_id;
END CASE;
end;

4. 迁移历史数据 

将触发器生效后,之前逻辑表中数据迁移到分表中,可以借助市面上etl工具,或者线下通过程序导入(此流程开发着可自行安排)

5.上线集成分表后的程序

修改项目分表相关规则,目前使用的是基于jdbc层的shadingsphere,所以配置分表规则即可。上线程序

 

 


 

以上适用于场景:

1. 热切分库分表

2. 不锁表增加、修改表字段

 

后续在博客发现pt-osc与自己的思路类似,后续可以了解一下,毕竟对于不经常写触发器的开发来说,自己实现,较为复杂,易出错。

posted @ 2021-03-04 13:16  不喝北冰洋  阅读(673)  评论(0编辑  收藏  举报