圖樂資訊

MySQL 資料庫遷移為什麼只能執行一次?我為文章模式新增欄位的過程

發布時間:2026/7/18

作者:沈嘉怡

我在為 Gotule 新增普通文章模式時,需要替 MySQL 資料庫加入內容型別、固定舊網址編號和圖片替代文字等欄位。本文記錄我如何先完成備份、執行一次遷移 SQL,再查詢資料確認新欄位正常生效。

MySQL 資料庫遷移為什麼只能執行一次?我為文章模式新增欄位的過程-圖片1
執行 MySQL 資料庫遷移前備份網站程式與資料庫

為什麼新增文章模式需要修改資料庫?

我原來的網站只有圖集模式。每篇內容由多張圖片和文字組成,讀者需要使用上一頁、下一頁按鈕逐頁閱讀。

後來為了增加原創文章,我替網站加入普通文章模式。普通文章會在同一個頁面連續顯示所有圖片和文字,不再使用圖集的分頁方式。

前端畫面可以根據文章型別決定如何顯示,但資料庫也必須記住每篇內容屬於普通文章還是舊圖集。

這次更新需要新增幾個資料欄位:

這不是隻修改網頁外觀。只要資料表結構發生變化,就需要執行資料庫遷移。

我沒有直接在正式資料庫嘗試

資料庫遷移會修改正式網站的資料表。如果 SQL 寫錯、欄位名稱錯誤,或重複執行了不能重複的指令,可能會造成建立失敗,甚至影響後臺讀取文章。

因此,我沒有拿正式資料庫直接嘗試,而是先為網站程式和 MySQL 資料庫分別建立備份。

程式備份大約是 312MB,資料庫備份大約是 4.7MB。確認兩個檔案都已經產生,而且檔案大小不是零以後,我才繼續處理遷移。

程式備份可以在程式碼被錯誤覆蓋時恢復,資料庫備份則可以在資料表結構或內容發生問題時還原。

為什麼兩個備份都需要保留?

只備份程式程式碼並不能保護文章資料,因為標題、正文、分類和圖片資料都儲存在 MySQL 中。

反過來,只備份資料庫也不夠。如果新程式無法建立,仍然需要原來的程式版本讓網站恢復執行。

我現在會把部署前的保護分成兩部分:

  1. 備份目前正在執行的網站程式。
  2. 匯出當前 MySQL 資料庫。
  3. 檢查兩個備份檔案確實存在。
  4. 記錄備份目錄和建立時間。
  5. 完成後才解壓更新包和執行遷移。

這次操作讓我明白,資料庫遷移的第一步不是執行 SQL,而是先準備一條可以安全返回原來狀態的路徑。

在 Docker MySQL 容器內執行文章模式資料庫遷移

先確認遷移檔案已經存在

完成備份後,我先確認更新包裡的資料庫遷移檔案已經放進正確目錄。

這次使用的遷移檔是:

drizzle/0004_add_article_mode.sql

我先檢查檔案名稱和大小,確定解壓縮更新包後,這個 SQL 檔案確實存在。

如果遷移檔沒有出現在預期位置,我不會隨意尋找其他同名檔案執行,也不會直接在終端手動輸入一長串修改資料表的指令。

保留一份固定的遷移檔,可以清楚記錄這次到底新增了哪些欄位,也方便日後檢查網站版本。

透過 Docker 連線正式 MySQL

我的 MySQL 是由 Docker Compose 管理,所以我沒有在 VPS 外部另外建立一個資料庫連線。

我先確認 MySQL 容器顯示 Healthy,再透過 Docker Compose 進入資料庫容器,使用專案原本設定的資料庫名稱和密碼執行遷移檔。

執行時終端沒有顯示錯誤,並重新回到命令提示符號。

不過,沒有錯誤訊息並不代表我可以直接重複執行。下一步仍然要查詢資料表,確認新欄位是否真的已經加入。

為什麼遷移 SQL 通常只執行一次?

資料庫遷移的作用,是把舊的資料表結構改成新版本需要的結構。

例如第一次執行時,SQL 會在 galleries 資料表加入 contentModelegacyArticleNumber 等新欄位。欄位建立完成後,資料表就已經是新結構。

如果再次執行相同的新增欄位指令,MySQL 可能會提示欄位已經存在,導致遷移失敗。

更危險的遷移還可能包含搬移資料、改變欄位型別或刪除舊結構。重複執行這些操作,結果不一定與第一次相同。

因此,我會把遷移分成以下三個階段:

  1. 執行前先完成程式和資料庫備份。
  2. 確認目前尚未執行這份遷移。
  3. 只執行一次遷移檔案。
  4. 執行後立即查詢資料表驗證結果。
  5. 記錄這份遷移已經完成。

我不會因為終端沒有出現明顯輸出,就再次執行同一份 SQL。正確的做法是先查詢資料庫,而不是憑感覺重複操作。

查詢 MySQL 確認文章模式與固定舊網址欄位生效

執行後先查詢新欄位

完成遷移後,我沒有立刻重新建立整個網站,而是先查詢 galleries 資料表。

我檢查的內容包括:

查詢結果能夠正常顯示這些欄位,代表資料庫已經接受新的表格結構。

舊內容的 contentMode 保持為 gallery,所以原來的圖集不會因為這次遷移而自動變成普通文章。

這一點非常重要。新增功能時,不應該在沒有確認的情況下改變所有舊資料。

把第一篇原創內容設定為普通文章

確認欄位存在後,我才把 OneDrive 專案轉移文章設定為普通文章模式。

這篇內容的資料庫 ID 是 63。我將它的 contentMode 改為 article,並設定固定網址:

onedrive-project-storage-transfer

同時保留舊網址編號 1,讓原來的 /article/01 仍然可以找到這篇文章。

更新完成後,我再次查詢 ID 63,確認結果顯示:

這樣普通文章可以使用新的固定網址,舊數字網址也不會立即失效。

為什麼不能一次修改所有舊圖集?

網站裡原本有許多使用上一頁和下一頁閱讀的圖集。它們的圖片和文字是按照分頁方式建立的。

如果我把所有舊資料的 contentMode 一次改成 article,這些內容可能會突然在同一頁連續顯示,版面和閱讀方式都會發生變化。

因此,我只把真正按照普通文章結構編輯的內容設為 article。舊圖集繼續保持 gallery,不修改它們原來的功能。

現在後臺新增內容時,我可以自行選擇:

這種逐篇選擇的方式,比一次轉換整個資料庫安全。

重新建立網站後的檢查

完成資料庫遷移和內容設定後,我才重新建立網站應用程式。

網站啟動後,我檢查了以下專案:

  1. 新的普通文章網址可以正常開啟。
  2. 普通文章不會顯示上一頁和下一頁。
  3. 舊圖集繼續保留分頁功能。
  4. /article/01 會跳轉到新的固定網址。
  5. 文章標題、摘要、圖片和 ALT 文字正常顯示。
  6. 後臺可以選擇內容型別。
  7. MySQL 容器繼續顯示 Healthy。

只有資料庫查詢和實際網頁都正確,我才把這次遷移視為完成。

這次資料庫遷移讓我學到的事情

以前我看到 SQL 沒有輸出錯誤,就會以為操作已經完成。這次經驗讓我明白,資料庫遷移必須包含備份、執行和驗證三個部分。

沒有備份,發生問題時就沒有安全的返回路徑;沒有驗證,則無法確定遷移是否真正生效。

我現在會遵守以下原則:

資料庫遷移本身可能只需要幾秒鐘,但真正重要的是遷移前後的確認過程。