记一次数据迁移

Posted 程序员大咖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次数据迁移相关的知识,希望对你有一定的参考价值。

👇👇关注后回复 “进群” ,拉你进程序员交流群👇👇

作者丨小羊快码

来源丨小羊快码(ID:xyquickcode)

大家好,我是小羊~

最近由于业务规划,小羊需要将老数据库中的数据,迁移到新数据库,数据大概有3000万条。

小羊虽然懂一些后台技术,但是数据迁移这块,还真没独立负责过。过程中踩了一些坑,也获得了一些经验,下面就分享给大家。

为什么用 mysqldump

迁移数据有几种方式,可选的如下:

1. 数据库控制台页面导入导出

这种产品级的能力肯定要优先选择,我一开始也兴冲冲以为此路可通,结果发现导出数据只支持百万以内,导入更是只支持10m 。对于线上动则千万级的数据库来说,这功能就跟没有一样,告辞。

2. 使用主从同步的方式导入

相当于是通过 binlog 的记录,来同步数据。我们的数据库是在云上,主从同步只要配置一下就可以使用。但是我们的新旧数据库,在不同 VPC 下,这就意味着没法互连,这条路也行不通。而直接下载 binlog 呢?也不是不行,但是通过 binlog 记录同步,而没有了云上自动同步的优势,吸引力不大。

3. mysqldump 直接同步表数据

这种方案作为迁移还是很好用的,毕竟是针对数据的同步。不像 binlog  是针对记录,效率肯定会高些。

基于以上分析,我最终决定用 mysqldump 来做数据迁移。下面就来看看具体是怎么做的吧。

mysqldump 命令准备

首先,我们来看看涉及到 mysqldump 的命令

导出:

mysqldump  -u$用户名  -h$ip  -p$密码 -P$端口号  -c $数据库

--tables $表名1 $表名2  > dump.sql

使用:

mysqldump  -uroot -h127.0.0.1 -pxiaoyang -P3306  -c test --tables user score > dump.sql

这句话的意思,是说将127.0.0.1:3306上 test 库中的 user 表和score 表导出

导入:

通过命令行登上新数据库,source dump.sql 即可导入。

这样看起来就万事俱备了,Let's Go!

踩坑之旅

我开始执行导出导入命令,以为会一帆风顺,结果导入时候遇到了如下报错:

ERROR 3546 (HY000): @@GLOBAL.GTID_PURGED cannot be changed: the added gtid set must not overlap with @@GLOBAL.GTID_EXECUTED

这个报错看起来和 GTID 信息有关,于是我去查了下资料,发现 MySQL 可基于 GTID 做主从复制,导出时会携带数据库中的 GTID 信息。而带有 GTID 信息的 dump 文件,要求目标数据库实例必须开启 GTID 功能,不然就会报如上错误。

由于新集群此时还未开启主从同步,在不改变集群配置的时候,我们的mysqldump命令需要加上这个导出参数:--set-gtid-purged=OFF,即导出时去掉GTID信息。

如此就顺利解决掉了 GTID 的问题。

继续往下进行,我又遇到了新问题:

由于数据表字段比较多,mysqldump 组成的批量插入语句相对比较复杂。而我们用的是云服务,导致代理直接报错。并提示语句过于复杂,摆在面前的有两个选择:

1. 联系云厂商进行排查。但推动这个事情,起码得1-2天,并且云厂商也不见得会优先排期支持。

2. 既然是 mysqldump 进行了语句整合,那有没有让这些语句不合并的参数呢,还真有!–skip-opt 可以关掉合并功能。

我们通过方式2,解决了整合问题,这样就变成一条一条插入。关掉之后,满心期待,以为后面就是一马平川了,结果没跑几分钟进程 killed 了。

google 查了一下,原因是转换成单条 insert 之后,mysqldump 占据了更多的内存,由于系统内存不足,系统选择性的将耗用内存大的几个进程 kill 掉了,于是 mysqldump 被顺理成章的 kill 掉了。

不过好在 mysqldump 还提供了-q 参数,来优化性能。加入了这个参数之后,程序可以正常的跑起来了。几千万数据,在我们 16H32G 的 MYSQL 机器上,大概跑了有30个小时。

复盘优化

虽然最终顺利完成了任务,但是几千万数据,跑了30个小时,确实有点久。主要原因是因为我们语句都是逐条插入的,这样同步进行,没能吃满 MYSQL 机器性能,可以说比批量慢了一个量级。

下来之后小羊也在想,怎么提升呢?很简单,瓶颈在于请求顺序进行需要耗费时间。那我们可以将 mysqldump 导出的文件,分成多份,并发进行。简单测试过后,得出结论:分成100份对 MYSQL 性能降低得也有限,那原来的30h,可以变成0.3h了哦,感兴趣的小伙伴也可以测试一下极限是多少,这其实是 MYSQL 插入并发度的问题。

好了,在后台开发中,数据迁移其实不是高频操作,大家的实践经验也不多。希望大家通过此文,能有所收获,下次做迁移就可以跳过这些坑啦。

-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!

点击👆卡片,关注后回复【面试题】即可获取

在看点这里好文分享给更多人↓↓

以上是关于记一次数据迁移的主要内容,如果未能解决你的问题,请参考以下文章

SQLServer记一次数据迁移-标识重复的简单处理

初码-Azure系列-记一次MySQL数据库向Azure的迁移

记一次wordpress网站迁移的经历

记一次从oracle到hive的历史数据迁移

记一次Mysql 数据库迁移后报错问题

记一次RAID阵列的迁移经历