Mysql百萬級資料遷移,怎麼遷移?實戰過沒?

Laravel00發表於2021-12-14

文章來自微信公眾號:PHP自學中心

假如有這麼一個場景,開發了一個小程式,趁著雙十一活動的熱度,一個月後迅速積累了一百多萬使用者,我們在小程式頁面增加了收集formid的埋點,用於給微信使用者傳送模板訊息通知。

隨著資料量的增大,之前使用的伺服器空間開始有點不夠用,最近新寫了一個專門用於做小程式後臺開發的框架,於是想把原來的資料遷移到新系統的資料庫。買了一臺4核8G的機器,開始做資料遷移。下面對遷移過程做一個簡單的記錄。

Mysql百萬級資料遷移,怎麼遷移?實戰過沒?

方案選擇

mysqldump遷移

平常開發中,我們比較經常使用的資料備份遷移方式是用mysqldump工具匯出一個sql檔案,再在新資料庫中匯入sql來完成資料遷移。

試驗發現,通過mysqldump匯出百萬級量的資料庫成一個sql檔案,大概耗時幾分鐘,匯出的sql檔案大小在1G左右,然後再把這個1G的sql檔案通過scp命令複製到另一臺伺服器,大概也需要耗時幾分鐘。在新伺服器的資料庫中通過source命令來匯入資料,我跑了一晚上都沒有把資料匯入進來,cpu跑滿。

指令碼遷移

直接通過命令列運算元據庫進行資料的匯出和匯入是比較便捷的方式,但是資料量較大的情況下往往會比較耗時,對伺服器效能要求也比較高。如果對資料遷移時間要求不是很高,可以嘗試寫指令碼來遷移資料。雖然沒有實際嘗試,但是我想過大概有兩種指令碼方案。

第一種方式,在遷移目標伺服器跑一個遷移指令碼,遠端連線源資料伺服器的資料庫,通過設定查詢條件,分塊讀取源資料,並在讀取完之後寫入目標資料庫。這種遷移方式效率可能會比較低,資料匯出和匯入相當於是一個同步的過程,需要等到讀取完了才能寫入。如果查詢條件設計得合理,也可以通過多執行緒的方式啟動多個遷移指令碼,達到並行遷移的效果。

第二種方式,可以結合redis搭建一個“生產+消費”的遷移方案。源資料伺服器可以作為資料生產者,在源資料伺服器上跑一個多執行緒指令碼,並行讀取資料庫裡面的資料,並把資料寫入到redis佇列。目標伺服器作為一個消費者,在目標伺服器上也跑一個多執行緒指令碼,遠端連線redis,並行讀取redis佇列裡面的資料,並把讀取到的資料寫入到目標資料庫。這種方式相對於第一種方式,是一種非同步方案,資料匯入和資料匯出可以同時進行,通過redis做資料的中轉站,效率會有較大的提升。

這裡你也可以使用go語言來寫遷移指令碼,利用其原生的併發特性,可以達到並行遷移資料的目的,提升遷移效率。

檔案遷移

第一種遷移方案效率太低,第二種遷移方案編碼代價較高,通過對比和在網上找的資料分析,我最終選擇了通過mysql的。

select data into outfile file.txt、load data infile file.txt into table

的命令,以匯入匯出檔案的形式完成了百萬級資料的遷移。

遷移過程

在源資料庫中匯出資料檔案

select * from dc_mp_fans into outfile '/data/fans.txt';  

複製資料檔案到目標伺服器

zip fans.zip /data/fans.txtscp fans.zip root@ip:/data/   

在目標資料庫匯入檔案

unzip /data/fans.zipload data infile '/data/fans.txt' into table wxa_fans(id,appid,openid,unionid,@dummy,created_at,@dummy,nickname,gender,avatar_url,@dummy,@dummy,@dummy,@dummy,language,country,province,city,@dummy,@dummy,@dummy,@dummy,@dummy,@dummy,@dummy,@dummy,@dummy);

按照這麼幾個步驟操作,幾分鐘內就完成了一個百萬級資料表的跨伺服器遷移工作。

注意項
  • mysql安全項設定

在mysql執行load data infile和into outfile命令都需要在mysql開啟了secure_file_priv選項, 可以通過show global variables like ‘%secure%’;檢視mysql是否開啟了此選項,預設值Null標識不允許執行匯入匯出命令。

通過vim /etc/my.cnf修改mysql配置項,將secure_file_priv的值設定為空:

[mysqld]  secure_file_priv=''

則可通過命令匯入匯出資料檔案。

  • 匯入匯出的資料表欄位不對應

上面示例的從源資料庫的dc_mp_fans表遷移資料到目標資料庫的wxa_fans表,兩個資料表的欄位分別為:dc_mp_fans

Mysql百萬級資料遷移,怎麼遷移?實戰過沒?

wxa_fans

Mysql百萬級資料遷移,怎麼遷移?實戰過沒?

在匯入資料的時候,可以通過設定欄位名來匹配目標欄位的資料,可以通過@dummy丟棄掉不需要的目標欄位資料。

總結

結合本次資料遷移經歷,總結起來就是:

  • 小資料量可以使用mysqldump命令進行匯入匯出,這種方式簡單便捷。
  • 資料量較大,且有足夠的遷移耐心時,可以選擇自己寫指令碼,選擇合適的並行方案遷移資料,這種方式編碼成本較高。
  • 資料量較大,且希望能在短時間內完成資料遷移時,可以通過mysql匯入匯出檔案的方式來遷移,這種方式效率較高。
本作品採用《CC 協議》,轉載必須註明作者和本文連結
溫馨提示:微信搜尋並關注   學Laravel  裡面有兩套Laravel課程:【laravel7.x 從入門到核心架構講解】 與 【Laravel高階實戰教程42集】,直接獲取就可以了

相關文章