Atlas数据库模式管理最佳实践Skill atlas-best-practices

Atlas数据库模式管理最佳实践指南,涵盖声明式和版本化迁移、HCL/SQL模式定义、代码检查、测试和项目配置。关键词:Atlas,数据库迁移,模式管理,DevOps,CI/CD,SQL,HCL,版本控制,声明式,代码检查,测试。

DevOps 0 次安装 43 次浏览 更新于 2/23/2026

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 diffschema apply;它安全地验证模式。
  • 在CI中启用严格代码检查,及早捕获破坏性和数据依赖的变更。
  • 生产环境使用版本化迁移;声明式工作流适用于开发/测试。
  • 使用.test.hcl文件测试模式;验证约束、触发器和函数。
  • 将迁移推送到Atlas注册表进行部署;避免手动复制文件。
  • 对PostgreSQL并发索引操作使用-- atlas:txmode none
  • 在代码检查规则中配置命名约定;一致性防止错误。