存儲總量達20T的MySQL實例,如何完成遷移?

版權聲明:本文由王亮原創文章,轉載請註明出處: 
文章原文連接:https://www.qcloud.com/community/article/122html

來源:騰雲閣 https://www.qcloud.com/communitymysql

 

王亮,騰訊雲高級工程師。2010年加入騰訊,曾負責騰訊社交產品CDN圖片類業務,動態加速業務的運維工做。現負責數據庫產品的解決方案工做。git

某國內大型遊戲開發商有超過130個IDC部署MySQL實例,存儲總量達20T。因業務須要,將所有實例遷移到騰訊雲CDB for MySQL。騰訊雲數據庫團隊爲保證業務遷移順利進行,對遷移流程,工具進行了前期的調查研究,並對過程當中發現的4大問題進行及時解決,如下是實際遷移經驗分享:github

一. 測試用例/過程

目前開發商上雲(外部MySQL遷移到CDB)提供多種方案,其中開發商的MySQL實例有外網IP的能夠直接使用騰訊雲數據庫遷移工具完成遷移(其餘的遷移方法參見連接本次遷移任務中該開發商的全部MySQL實例均有外網代理IP供使用,故直接選用遷移工具完成數據導入。sql

遷移工具的基本原理:經過待遷移實例提供的高權限賬號獲取源實例基本的MySQL實例配置,並同步到目標CDB實例;經過mysqldump直接將源實例導出傳輸到CDB實例後導入;源數據庫實例和目標CDB創建主從關係同步新數據。其中CDB實例與源IDC之間經過NAT方式以一臺帶外網的服務器爲中轉發起通訊。數據庫

1. 遷移工具基本功能

騰訊雲數據庫控制檯頁面根據引導創建遷移任務;在後臺管理頁面觀察遷移任務後臺日誌等。bash

任務開始運行後檢測代理機器流量變化,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並開啓現網運營。基於這樣的經驗,咱們有能力也有信心爲騰訊雲用戶提供更加優質高效的數據存儲遷移服務。

相關文章
相關標籤/搜索