版权声明:本文由王亮原创文章,转载请注明出处: 
文章原文链接:https://www.qcloud.com/community/article/122

来源:腾云阁 https://www.qcloud.com/community

王亮,腾讯云高级工程师。2010年加入腾讯,曾负责腾讯社交产品CDN图片类业务,动态加速业务的运维工作。现负责数据库产品的解决方案工作。

某国内大型游戏开发商有超过130个IDC部署MySQL实例,存储总量达20T。因业务需要,将全部实例迁移到腾讯云CDB for MySQL。腾讯云数据库团队为保证业务迁移顺利进行,对迁移流程,工具进行了前期的调查研究,并对过程中发现的4大问题进行及时解决,以下是实际迁移经验分享:

一. 测试用例/过程

目前开发商上云(外部MySQL迁移到CDB)提供多种方案,其中开发商的MySQL实例有外网IP的可以直接使用腾讯云数据库迁移工具完成迁移(其他的迁移方法参见链接本次迁移任务中该开发商的所有MySQL实例均有外网代理IP供使用,故直接选用迁移工具完成数据导入。

迁移工具的基本原理:通过待迁移实例提供的高权限帐号获取源实例基本的MySQL实例配置,并同步到目标CDB实例;通过mysqldump直接将源实例导出传输到CDB实例后导入;源数据库实例和目标CDB建立主从关系同步新数据。其中CDB实例与源IDC之间通过NAT方式以一台带外网的服务器为中转发起通信。

1. 迁移工具基本功能

腾讯云数据库控制台页面根据引导建立迁移任务;在后台管理页面观察迁移任务后台日志等。

任务开始运行后检测代理机器流量变化,CDB的写入等数据展示



知识点:如何为测试数据库产生较大的数据量。这里推荐一个工具mysql_gen_data。产生测试数据并导入到MySQL的过程如下:

#!/bin/bash
./mysql_gen_data -f "%1n,%100s,%100s,%100s,%100s,%100s" \
-n 10000000 >random.dat
mysql –uroot –p*********** –e “create database cdbtest;use cdbtest; \
CREATE TABLE cdbtest_tb \
(c1 varchar(100),c2 varchar(100),c3 varchar(100), \
c4 varchar(100),c5 varchar(100),c6 varchar(100)) \
ENGINE=InnoDB DEFAULT CHARSET=utf8;”
for i in {1..10}; do
echo "$(date '+%T') round $i start"
echo "prepare data..."
sed -i "s/^/$i/" random.dat
echo "insert data..."
mysql -uroot –p******** cdbtest -e "LOAD DATA local INFILE '/data/random.dat' into table cdbtest_tb fields terminated by',';"
echo "$(date '+%T') round $i end"
done


后台与腾讯云管理台查看本次测试任务,迁移成功完成。

2. 主从以及从机和CDB建立主从的同步

由于本次迁移的开发商将使用他们自建IDC的从机向CDB迁移数据,简单关系如下图,之前没有使用迁移工具进行过类似操作,故进行本次测试。

知识点:如何配置MySQL的主从关系。测试的MySQL主从的配置如下:(主MySQL)

server_id = 98
log_bin = binlog
binlog_format = ROW
innodb_stats_on_metadata = off




后台与腾讯云管理台查看本次测试任务,迁移成功完成。

3. 多实例+较大binlog并发同步

开发商在经过相关测试后,一期计划15个实例并发迁移到CDB,每天总共产生约100G的binlog。由于之前迁移工具没有大并发使用,且单日有较大数据更新,故提前测试用户场景。测试的基本架构如下图:在一个服务器上开启15个MySQL实例映射到不同端口,15个MySQL实例同时和15个CDB实例建立主从,并发起迁移任务。

知识点:如何在一台服务器上创建多个MySQL实例?这里使用的MySQL自带的mysqld_multi工具,其实这只是一个perl脚本,开启多实例配置如下(/etc/my.conf)可以视内存大小,开多个mysqld的配置项:

[mysqld_multi]
mysqld = /usr/bin/mysqld_safe
mysqladmin = /usr/bin/mysqladmin
user = root
password = ****** [mysqld1]
port = 3306
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
pid-file=/var/lib/mysqld.pid
server_id = 11
log_bin = binlog
binlog_format = ROW
expire_logs_days=1
innodb_stats_on_metadata = off symbolic-links=0
user = root
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES [mysqld2]
port = 3312
datadir=/data/mysql12
socket=/data/mysql12/mysql.sock
pid-file=/data/mysql12/mysqld.pid
server_id = 12
log_bin = binlog
binlog_format = ROW
expire_logs_days=1
innodb_stats_on_metadata = off
user = root
symbolic-links=0 sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES [mysqld3]
........
[mysqld4]
.......

然后使用mysqld_multi start 1-4启动配置项里面的对应数量实例即可。启动多个MySQL实例如图:

通过定时update对应数据库实例的数据,产生较大量的binlog,单次update产生700Mbinlog,每2小时执行一次,每天产生7001215=126G.简单代码如下:

#!/bin/sh

SET_STRING=`date +"%s"`
LOG_NAME="/data/log/update.log"
NOW_STRING=`date +"[%Y-%m-%d %H:%M:%S]"` for i in {12..26} do
BEGIN_TIME=`date +"[%Y-%m-%d %H:%M:%S]"`
echo ${BEGIN_TIME}" Update data in this time is:"$SET_STRING >> $LOG_NAME
echo ${BEGIN_TIME}" Update database"${i} "start..." >> $LOG_NAME
mysql -uroot migrate${i} -S /data/mysql${i}/mysql.sock -e "update tb set data1="${SET_STRING}""
END_TIME=`date +"[%Y-%m-%d %H:%M:%S]"`
echo ${END_TIME}" Update database"${i} "end..." >> $LOG_NAME
done

使用数据库迁移工具建立15个迁移任务,控制台和后台检查均迁移成功:

同时为了检验大量binlog情况下数据完整性,写了简单脚本定时检查数据是否有更新,脚本如下:(这里经过测试发现可以通过广州跳板机直接连接CDB实例的masterIP,故直接在广州跳板机脚本拉取IDC更新数据,同时对比CDB实例数据,写入日志)

#!/bin/sh

DATA_CORRECT=$1
NOW_TIME=`date +"[%Y-%m-%d %H:%M:%S]"`
cat my.file | while read line
do IP=`echo $line | awk -F " " '{print $1}'`
PORT=`echo $line | awk -F " " '{print $2}'`
DATABASE=`echo $line | awk -F " " '{print $3}'`
DATA_INBASE=`mysql -uroot -P${PORT} -h${IP} -p123456cdb ${DATABASE} -e "select data1 from tb limit 1\G" | grep data1 | awk -F " " '{print $2}'` echo ${NOW_TIME}"[INFO]Data you want to update to ${DATABASE} is:"$DATA_CORRECT
echo ${NOW_TIME}"[INFO]Data from Database "$DATABASE" is:"$DATA_INBASE if [ $DATA_INBASE -eq $DATA_CORRECT ]
then
echo ${NOW_TIME}"[SUCCESS]"$DATABASE" update succesfully!"
else
echo ${NOW_TIME}"[ERROR]"$DATABASE" update ERROR!"
fi done

通过校验日志可以看到,数据更新均成功完成。

二. 开发商迁移测试数据记录

以上我方内部测试完成后,开发商自行进行了3次迁移,相关数据如下:

某次迁移的带宽表现。
由于开发商出口带宽只有约500Mbps,经过测试发现迁移瓶颈主要出现在带宽限制上。实际并发时带宽大小待二期迁移时确认。

三.遇到的问题

  1. 首次创建主从无法连接源数据库
    现象:如图所示,每次建任务后总提示源数据库无法连接
    Error:Can’t connect to MySQL server on 10.*.*.*
    分析解决:由于迁移工具本质是CDB代理经过NAT通过外网和IDCMySQL实例相连,CDB的代理系统时间和NAT外网机器有差异,同时IDC开启连接重用,导致建立连接时前后时间不一致,系统认为为异常包,丢弃,连接失败。直接修改IDC服务器的内核参数,即net.ipv4.tcp_timestamps = 0net.ipv4.tcp_tw_recycle = 0即可

  2. 跨版本迁移的存储过程迁移失败
    现象:如图所示,开发商在迁移过程中出现proc表无法迁移的现象
    ERROR:Can’t load from mysql.proc. The table is probably corrupted
    解决:经CDB开发同事确认跨版本迁移的proc表因字段定义不同存在异常,发布版本跳过proc表解决。

  3. 迁移测试中创建新数据库导致binlog导入失败
    现象:迁移任务出现错误,无法迁移存储过程,binlog追加失败
    errno:1049:Error ‘Unknown database ‘xxxx’on query.
    解决:原因为本次迁移选定了只迁移某个数据库,迁移过程中新建了一个数据库,并开启binlog,导致CDB拉到的binlog有新数据库信息,和迁移数据库不匹配。解决方法为迁移过程不要出现DDL操作。

四. 总结

凡事预则立不预则废。正是因为客户在迁移前我们有多项功能测试,性能测试和边界条件测试的预备,使得在正式数据迁移时未出现数据不一致、现网运营切换故障等任何异常情况。为现网大规模的数据库实例迁移积累了经验。截止目前,客户逾130个MySQL实例已顺利迁移到腾讯云CDB并开启现网运营。基于这样的经验,我们有能力也有信心为腾讯云用户提供更加优质高效的数据存储迁移服务。

存储总量达20T的MySQL实例,如何完成迁移?的更多相关文章

  1. 如何安全地关闭MySQL实例

    如何安全地关闭MySQL实例 转载自:http://imysql.com/2014/08/13/mysql-faq-howto-shutdown-mysqld-fulgraceful.shtml 本文 ...

  2. 在docker中运行mysql实例

    Docker是一种新兴的虚拟化技术,能够一定程度上的代替传统虚拟机.下图是容器跟虚拟机的对比 对docker有个大致了解,学习docker断断续续,虽说学习不能急于求成,但断断续续学的话,浪费的碎片化 ...

  3. MySQL技术内幕InnoDB存储引擎(一)——MySQL体系结构和存储引擎

    1.数据库和实例 数据库(database)和实例(instance)不能混淆. 什么是数据库 数据库是物理操作系统文件或其他文件类型的集合.说白了,就是存储着的文件,不会运行起来,只能被实例增删改查 ...

  4. 全球共有多少MySQL实例在运行?这里有一份数据

    摘要 Shadowserver Foundation在5月31日发布了一份全网的MySQL扫描报告,共发现了暴露在公网的360万个MySQL实例.因为这份报告基数够大,而且信息也非常完整,从数据库专业 ...

  5. CentOS 7.0 启动多个MySQL实例(mysql-5.7.21)

    Linux系统:CentOS-7.0 MySQL版本:5.7.21 Linux系统下启动多个MySQL实例,目前知道有两种方法,一种是通过官方提供的mysqld_multi.server来实现,但是我 ...

  6. Windows下多个Mysql实例配置主从(转)

    https://www.cnblogs.com/jpfss/p/8143720.html 序:     网上有很多类似的文章,也是各种百度出来的,但是对于多数刚开始接触MYSQL主从的小白来说,网上文 ...

  7. 同一台windows下配置安装多个mysql实例,实现主从同步

    一.安装多个mysql 参见: https://blog.csdn.net/wrh_csdn/article/details/80198795 https://www.cnblogs.com/qjoa ...

  8. 2017全球GDP总量达74万亿美元 各国占比排行榜

    全球GDP总量达74万亿美元 各国占比排行榜     2017年公布的2015年全球各国GDP占比,数据图片来源:世界银行报告 2月24日,来自世界银行的最新GDP数字已于2月早些时候公布,现由How ...

  9. Python操作Mysql实例代码教程在线版(查询手册)_python

    实例1.取得MYSQL的版本 在windows环境下安装mysql模块用于python开发 MySQL-python Windows下EXE安装文件下载 复制代码 代码如下: # -*- coding ...

随机推荐

  1. SQL与NoSQL的CRUD对照

    SQL与NoSQL的CRUD对照 flyfish 2015-7-21 Create, Read, Update and Delete (CRUD) SQL方式 查 SELECT 列名称 FROM 表名 ...

  2. salt '*' state.highstate 报错找不到文件,环境如下No Top file or master_tops data matches found.

    salt '*' state.highstate 报错找不到文件,环境如下No Top file or master_tops data matches found. file_roots:    b ...

  3. 轻量级ORM框架Dapper应用三:使用Dapper实现In操作

    IN 操作符允许我们在 WHERE 子句中规定多个值. 本篇文章中,还是使用和上篇文章中同样的实体类和数据库,Dapper使用in操作符的代码如下: using System; using Syste ...

  4. e686. 显示打印窗口

    The print dialog allows the user to change the default printer settings such as the default printer, ...

  5. e674. 创建并绘制加速图像

    Images in accelerated memory are much faster to draw on the screen. This example demonstrates how to ...

  6. e663. 在gif图像中获取透明和色彩的数量

    A IndexColorModel is used to represent the color table of a GIF image. // Get GIF image Image image ...

  7. mui.back()返回刷新功能

    使用场景:操作某个步骤需要获取用户信息,如果用户未登陆,则跳转登录页面,登陆成功之后使用mui.back()返回父页面,父页面必须刷新. 子页面:登陆页 父页面:跳转登录页的页面 1. 在子页面初始化 ...

  8. js使用正则表达式从url中获取参数值

    //从url中获取参数值 function getvl(name) { var reg = new RegExp("(^|\\?|&)"+ name +"=([^ ...

  9. Ubuntu 12.04/13.04 安装 Oracle11gR2:该笔记已经陈旧!请参考后续的笔记

    注意点: 在 ubuntu的 /bin 下建立以下几个基本命令的链接: basename awk sh->bash | sh -> ksh 安装以下几个必须的包: binutils bui ...

  10. 放在github pages上的静态网站怎么取消绑定自定义域名?

    使用GitHub Pages搭建的静态网站绑定了自定义域名操作,但是想反悔怎么办? 删除CNAME文件,重新删除仓库,新建后均不行~ 解决办法:清除一下浏览器缓存,或者用别的浏览器打开就好了,因为之前 ...