目錄
- 背景
- 方案一:老數(shù)據(jù)備份
- 方案二:分表
- 方案三:遷移至tidb
- 重點說下同步老數(shù)據(jù)遇到的坑
- 最終同步腳本方案
- 總結
背景
由于歷史業(yè)務數(shù)據(jù)采用mysql來存儲的,其中有一張操作記錄表video_log,每當用戶創(chuàng)建、更新或者審核人員審核的時候,對應的video_log就會加一條日志,這個log表只有insert,可想而知,1個video對應多條log,一天10w video,平均統(tǒng)計一個video對應5條log,那么一天50w的log, 一個月50 * 30 = 1500w條記錄, 一年就是1500 * 12 = 1.8億。目前線上已經(jīng)有2億多的數(shù)據(jù)了,由于log本身不面向C端,用于查詢問題的,所以可以忍受一點的延遲。 但是隨著時間的積累,必然會越來越慢,影響效率,于是提出改造。

方案一:老數(shù)據(jù)備份
由于log本身不是最關鍵的數(shù)據(jù),但是也要求實時性高(用于實時查詢問題),所以一開始的想法是核心的基礎存儲還是保持不變,較老的數(shù)據(jù)遷移出去,畢竟突然去查詢一年前的操作記錄的概率很小,如果突然要查,可以走離線。設計的話,我們只需要一個定時腳本,每天在凌晨4點左右(業(yè)務低峰期)抽數(shù)據(jù)。抽出的數(shù)據(jù)可以上報到一些離線存儲(一般公司都有基于hive的數(shù)倉之類的),這樣就可以保持線上的video_log的數(shù)據(jù)不會一直增長。

方案二:分表
分表也是一種解決方案,相對方案一的好處就是,所有的數(shù)據(jù)都支持實時查,缺點是代碼要改造了。
- 首先確認sharding key,因為video_log是和video綁定的,所以自然而然選擇video_id作為我們的sharding key
- 按什么分表確定了,接下來確認下分多少張表。先定個小目標,支撐3年。每張表最大數(shù)據(jù)量為1個億(由于我們的查詢簡單),按照上面的統(tǒng)計,我們3年大概:3*1.8=5.4億,那么大概需要5.4/1≈6張表。

接下來就是改造代碼了,得解決新老數(shù)據(jù)讀寫的問題。
- 新數(shù)據(jù)的插入直接插入新表
- 由于log表只有insert,所以不存在update、delete這些操作,不需要考慮這些場景。
- 分表后,一個video的log存在兩張表(老表和新表),所以臨時兩張表都查,然后做個合并
- 同步老數(shù)據(jù)到新表中
- 下線讀取老表的代碼

方案三:遷移至tidb
方案二的缺點比較明顯,3年后咋辦,繼續(xù)拆表?感覺始終有個歷史債在那。于是我們的目光定位到了tidb,tidb是分布式的數(shù)據(jù)庫,接入了tidb,我們就無需關心分表了,這些tidb都幫我們做了,它會自己做節(jié)點的擴容。由于是分布式的,所以tidb的主鍵是無序的,這點很重要。
整個流程大概分為以下4個步驟:
- 先雙寫(記錄下剛開始雙寫時的mysql的id,在此id前的肯定都是老數(shù)據(jù))
- 同步老數(shù)據(jù)(通過第一步記錄的id來區(qū)分)
- 切讀(老數(shù)據(jù)同步完了)
- 下雙寫

重點說下同步老數(shù)據(jù)遇到的坑
遷移至tidb,看似很簡單,其實在job腳本這里隱藏著幾個坑。
- 要考慮萬一job中途斷了,重新啟動咋辦,撇開重頭跑數(shù)據(jù)的時間成本,已經(jīng)同步的數(shù)據(jù)重新跑會重復,還要考慮重復數(shù)據(jù)的問題。解決重復數(shù)據(jù)的問題,可以對老表新加一個字段標識是否已同步,每次同步完,更新下字段。缺點:線上數(shù)據(jù)大,加個字段不太安全,可能造成線上阻塞。
- 既然加個字段不好,那就用現(xiàn)有的主鍵id做約束,把主鍵id也同步過去,這樣就算腳本重啟,從頭開始跑的,也因為相同的主健已經(jīng)插入過,那么就會報錯跳過??此坪芡昝?,然而tidb是分布式的,主鍵id不是連續(xù)的,那么可能出現(xiàn)這樣一種情況。正常的業(yè)務數(shù)據(jù)插入tidb,tidb分配的主鍵id和mysql同步的主鍵id重復,那么不管是誰,最后插入的那一條肯定是失敗的。

最終同步腳本方案
綜合考慮數(shù)據(jù)的重復性,job重啟效率性,和整個同步的效率性,我大概做出以下方案:
- 任務分批提升效率:首先根據(jù)處理能力和預期完成時間,先對老數(shù)據(jù)進行分批,大概分了10批,10個job去跑不同批次的數(shù)據(jù),互不干擾,且每次批量更新100條。
- 記錄狀態(tài),重啟自動恢復到斷點:每次同步數(shù)據(jù)后記錄下當前同步的位置(redis記錄下當前的id),就算重啟也可以從redis里拿到之前的更新位置,接著更新。
- 避免主鍵沖突:同步除了主鍵之外的所有字段(不同步主鍵)
最終通過方案三的四個切換步驟+高效率的同步腳本平穩(wěn)的完成了數(shù)據(jù)的遷移
總結
到此這篇關于mysql遷移的方案與踩坑的文章就介紹到這了,更多相關mysql遷移方案與踩坑內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- MySQL數(shù)據(jù)庫遷移data文件夾位置詳細步驟
- Mysql的數(shù)據(jù)庫遷移到另一個機器上的方法詳解
- oracle數(shù)據(jù)庫遷移到MySQL的方法總結
- mysql數(shù)據(jù)庫遷移至Oracle數(shù)據(jù)庫
- MySQL數(shù)據(jù)庫遷移快速導出導入大量數(shù)據(jù)
- mysql Innodb表空間卸載、遷移、裝載的使用方法
- 關于MySQL數(shù)據(jù)遷移--data目錄直接替換注意事項的詳解
- 淺析mysql遷移到clickhouse的5種方法
- mysql5.5數(shù)據(jù)庫data目錄遷移方法詳解
- mysql 備份與遷移 數(shù)據(jù)同步方法