数据迁移项目总结
将数据从sqlengine导入mysql,总结几个点:
=============== 1、效率上:
对于sqlengine,使用c++工具导出,每个表一个进程,每个分区一个线程并行读取。
对于mysql,采用 insert into table1(k1) values(v1),(v2),(v3)....这样的sql语句导入。根据每行的大小,和mysql每次导入数据包的最大限度: max_allowed_packet ,计算每个sql语句拼装的参数数量。本次导入采用账号数据每100条一次。token小数据每500条一次。 这样导入的好处: 1、减少mysql连接次数 2、减少mysql解析sql语句cpu消耗。
对于innoDB,每行数据做execute,每100次做一次commit的效率也不好。因为每行数据会占用一次网络IO
=============== 2、注意点:
本次导入总共40分钟,要做好:
a、导入进度的显示
b、采用后台任务导入,防止主机网络连接断开任务失败
c、做好导入pk的本地文件顺序化记录,这样中间失败后,可以很快速的再次重来
d、导入完成后,做好数据校验工作
e、将导入的数据,保存到另一个不可更改的数据库中,以作备案
f、导入时,对于来源数据,做全量读取,任意一行和一列数据,都必须找到对应的目标数据栏,否则打警告log。防止来源数据漏导。
============== 3、技术点
1、通过fork的形式,由主进程派生出子进程,然后wait子进程,直到所有子进程的任务完成,汇总统计时间、数量等信息。
sem_init(&sem, 0, 0);std::vector<ThreadWorker> workers(partCount);for(int i = 0; i < partCount; ++i) { ThreadWorker& worker = workers[i]; worker.threadID = i; worker.pkrange = ranges[i]; worker.operatorPtr = this; pthread_t pthread; pthread_create(&pthread, NULL, ThreadWorker::scanInThread,(void*)&worker); ## 线程内通过 sem_post(&sem); 发送完成信号} for(int i = 0; i < partCount; ++i) { sem_wait(&sem);}