iT邦幫忙

2026 iThome 鐵人賽

DAY 13
0

建置篇結束,網路通了、資料庫也建好了。接下來要把資料搬過去。

我在這件事上用了兩種完全不同的做法。測試環境(7 月)用第一種,生產環境(8 月)換成第二種。

換的理由有三個。兩個是「不想帶到新環境的東西」,第三個是第一種做法在測試環境已經出過一次事。

第一種做法:整包倒過去

最直覺的搬家方式:把舊資料庫整個匯出成一個檔案,裡面同時包含表的結構和裡面的資料,然後灌進新的資料庫。灌完之後再部署服務,讓它們連過來。

這個做法的問題是,我們的舊資料庫是 MariaDB,新的是 MySQL。兩者是遠親,語法大致相容,但有些地方不一樣。

所以中間得多一道工序:把匯出的檔案讀一遍,把不相容的語法改掉。要處理的至少有三類:

  • 某些索引的寫法 MySQL 8 不吃
  • 長文字欄位加唯一索引,MySQL 8 會直接拒絕
  • 表的建立順序如果不對,外鍵會參照到還不存在的表

改完之後可以灌,也灌成功了。測試環境就是這樣過來的。

這條路我們在測試環境走過兩次,兩次的來源還不一樣:第一次從舊叢集裡的資料庫匯出,後來重新遷移的時候改從另一台匯出。但不管來源是哪一台,那道語法轉換的工序都得再跑一遍。它不是一次性的成本,是每次重來都要付的成本。

但這個做法帶了一些東西過去

問題是那個匯出檔裡的表結構,是舊資料庫累積了很久的樣子。

一個跑了幾年的系統,表結構上常常有一些沒人記得的欄位:早期功能留下的、改版後不再使用的、當初加了但後來換做法的。它們還在,只是沒人用。

整包倒過去的意思是,這些東西也一起搬進新家。新環境從第一天起就繼承了舊環境的所有歷史。

還有一個更討厭的副作用,跟文字的排序規則有關。匯出檔裡的表帶著舊資料庫的排序規則,而服務的程式如果自己去建表,用的會是新資料庫的預設值。兩種規則混在同一個資料庫裡,某些操作會直接報錯說兩邊不相容。

這就是前面說的那次出事。 測試環境匯入的時候炸出一個錯誤代碼,訊息講的是外鍵兩邊的欄位不相容,而我當時完全看不出它跟排序規則有什麼關係,更看不出它跟「我用了哪種搬家方式」有什麼關係。那整件事後面會單獨講一篇。

https://ithelp.ithome.com.tw/upload/images/20260927/201786568d9HRnJYpO.jpg

第二種做法:讓程式自己建表,我們只搬資料

生產環境我換了順序:先部署服務。 我們的服務用的框架有一個功能,啟動時會檢查資料庫,該建的表自己建、該加的欄位自己加。所以服務一起來,一套乾淨的表結構就出現了。

然後只灌資料。 匯出的時候加一個參數(--no-create-info)明確告訴它「不要帶表結構」,出來的檔案裡就只有一列一列的資料,沒有任何建表的指令。

這樣做有三個好處:

一、不用做語法轉換了。 因為表結構不是從舊資料庫來的,是新環境的程式自己建的。MariaDB 和 MySQL 的語法差異,在這條路上根本不會出現。

二、新環境拿到的是乾淨的結構。 表裡只有現在的程式真正需要的欄位,那些歷史包袱留在舊環境,跟著舊環境一起退休。

三、排序規則統一了。 全部的表都由同一支程式、在同一台伺服器上建立,用的是同一套預設值。剛才那個「兩種規則混在同一個資料庫裡」的狀況,在這條路上不會發生。

這個做法的代價

前面講得好像第二種做法只有好處,其實有一個代價,而且不小。

它是一次把全部資料倒過去,沒有「先倒大部分、切換前再補上這段期間的差異」這種增量機制。所以從開始匯出到正式切換的這整段時間,來源那邊不能再有任何新的寫入,寫進去的就會遺失。

這讓停機視窗變成實打實的:得先把對外的入口關掉、切斷所有使用者的寫入,才能開始匯出,然後整個過程都在計時。

我們願意付這個代價,是因為生產環境用的是藍綠切換:來源那一套從頭到尾沒有被動過,還在正常服務。萬一新環境出問題,把流量切回去就好,倒過去的那份下次重灌。這讓「停機視窗很緊」變成一個時間問題,而不是一個風險問題。

為什麼生產環境才做得到

這個做法有一個前提:你要有一個乾淨的環境可以讓服務先跑起來建表。

測試環境當初做不到,因為那是在既有的叢集上加東西,服務早就在跑、資料早就在裡面。生產環境是藍綠切換,那一套是全新的,所以可以先讓服務空跑一輪,把結構建好,再灌資料。

這件事跟 Day 11 講的其實是同一個形狀:「既有」和「全新」的差別,會一路影響到你能選哪些做法。那時候影響的是網路要不要對接,這次影響的是資料能不能乾淨地搬。

也就是說,第二種做法不是我變聰明了,是我終於拿到一張白紙。

帶得走的東西

「搬資料」和「搬結構」是兩件可以分開的事,而且它們的最佳來源不一樣。

資料只能從舊環境來,這沒得選。但結構有兩個來源:舊資料庫的匯出檔,或是現在的程式碼。

如果你的專案是用程式自動建表的,那程式碼才是結構的真相,資料庫只是它的一個投影。從程式碼重建結構,你會得到「現在應該長的樣子」;從匯出檔重建,你會得到「歷史累積下來的樣子」。

不過這個結論有前提。它成立是因為我們的服務會自己建表,所以「真相」有個明確的所在地。如果你的結構是靠版本化的變更檔在管的,那真相在那些檔案裡;如果是歷年來大家手動改上去的,那就沒有真相,只有現況,這時候整包搬過去反而是唯一誠實的選擇。

搬家是少數幾個可以順便丟東西的時機。整包搬過去雖然省事,但等於把打包好的雜物原封不動放進新家。


明天開始講實際怎麼搬。第一件事是把資料倒出來,而這一步不只是倒出來,中途還要順便改名字:資料庫的名字要改、有些欄位的名字也要改,還有一張表要整個跳過。


上一篇
Day 12:不在資料庫裡的那些檔案
系列文
菜鳥工程師的 DR 告白:混合雲異地備援,與資料庫回家的那 12 分鐘 共 13 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言