Atlas: Schema-As-Code

Jeff Yen
8 min readAug 22, 2024

--

123

Atlas 是一個獨立於語言的工具,用於使用現代 DevOps 原則來管理和遷移資料庫架構。它提供了兩種工作流程:

  1. 宣告式:類似於 Terraform,Atlas 將當前的資料庫狀態與 HCL、SQL 或 ORM 架構中定義的期望狀態進行比較。根據這一比較,它會生成並執行一個遷移計劃,以將資料庫轉換為所需的狀態。
  2. 版本化:與其他工具不同,Atlas 會自動為您規劃架構遷移。用戶可以在 HCL、SQL 或他們選擇的 ORM 中描述他們期望的資料庫架構,通過使用 Atlas,他們可以規劃、檢查並應用必要的遷移到資料庫。

要下載並安裝 Atlas CLI 的最新版本

curl -sSf https://atlasgo.sh | sh

Start a local database container

在本指南中,我們將啟動一個執行 MySQL 的本地 Docker 容器。

docker run --rm -d --name atlas-demo -p 3306:3306 -e MYSQL_ROOT_PASSWORD=pass -e MYSQL_DATABASE=example mysql

在這個範例中,我們將從一個表示使用者表的資料結構開始,其中每個使用者都有一個 ID 和一個名稱:

CREATE table users (
id int PRIMARY KEY,
name varchar(100)
);

要在本地資料庫中建立上述的表格,可以執行以下命令:

docker exec atlas-demo mysql -ppass -e 'CREATE table example.users(id int PRIMARY KEY, name varchar(100))'

Inspecting our database

atlas schema inspect 命令支援從指定的資料庫 URL 讀取資料庫描述,並以三種不同的格式輸出:Atlas DDL(預設)、SQL 和 JSON。在本指南中,我們將演示使用 Atlas DDL 和 SQL 格式的流程,因為 JSON 格式通常用於使用 jq 進行輸出處理。

Atlas DDL(HCL)

要檢查本地執行的 MySQL 實例,可以使用 -u 標誌,並將輸出寫入名為 schema.hcl 的檔案中:

atlas schema inspect -u "mysql://root:pass@localhost:3306/example" > schema.hcl

這個區塊代表了一個包含 idname 欄位的資料表資源。schema 欄位引用了本文檔其他部分定義的 example 架構。此外,primary_key 子區塊將 id 欄位定義為該表的主鍵。Atlas 力求模仿使用者正在操作的資料庫語法。在這個例子中,id 欄位的類型是 int,而 name 欄位的類型是 varchar(100)

現在,假設我們想要添加一個 blog_posts 表,並讓我們的架構表示一個簡化的部落格系統。

修改schema.hcl 文件的當前內容,添加的 table 區塊內容.

table "blog_posts" {
schema = schema.example
column "id" {
null = false
type = int
}
column "title" {
null = true
type = varchar(100)
}
column "body" {
null = true
type = text
}
column "author_id" {
null = true
type = int
}
primary_key {
columns = [column.id]
}
foreign_key "author_fk" {
columns = [column.author_id]
ref_columns = [table.users.column.id]
}
}

除了我們在 users 表中看到的元素外,這裡我們還可以找到一個外鍵區塊,宣告 author_id 欄位引用了 users 表中的 id 欄位。

現在,讓我們通過執行遷移來應用這些變更。在 Atlas 中,遷移可以在兩種工作流程中應用:宣告式和版本式。

Declarative Migrations

宣告式方法要求使用者定義所需的最終架構,Atlas 提供了一種安全的方法來更改資料庫以達到這個目標。讓我們來看看實際操作。

繼續這個範例,為了將變更應用到我們的資料庫中,我們將執行 apply 指令:

atlas schema apply \
-u "mysql://root:pass@localhost:3306/example" \
--to file://schema.hcl

Atlas 透過顯示 SQL 語句來呈現它所生成的計劃。例如,對於 MySQL 資料庫,我們將看到如下內容:

Apply!!,這樣就完成了宣告式遷移!

docker exec -it atlas-demo mysql -u root -p
mysql> USE example;
mysql> SHOW TABLES;
mysql> DESCRIBE blog_posts;

為了確保變更已經應用到架構中,你可以再次執行 inspect 指令。這次,我們使用 --web-w 標誌來打開 Atlas Web UI 以查看架構。

atlas schema inspect \
-u "mysql://root:pass@localhost:3306/example" \
--web

Versioned Migrations

另一方面,版本化遷移工作流程(有時稱為「change-based migrations”」)允許將數據庫架構的每一項變更都提交到源代碼控制中,並在代碼審查期間進行檢視。用戶仍然可以受益於 Atlas 智能規劃的遷移,但這些遷移不會自動應用。

首先,我們將通過運行atlas migrate diff命令來計算數據庫的理想狀態和當前狀態之間的差異。

要運行此命令,我們需要提供以下必要參數:

-dir遷移目錄的 URL,默認為 file://migrations。
-to理想狀態的 URL。可以使用數據庫 URL、HCL 或 SQL 架構,或另一個遷移目錄來指定狀態。
-dev-url用於計算差異的開發數據庫的 URL。

atlas migrate diff create_blog_posts \
--dir "file://migrations" \
--to "file://schema.hcl" \
--dev-url "docker://mysql/8/example"

運行 ls migrations 命令時,你會看到 Atlas 在 migrations 目錄中創建了兩個文件。通常,這兩個文件可能是:

  1. 一個 SQL 文件:這個文件包含了實際的數據庫變更命令。文件名通常包括一個時間戳和一個描述性的名稱,例如 “20230822120000_initial_schema.sql”。
  2. 一個 Atlas 元數據文件:這個文件通常以 “.atlas.sum” 結尾,包含了關於遷移的元數據信息。例如,它可能叫做 “atlas.sum”。

這兩個文件共同定義了一個數據庫遷移步驟。SQL 文件包含了要執行的實際更改,而元數據文件則幫助 Atlas 跟踪已應用的遷移和維護遷移的完整性。

現在我們已經準備好了遷移文件,您可以使用 migrate apply 命令將更改應用到資料庫。我會下一篇講解如何 Versioned Migrations Quickstart Guide

--

--