從一次數據遷移項目里,我得到的四個經驗教訓
不久前,我經歷了一次數據遷移項目。前幾天,我跟一位架構師探討了一下當時的各個步驟,和我所選擇并進一步開發的解決方案。我覺得我應該告訴他一些信息 ,避免他日后遷移數據時踩坑。
在我們的交流中 ,我提到了數據遷移的各種難題和我們遇到的問題。現在我意識到,這些東西對許多從事數據遷移項目的人們來說都很有用。我聽說這些是很常見的問題,多是那些開始數字化轉型的公司容易遇到的 。數據遷移項目通常是一套解決方案,讓你提取、轉換舊數據,然后將其存儲到新的系統中。
之前沒想到的是,我從事軟件工作以來只參與過一個數據遷移項目。感覺好像回到了我在學習 SQL 時掙扎的日子。那時的經歷很有意思,你在 Oracle 和 MariaDB 上都使用 PL/ SQL ,并為此頭痛不已。你只能自行猜測哪個是舊系統,哪個是光芒萬丈的新系統。但今天不講這個,今天講我認為導致延遲交付的最大陷阱。觀點是我自己的,但事情卻是大家都會遇到的,等等等等。
1. 用 SQL 腳本做主要工具
這是昨天早上我忘了向同事強調的一個問題,今天早上它又在我腦海閃現。別誤會,SQL 是強大的 數據 檢索和顯示工具。但是,當你有一個由多個開發人員組成的團隊,并在同一個代碼庫上工作時,關鍵要確保你的更改能與其他代碼很好地整合。
問題在于,要驗證不同的場景 時 ,我們不能只花幾秒鐘或幾分鐘運行典型的單元測試。我們必須執行實際的遷移,因此我不會稱之為“集成測試”,因為 集成測試的 環境與實際環境有所不同(后文會詳細介紹)。
我們必須啟動 docker 鏡像,然后給將來要 用真實數據應對 的每種 場景 加載虛擬數據。我覺得我們的 Jenkins 構建一次要 2-3 個小時才能完成。這使本地開發更加困難,因為沒有人愿意花 5 分鐘內改代碼然后花 2-3 個小時來測試。最開始我們改為只運行我們需要的那些測試用例。那時 CI 慢 到, 我甚至在上一年專門發了一個帖子講這個事情 。最終,我們將時間降到了 40 分鐘,仍然很慢,但考慮到我們正在處理的內容,可能這就是我們最好的選擇了。
https://www.codingnagger.com/2019/01/31/slow-ci/
現在我不是 在談我自己的經驗 ,而是 在說 一些跟我討論過的架構師 的看法 ,他們在那個項目 期間,甚至項目結束之后都向我建議 ,用一種實際的編程語言可以使我們免于這種痛苦:你可以 測試任意組件,完整的檢索 、轉換和加載 操作 只需幾秒鐘就夠了。然后你再對理想路徑進行一次集成測試。我們本來可以把 CI 構建控制在一分鐘之內的,從而節省很多時間。
2. 源字段和目標字段對不上
字段不匹配是很痛的痛點。我不是指從源數據字段到目標數據字段的對應錯誤,而是指字段對應沒問題,但目標字段類型不對。由于數據 的 敏感 性 ,我們研究解決方案時接觸不到真實數據。
所以這種問題只有到了在生產環境運行時才會暴露出來。你可能會有一些源字段是字符串類型的,但目標字段卻是整型的。當所有測試數據都是數值時不會有問題,但當在幾百萬實體中出現哪怕一兩條包含字母時,就全都完了。還有些時候數據會被截斷,因為目標字段所能表達的值范圍比源字段要小。這種問題不是數據遷移工程的責任,因為目標系統不是我們設計的,但實際上我們在交付數據遷移方案時卻不得不去修復這種問題。是的,現實并沒有那么理想。
所以在這里我要強調的是,如果你要構建一個系統的新版本,請確保新的數據庫字段的類型和格式都能匹配源數據。我們不能截斷地址或電話號碼,尤其是當我們系統需要這些信息時。
3. 與其他團隊邊界不明確
當時,我的團隊是做數據遷移的。我們設計了一個解決方案,把數據從這里遷移到那里。但如上文所述,我們有時不得不修復目標數據庫的問題,這些問題都是其他團隊為各種功能折騰出來的。最重要的是,我不明白我的團隊怎么就變成了其他團隊的測試數據提供者。反正 這些團隊不會把所有的測試數據匯總在一起以便測試其功能,而是會來找我們為他們生成隨機的測試數據。
回想起來,這么做真蠢。因此,我們構建的測試框架中有一個類用于生成數據。在 開發時,我們把這些數據存到源數據庫里,然后運行遷移過程,提取、轉換這些數據,并把它們存到目標數據庫里。接著再從目標系統中導出這些數據發送給那些團隊。我們不得不這么做,因為我們不想在我們的職責范圍之外制造數據。但是,我認為我們做的太多了。我們應該把 底線控制 在“請您自行創建測試數據”上。
雖然幫助他人 也是可以的 ,但我們不能在自己本職工作都沒做完的情況下這么做。最后的結果就是,我們負責了整個工程的三個主要部分:數據遷移、修復目標數據庫的問題、給每個人生成測試數據。
4. 不同環境的設置
我記得當時我沒有過多考慮 各種部署 環境的不同設置。從開發環境到預發布環境,再到生產環境,它們 會 有很多差異。顯然,我們為此付出了代價。你可能會認為不同版本間的 Oracle 數據庫或 MariaDB 數據庫應該不會有什么大問題吧?但如果我告訴你下個版本跟這個版本的差異會破壞掉你所有的 SQL 腳本呢?就像必須把 VALUES 替換成 VALUE。
想象一下遷移工具在你本地運行得好好的,接下來你把它推送到一個緩慢的 CI 流程 。然后你再把它發布到一個環境,運行遷移過程并檢查 ,沒什么問題 。結果到生產環境出問題了,因為生產環境的 MariaDB 版本太老。此外,生產環境還是個 EC2 實例,而預發布環境則是 RDS。
這個項目在開發環境和在生產環境的變量設置完全一致,但我還是被它們輸出的差異驚到了。為 了 在不同集成環境里都能工作而到處改代碼 ,那些痛苦你都逃開了 。生產環境的配置 本應能 證明你的解決方案可以在生產環境工作,但 其實 它跟真實的生產環境配置一點也不像, 這肯定就會出問題 。這絕對是我在這次經歷中得到的最大一筆經驗。
5. 總結
我將在余生中繼續學習從舊項目獲得的經驗教訓。我甚至會重溫這篇博客文章來確保我不會忘記這些經驗教訓,因為它們在我下次進行數據遷移時還是非常有用的。更妙的是,其中一些經驗教訓不僅僅可以用于數據遷移,還可以應用于其他方面。
即使這次我沒有去找個工具來做, 本文談到 的 這些 經驗也讓我堅信應該找個好工具來做好工作。信任已有信息固然很好,但也不妨 去看看周圍 ,對自己也沒有什么壞處。有時這些工具并不比 SQL 查詢慢。
其次,盡可能確保開發環境的設置與生產環境匹配。這將避免許多集成問題。
最后,當職責明確了之后,應避免給自己攬更多的活兒,它們會妨礙你的本職工作。塞爾吉奧·拉莫斯(Sergio Ramos)并不是世界上最好的后衛,因為他本賽季得分超過菲爾米諾。最好的后衛應該是先做好自己擅長的防守工作,然后偶爾進進球。