MySQL / TiDB數據遷移及驗證

一、環境準備

1.1 工具介紹

數據量比較大,使用MySQL官方自帶的mysqldump難以滿足需求的時候,可以使用mydumper執行數據遷移工作。mydumper 最突出的特性就是可採用多線程並行備份,極大提高了數據導出的速度。mydumper的工作原理可以參考:MyDumper原理簡介
與其他備份工具一樣,mydumper 默認情況下是用 FTWRL (Flush Tables With Read Lock) 全局讀鎖來保證備份數據的一致性。在開始備份之前,需要對當前數據庫負載情況謹慎評估,擇時或者從庫執行。另外,雖然 mydumper 支持表級別的並行操作,且在導出的時候會對大的表數據進行分塊 chunk 導出,但是同一個表的 chunks 是在同一個線程中處理的,並非多線程並行的。

1.2 軟件安裝

可以考慮在mydumper的GitHub地址中下載release包,或者從TiDB官方網站下載tidb-enterprise-tools,其中也包含了mydumper。這裏我們選擇從GitHub下載。

# download
wget https://github.com/maxbube/mydumper/releases/download/v0.9.5/mydumper-0.9.5-2.el7.x86_64.rpm
# install
sudo rpm -i mydumper-0.9.5-2.el7.x86_64.rpm
# check installation
mydumper --help
myloader --help

二、數據導出

2.1 檢查確認需要導出的目標表數據和索引大小

SELECT
	TABLE_NAME,
	(DATA_LENGTH)/(1024*1024) data_m_bytes,
	(INDEX_LENGTH)/(1024*1024) index_m_bytes,
	TABLE_ROWS 
FROM
INFORMATION_SCHEMA.TABLES 
WHERE
	TABLE_SCHEMA = 'post_boots' 
	AND TABLE_NAME IN ( 'index_beauty_is_myhouse_in_hour', 
	'index_beauty_isnt_myhouse_in_hour', 'index_barm_zoom_style_region' )
order by TABLE_NAME;

2.2 執行導出

  • 使用mydumper導出數據
screen -R daba_backup
mydumper --verbose=3 -h 10.2.2.2 -P 4000 -u $user -p $passwd -t 16 -F 8 -B post_boots \ 
-T index_beauty_is_myhouse_in_hour,index_beauty_isnt_myhouse_in_hour,index_barm_zoom_style_region \ 
--skip-tz-utc -o /home/babe/post_boots_tidb_bak > /home/babe/post_boots_tidb_backup_output.txt 2>&1

參數解釋:

-t 線程數;
-F 導出文件分塊大小,官方建議是64M,TiDB對事務大小做了限制,如果發現導出時候控制檯報錯,可以適當降低這個數值;
-B 需要導出的database;
-T 指定需要導出的表,英文逗號分割;
–skip-tz-utc 忽略掉 MySQL 與導數據的機器之間時區設置不一致的情況,禁止自動轉換;
-o 指定導出路徑,mydumper會自動創建;

  • 檢查導出結果
# 查看輸出是否有錯誤
vi /home/babe/post_boots_tidb_backup_output.txt
# 由於tidb的限制,確認下生成的文件中沒有超過30萬行的
find /home/babe/post_boots_tidb_bak -name "*.sql" -exec wc -l {} \; | awk '$1>300000'
  • 壓縮導出數據文件夾
tar -zcvf post_boots_doodv1_tidb.tar.gz /home/babe/post_boots_tidb_bak

三、數據導入

  • 執行導入
myloader --verbose=3 -q 200 -h 10.2.2.2 -P 4000 -u $user -p $passwd -t 16 -B post_boots_imported \ 
-d /home/babe/post_boots_tidb_bak  > /home/babe/post_boots_tidb_import_output.txt 2>&1
  • 檢查導入結果
vi /home/babe/post_boots_tidb_import_output.txt

四、數據驗證

4.1 檢查新庫表的數據和索引大小

SELECT
	TABLE_NAME,
	(DATA_LENGTH)/(1024*1024) data_m_bytes,
	(INDEX_LENGTH)/(1024*1024) index_m_bytes,
	TABLE_ROWS 
FROM
INFORMATION_SCHEMA.TABLES 
WHERE
	TABLE_SCHEMA = 'post_boots_imported' 
	AND TABLE_NAME IN ( 'index_beauty_is_myhouse_in_hour', 
	'index_beauty_isnt_myhouse_in_hour', 'index_barm_zoom_style_region' )
order by TABLE_NAME;

4.2 檢查數據行數是否一致

select count(*) from post_boots.index_beauty_is_myhouse_in_hour union all
select count(*) from post_boots_imported.index_beauty_is_myhouse_in_hour;

select count(*) from post_boots.index_beauty_isnt_myhouse_in_hour union all 
select count(*) from post_boots_imported.index_beauty_isnt_myhouse_in_hour;

4.3 檢查數據明細是否一致

  • 目標庫和源庫不在一個實例

參考 MySQL —— 如何快速對比數據? 的思路,可以用數據行的md5值來比較數據明細是否一致。由於TiDB的group_concat實現不支持order by,因此採用截取行md5值後幾位然後求和取整的方式來近似比較。

SELECT min(id) AS min_id, 
       max(id) AS max_id, 
			 (id div 10000) id_gap, 
       count(1) AS ROW_COUNT, 
       cast( 
			 round( 
					sum( 
						SUBSTR( 
MD5(concat(IFNULL(id,''),IFNULL(date_with_hour,''),IFNULL(is_id,''),IFNULL(source_is_id,''),IFNULL(myhouse_id,''),IFNULL(source_myhouse_id,'')) 
							), -2) 
					), 2) 
					as char(12)) 
					AS md5_value 
FROM post_boots.index_beauty_is_myhouse_in_hour 
GROUP BY id_gap 
order by id asc;

在新舊錶執行上述語句,導出執行結果——譬如用mysql命令行客戶端用-e選項執行語句然後重定向到文件,然後使用diff命令比較文件差異:

diff -i -B -s post_boots.index_beauty.txt post_boots_imported.index_beauty.txt
  • 目標庫和源庫在同一個實例

參考 MySQL Compare Two Tables 的做法,使用如下語句對比目標庫和源庫的數據是否一致:

SELECT id, date_with_hour, is_id, source_is_id, myhouse_id, source_myhouse_id
FROM (
    SELECT id, date_with_hour, is_id, source_is_id, myhouse_id, source_myhouse_id
    from post_boots.index_beauty_is_myhouse_in_hour where id >=60000000
    UNION ALL
    SELECT id, date_with_hour, is_id, source_is_id, myhouse_id, source_myhouse_id 
		FROM post_boots_imported.index_beauty_is_myhouse_in_hour where id >=60000000
) tbl
GROUP BY id, date_with_hour, is_id, source_is_id, myhouse_id, source_myhouse_id
HAVING count(*) <> 2
ORDER BY `id`;

注意如果數據量較大,需要按照id劃分區間比較。

五、參考資料

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章