一、環境準備
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
劃分區間比較。