name: atlas最佳实践 description: Atlas数据库模式管理的最佳实践模式,涵盖HCL/SQL模式定义、版本化和声明式迁移、代码检查分析器、测试和项目配置。适用于处理atlas.hcl、.hcl模式文件、Atlas CLI命令或数据库迁移时使用。
Atlas最佳实践
Atlas是一个语言无关的工具,用于使用声明式或版本化工作流管理数据库模式。
两种工作流
声明式(类似Terraform): Atlas比较当前状态与期望状态,并自动生成迁移。
atlas schema apply --url "postgres://..." --to "file://schema.hcl" --dev-url "docker://postgres/15"
版本化: Atlas从模式变更生成迁移文件,存储在版本控制中。
atlas migrate diff add_users --dir "file://migrations" --to "file://schema.sql" --dev-url "docker://postgres/15"
atlas migrate apply --dir "file://migrations" --url "postgres://..."
开发数据库
Atlas需要一个开发数据库用于模式验证、差异比较和代码检查。使用docker驱动创建临时容器:
# PostgreSQL
--dev-url "docker://postgres/15/dev?search_path=public"
# MySQL
--dev-url "docker://mysql/8/dev"
# SQLite
--dev-url "sqlite://dev?mode=memory"
模式即代码
HCL模式(推荐)
使用数据库特定的文件扩展名以获得编辑器支持:.pg.hcl(PostgreSQL)、.my.hcl(MySQL)、.lt.hcl(SQLite)。
schema "public" {
comment = "应用模式"
}
table "users" {
schema = schema.public
column "id" {
type = bigint
}
column "email" {
type = varchar(255)
null = false
}
column "created_at" {
type = timestamptz
default = sql("now()")
}
primary_key {
columns = [column.id]
}
index "idx_users_email" {
columns = [column.email]
unique = true
}
}
table "orders" {
schema = schema.public
column "id" {
type = bigint
}
column "user_id" {
type = bigint
null = false
}
column "total" {
type = numeric
null = false
}
foreign_key "fk_user" {
columns = [column.user_id]
ref_columns = [table.users.column.id]
on_delete = CASCADE
}
check "positive_total" {
expr = "total > 0"
}
}
SQL模式
使用标准SQL DDL文件:
CREATE TABLE "users" (
"id" bigint PRIMARY KEY,
"email" varchar(255) NOT NULL UNIQUE,
"created_at" timestamptz DEFAULT now()
);
项目配置
创建atlas.hcl用于环境配置:
variable "db_url" {
type = string
}
env "local" {
src = "file://schema.pg.hcl"
url = var.db_url
dev = "docker://postgres/15/dev?search_path=public"
migration {
dir = "file://migrations"
}
format {
migrate {
diff = "{{ sql . \" \" }}"
}
}
}
env "prod" {
src = "file://schema.pg.hcl"
url = var.db_url
migration {
dir = "atlas://myapp" # Atlas注册表
}
}
使用环境运行:
atlas schema apply --env local --var "db_url=postgres://..."
迁移代码检查
Atlas分析迁移的安全性。在atlas.hcl中配置:
lint {
destructive {
error = true # 在DROP TABLE/COLUMN时失败
}
data_depend {
error = true # 在数据依赖变更时失败
}
naming {
match = "^[a-z_]+$"
message = "必须为小写字母和下划线"
index {
match = "^idx_"
message = "索引必须以idx_开头"
}
}
# PostgreSQL:要求索引使用CONCURRENTLY(Pro版)
concurrent_index {
error = true
}
}
关键分析器:
- DS:破坏性变更(DROP SCHEMA/TABLE/COLUMN)
- MF:数据依赖变更(ADD UNIQUE,NOT NULL)
- BC:向后不兼容(重命名表/列)
- PG(Pro版):并发索引,阻塞DDL
检查迁移:
atlas migrate lint --env local --latest 1
在迁移文件中抑制特定检查:
-- atlas:nolint destructive
DROP TABLE old_users;
模式测试
在.test.hcl文件中编写测试:
test "schema" "user_constraints" {
parallel = true
exec {
sql = "INSERT INTO users (id, email) VALUES (1, 'test@example.com')"
}
# 测试唯一约束
catch {
sql = "INSERT INTO users (id, email) VALUES (2, 'test@example.com')"
error = "duplicate key"
}
assert {
sql = "SELECT COUNT(*) = 1 FROM users"
error_message = "预期恰好有一个用户"
}
cleanup {
sql = "DELETE FROM users"
}
}
# 表驱动测试
test "schema" "email_validation" {
for_each = [
{input: "valid@test.com", valid: true},
{input: "invalid", valid: false},
]
exec {
sql = "SELECT validate_email('${each.value.input}')"
output = each.value.valid ? "t" : "f"
}
}
运行测试:
atlas schema test --env local schema.test.hcl
事务模式
使用指令控制每个文件的事务行为:
-- atlas:txmode none
CREATE INDEX CONCURRENTLY idx_users_email ON users (email);
模式:file(默认,每个文件一个事务)、all(所有文件一个事务)、none(无事务)。
预执行检查(Pro版)
在atlas.hcl中阻止危险操作(需要Atlas Pro版):
env "prod" {
check "migrate_apply" {
deny "too_many_files" {
condition = length(self.planned_migration.files) > 3
message = "不能一次应用超过3个迁移"
}
}
}
常用命令
# 从模式差异生成迁移
atlas migrate diff migration_name --env local
# 应用待处理的迁移
atlas migrate apply --env local
# 验证迁移目录完整性
atlas migrate validate --env local
# 查看迁移状态
atlas migrate status --env local
# 推送到Atlas注册表
atlas migrate push myapp --env local
# 声明式应用(无迁移文件)
atlas schema apply --env local --auto-approve
# 检查当前数据库模式
atlas schema inspect --url "postgres://..." --format "{{ sql . }}"
# 比较模式
atlas schema diff --from "postgres://..." --to "file://schema.hcl"
CI/CD集成
GitHub Actions设置:
- uses: ariga/setup-atlas@v0
with:
cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
- name: 检查迁移
run: atlas migrate lint --env ci --git-base origin/main
现有数据库的基线
在现有数据库上采用Atlas时:
# 创建反映当前模式的基线迁移
atlas migrate diff baseline --env local --to "file://schema.hcl"
# 标记基线为已应用(跳过执行)
atlas migrate apply --env prod --baseline "20240101000000"
ORM集成
Atlas支持通过外部提供者从ORM加载模式:
data "external_schema" "gorm" {
program = [
"go", "run", "-mod=mod",
"ariga.io/atlas-provider-gorm",
"load", "--path", "./models",
"--dialect", "postgres",
]
}
env "local" {
src = data.external_schema.gorm.url
}
支持:GORM、Sequelize、TypeORM、Django、SQLAlchemy、Prisma等。
说明
- 始终使用开发数据库进行
migrate diff和schema apply;它安全地验证模式。 - 在CI中启用严格代码检查,及早捕获破坏性和数据依赖的变更。
- 生产环境使用版本化迁移;声明式工作流适用于开发/测试。
- 使用
.test.hcl文件测试模式;验证约束、触发器和函数。 - 将迁移推送到Atlas注册表进行部署;避免手动复制文件。
- 对PostgreSQL并发索引操作使用
-- atlas:txmode none。 - 在代码检查规则中配置命名约定;一致性防止错误。