Mysql百万级数据迁移实战笔记

背景

上个月跟朋友一块儿作了个微信小程序,趁着5.20节日的热度,两个礼拜内迅速积累了一百多万用户,咱们在小程序页面增长了收集formid的埋点,用于给微信用户发送模板消息通知。mysql

这个小程序一开始的后端逻辑是用douchat框架写的,使用框架自带的dc_mp_fans表存储微信端受权登陆的用户信息,使用dc_mp_tempmsg表存储formid。截止到目前,收集到的数据超过380万,很大一部分formid都已经成功使用给用户发送过模板通知,起到了较好的二次推广的效果。redis

随着数据量的增大,以前使用的服务器空间开始有点不够用,最近新写了一个专门用于作小程序后台开发的框架,因而想把原来的数据迁移到新系统的数据库。买了一台4核8G的机器,开始作数据迁移。下面对迁移过程作一个简单的记录。 sql

方案选择

  • mysqldump迁移

日常开发中,咱们比较常常使用的数据备份迁移方式是用mysqldump工具导出一个sql文件,再在新数据库中导入sql来完成数据迁移。试验发现,经过mysqldump导出百万级量的数据库成一个sql文件,大概耗时几分钟,导出的sql文件大小在1G左右,而后再把这个1G的sql文件经过scp命令复制到另外一台服务器,大概也须要耗时几分钟。在新服务器的数据库中经过source命令来导入数据,我跑了一夜都没有把数据导入进来,cpu跑满。shell

  • 脚本迁移

直接经过命令行操做数据库进行数据的导出和导入是比较便捷的方式,可是数据量较大的状况下每每会比较耗时,对服务器性能要求也比较高。若是对数据迁移时间要求不是很高,能够尝试写脚原本迁移数据。虽然没有实际尝试,可是我想过大概有两种脚本方案。数据库

第一种方式,在迁移目标服务器跑一个迁移脚本,远程链接源数据服务器的数据库,经过设置查询条件,分块读取源数据,并在读取完以后写入目标数据库。这种迁移方式效率可能会比较低,数据导出和导入至关因而一个同步的过程,须要等到读取完了才能写入。若是查询条件设计得合理,也能够经过多线程的方式启动多个迁移脚本,达到并行迁移的效果。小程序

第二种方式,能够结合redis搭建一个“生产+消费”的迁移方案。源数据服务器能够做为数据生产者,在源数据服务器上跑一个多线程脚本,并行读取数据库里面的数据,并把数据写入到redis队列。目标服务器做为一个消费者,在目标服务器上也跑一个多线程脚本,远程链接redis,并行读取redis队列里面的数据,并把读取到的数据写入到目标数据库。这种方式相对于第一种方式,是一种异步方案,数据导入和数据导出能够同时进行,经过redis作数据的中转站,效率会有较大的提高。vim

可使用go语言来写迁移脚本,利用其原生的并发特性,能够达到并行迁移数据的目的,提高迁移效率。后端

  • 文件迁移

第一种迁移方案效率过低,第二种迁移方案编码代价较高,经过对比和在网上找的资料分析,我最终选择了经过mysql的select data into outfile file.txtload data infile file.txt into table的命令,以导入导出文件的形式完成了百万级数据的迁移。微信小程序

迁移过程

  1. 在源数据库中导出数据文件
select * from dc_mp_fans into outfile '/data/fans.txt';
复制代码
  1. 复制数据文件到目标服务器
zip fans.zip /data/fans.txt
scp fans.zip root@ip:/data/ 
复制代码
  1. 在目标数据库导入文件
unzip /data/fans.zip
复制代码
load data infile '/data/fans.txt' into table wxa_fans(id,appid,openid,unionid,@dummy,created_at,@dummy,nickname,gender,avatar_url,@dummy,@dummy,@dummy,@dummy,language,country,province,city,@dummy,@dummy,@dummy,@dummy,@dummy,@dummy,@dummy,@dummy,@dummy);
复制代码

按照这么几个步骤操做,几分钟内就完成了一个百万级数据表的跨服务器迁移工做。安全

注意项

mysql安全项设置

在mysql执行load data infileinto outfile命令都须要在mysql开启了secure_file_priv选项, 能够经过show global variables like '%secure%';查看mysql是否开启了此选项,默认值Null标识不容许执行导入导出命令。经过vim /etc/my.cnf修改mysql配置项,将secure_file_priv的值设置为空:

[mysqld]
  secure_file_priv=''
复制代码

则可经过命令导入导出数据文件。

导入导出的数据表字段不对应

上面示例的从源数据库的dc_mp_fans表迁移数据到目标数据库的wxa_fans表,两个数据表的字段分别为:

  • dc_mp_fans

  • wxa_fans

在导入数据的时候,能够经过设置字段名来匹配目标字段的数据,能够经过@dummy丢弃掉不须要的目标字段数据。

总结

结合本次数据迁移经历,总结起来就是:

  • 小数据量可使用mysqldump命令进行导入导出,这种方式简单便捷。
  • 数据量较大,且有足够的迁移耐心时,能够选择本身写脚本,选择合适的并行方案迁移数据,这种方式编码成本较高。
  • 数据量较大,且但愿能在短期内完成数据迁移时,能够经过mysql导入导出文件的方式来迁移,这种方式效率较高。

在新系统展现数据的效果:

下一篇将写一写前段时间经过脚本20分钟内给18万微信小程序粉丝群发模板通知的经历。敬请期待。

转载请注明原文连接:idoubi.cc

相关文章
相关标签/搜索