鵝的遷徙以實現平滑的資料庫變更

你好,夥伴!

今天,我們來談談什麼是資料庫遷移以及為什麼它們如此重要。在今天的世界裡,任何對資料庫的變更都應該小心謹慎並按照特定的流程進行,這並不意外。理想情況下,這些步驟應該整合到我們的 CI/CD 流程中,以便一切自動運行。

這是我們的議程:

  1. 問題是什麼?
  2. 我們如何解決它?
  3. 一個簡單的例子
  4. 一個更複雜的例子
  5. 建議
  6. 結果
  7. 結論

問題是什麼?

如果你的團隊從未處理過資料庫遷移,並且你不完全確定為什麼需要它們,我們來澄清一下。如果你已經知道基本概念,請隨意跳過。

主要挑戰

當我們對資料庫進行“計劃性”和“平穩”的變更時,我們需要保持 服務可用性 並滿足 SLA 要求(以免用戶遭受停機或延遲)。想像一下,你想在一個有 500 萬用戶的表中更改一個列的類型。如果你“直接”這樣做(例如,簡單地運行 ALTER TABLE 而不做準備),該表可能會被鎖定相當長的時間——而你的用戶將無法使用服務。

為了避免這種麻煩,請遵循兩條規則:

  1. 以不鎖定表的方式應用遷移(或至少最小化鎖定)。
  2. 如果您需要更改列类型,通常最容易的方法是先创建一个具有正确类型的新列,然后再删除旧列。

另一个问题:版本控制和回滚

有时您需要回滚迁移。

手动执行这个操作——进入生产数据库并处理数据——不仅风险高,而且如果您没有直接访问权限的话,这也很可能无法实现。这就是专用迁移工具派上用场的地方。它们可以让您清晰地应用更改并在必要时撤销它们。

我们该如何解决?使用正确的工具

每种语言和生态系统都有自己的迁移工具:

  • 对于Java,常见的有LiquibaseFlyway
  • 对于Go,一个常见选择是goose(我们将在这里介绍)。
  • 等等。

Goose:它是什么以及为什么有用

Goose是一个轻量级的Go实用工具,可帮助您自动管理迁移。它提供:

  • 简单性。最小依赖关系和迁移的透明文件结构。
  • 多功能性。支持各种数据库驱动程序(PostgreSQL、MySQL、SQLite等)。
  • 灵活性。可以使用SQL或Go代码编写迁移。

安装Goose

Shell

 

它是如何運作的:遷移結構

默認情況下,Goose會在db/migrations目錄中尋找遷移文件。每個遷移文件都遵循這個格式:

Shell

 

  • NNN是遷移編號(例如:001002,等等)。
  • 之後,您可以使用任何描述性名稱,例如init_schema
  • 擴展名可以是.sql.go

SQL遷移的示例

文件:001_init_schema.sql

SQL

 

我們的第一個示例

更改列類型(字符串→整數)

假設我們有一個帶有類型VARCHAR(255)users表中的age列。現在我們想將其更改為INTEGER。這是遷移可能看起來像的地方(文件005_change_column_type.sql):

SQL

 

這裡發生了什麼:

  1. 向上遷移

    • 我們將age列更改為INTEGERUSING (age::INTEGER)子句告訴PostgreSQL如何將現有數據轉換為新類型。
    • 請注意,如果age中有任何非數字數據,此遷移將失敗。在這種情況下,您將需要一種更複雜的策略(請參見下文)。
  2. 回退遷移

    • 如果我們回退,將 age 恢復為 VARCHAR(255)
    • 我們再次使用 USING (age::TEXT)INTEGER 轉換回文本。

第二種和複雜情況:多步遷移

如果 age 列可能包含混亂數據(不僅僅是數字),則安全起見,最好分幾個步驟執行:

  1. 添加一個新的列 (age_int),類型為 INTEGER
  2. 將有效數據複製到新列中,處理或刪除無效條目。
  3. 刪除舊列。
SQL

 

為了允許正確的回退,Down 部分只是反向鏡像操作。

自動化是關鍵

為了節省時間,將遷移命令添加到 Makefile(或任何其他構建系統)中非常方便。以下是一個包含主要 Goose 命令的示例 Makefile 用於 PostgreSQL

假設:

  • 數據庫的 DSN 為 postgres://user:password@localhost:5432/dbname?sslmode=disable
  • 遷移文件位於db/migrations
Shell

 

如何使用?

1. 創建新的遷移(SQL 文件)。這將生成一個文件db/migrations/002_add_orders_table.sql

Shell

 

2. 應用所有遷移。Goose 將在您的數據庫中創建一個schema_migrations表(如果尚不存在),並按升序應用任何新的遷移。

Shell

 

3. 回滾最後一個遷移。只回滾最後一個。

Shell

 

4. 回滾所有遷移(在生產環境中謹慎使用)。完全重置。

Shell

 

5. 檢查遷移狀態

Shell

 

輸出示例:

Shell

 

總結

通過使用遷移工具和 Makefile,我們可以:

  1. 限制對生產數據庫的直接訪問,僅通過遷移進行更改。
  2. 輕鬆跟踪數據庫版本並在出現問題時回滾它們。
  3. 保持單一、一致的數據庫變更歷史。
  4. 執行“平滑”的遷移,不會在微服務世界中破壞正在運行的生產環境。
  5. 獲得額外的驗證 — 每個更改都將通過 PR 和代碼審查流程(假設您已經設置了這些設置)。

另一個優勢是很容易將所有這些命令集成到您的 CI/CD 流水線中。請記住 — 安全高於一切。 

例如:

YAML

 

結論和提示

這些主要觀念非常簡單:

  • 保持遷移小而頻繁。這樣更容易審查、測試,並在需要時回滾。
  • 在所有環境中使用相同的工具,這樣開發、測試和生產環境就能保持同步。
  • 將遷移整合到CI/CD中,這樣您就不會依賴任何人手動運行它們。

這樣一來,您將擁有一個可靠且受控的流程來更改您的數據庫結構 — 這不會影響生產環境,並且讓您在出現問題時能夠快速響應。

祝您在遷移中好運!

感謝您的閱讀!

Source:
https://dzone.com/articles/goose-as-crucial-tool-for-your-service