一架梯子,一头程序猿,仰望星空!

Atlas 数据库版本管理

一款编程语言无关、支持多种数据库、适用于DevOps原则的数据库版本管理工具。

1. Atlas简介

atlas

Atlas 是一款独立于语言的工具,专门用于管理和迁移数据库表结构定义,并采用现代 DevOps 原则进行操作。它提供了两种工作流程:

  • 声明式:类似于 Terraform,Atlas 会将数据库的当前状态与所需状态进行比较,而所需状态是通过 HCL、SQL 或 ORM 架构定义的。基于这一比较,它将生成并执行迁移计划,将数据库过渡到其期望状态。
  • 版本化:与其他工具不同,Atlas 为你自动规划架构迁移。用户可以在 HCL、SQL 或他们选择的 ORM 中描述其期望的数据库架构,并通过使用 Atlas,规划、检查并将必要的迁移应用到数据库。

Atlas 的关键优势在于其简化了数据库管理的复杂性,使之变得易于版本控制、合作和实施。

2. 安装Atlas

在开始利用 Atlas 来管理数据库版本之前,我们需要进行安装。下面将介绍不同平台上的安装步骤。

2.1 macOS + Linux安装

在 macOS 或 Linux 系统上,可以通过以下命令行下载和安装 Atlas 的最新版本:

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

此命令将自动检测操作系统版本,下载适合的构建版本,并将 Atlas 二进制文件放置在可执行路径中。

2.2 通过Homebrew安装

如果你使用 macOS 并且已经安装了 Homebrew 包管理器,安装 Atlas 只需要执行简单的命令:

brew install ariga/tap/atlas

这将从 Homebrew 的仓库中获取最新版本的 Atlas,并进行安装。

2.3 Docker安装

通过 Docker 安装和运行 Atlas 是一种快速且便捷的方式,尤其是对于临时的测试或者不希望在主机系统上安装额外软件的用户。

首先,拉取 Atlas 的 Docker 镜像:

docker pull arigaio/atlas

接着,可以运行一个帮助命令来确认安装成功:

docker run --rm arigaio/atlas --help

如果需要容器可以访问主机网络或者本地目录,使用 --net=host 标志并挂载需要的目录:

docker run --rm --net=host \
  -v $(pwd)/migrations:/migrations \
  arigaio/atlas migrate apply \
  --url "mysql://root:pass@:3306/test"

2.4 Windows安装

下载二进制文件,https://release.ariga.io/atlas/atlas-windows-amd64-latest.exe , 把安装路径添加系统PATH环境变量即可。

3. 利用Atlas导出现有数据库表结构

Atlas 提供了 atlas schema inspect 命令,可以用来导出现有数据库的结构。此命令支持从数据库 URL 中读取数据库描述,并输出为三种不同的格式:默认的 Atlas HCL 格式、SQL 格式和 JSON 格式。在本指南中,我们将展示如何使用 Atlas HCL 和 SQL 格式,因为 JSON 格式通常用于使用 jq 处理输出。

检查本地运行的 MySQL 实例,并将输出写入名为 schema.hcl 的文件:

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

打开 schema.hcl 文件,查看描述数据库的 Atlas 表结构定义(HCL是Atlas定义的一种数据库无关的表结构配置格式)。例如,该文件将包含以下内容:

table "users" {
  schema = schema.example
  column "id" {
    null = false
    type = int
  }
  column "name" {
    null = true
    type = varchar(100)
  }
  primary_key {
    columns = [column.id]
  }
}

此代码块代表一个具有 idname 列的表表结构。schema 字段引用了定义在本文档其他地方的 example 模型定义。此外,primary_key 子块为表定义了 id 列作为主键。Atlas 力图模仿用户正在操作的数据库的语法。在这个例子中,id 列的类型为 int,而 name 列的类型为 varchar(100)

同样,为了导出数据库的 SQL 模型定义,你可以使用以下命令:

atlas schema inspect -u "mysql://root:pass@localhost:3306/example" --format '{{ sql . }}' > schema.sql

打开 schema.sql 文件,查看描述数据库的 SQL ,通常就是包含一些建表语句。

通过这种方式,可以方便地了解现有数据库的表结构细节,并为后续的版本化迁移提供准确的参考。

4.1 Declarative工作流程

Atlas的Declarative工作流程允许用户声明式地定义数据库所需的最终状态。用户只需描述他们希望数据库结构的终态是什么样子,Atlas工具会自动生成并执行迁移计划,以使数据库架构从当前状态安全地过渡到这一期望状态。

下面是如何使用Declarative工作流程来定义并达到期望的数据库状态:

4.1.1 定义目标表结构

首先,需要创建一个定义期望数据库结构的文件,可以选择HCL、SQL或ORM(对象关系映射)格式。

以HCL格式为例,定义一个新的blog_posts表:

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]
  }
}

提示:后面章节会单独介绍HCL语法格式。

4.1.2 使用Atlas工具执行迁移

在完成了数据库表结构的定义后,就可以使用Atlas的schema apply命令来执行迁移。

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

执行上述命令后,Atlas会比较现有数据库的架构和文件中定义的架构,生成一个迁移计划,并询问用户是否执行。用户确认执行计划后,Atlas会对数据库执行迁移,将其更新到期望的状态。

4.2 Versioned工作流程

Versioned工作流程是Atlas支持的另一种使用模式,有时被称为“基于变更的迁移”。它适合于数据库架构变更需要经过版本控制并在代码审核过程中进行审查的场景。

Versioned工作流程的步骤包括:

4.2.1 计算差异

在开始迁移之前,需要对当前的数据库结构和期望的状态进行比较,确定两者之间的差异。这可以通过运行atlas migrate diff命令来完成。

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

--dir指定迁移文件夹的URL,默认为file://migrations--to指定期望状态的URL(例如:你的开发环境数据库),--dev-url提供一个用于计算差异的开发数据库的URL(注意这个--dev-url需要指定一个空数据库,atlas借助这个空数据库计算差异)。

提示:如果你希望生成sql文件,参考前面章节通过--format参数设置格式。

4.2.2 应用迁移变更

完成差异计算后,Atlas将生成两个迁移文件保存在migrations文件夹。例如,如果生成的格式选择SQL, 则diff命令生成的文件,类似下面的SQL文件,包含了创建新表的迁移命令:

-- create "blog_posts" table
CREATE TABLE `blog_posts` (
  `id` int NOT NULL,
  `title` varchar(100) DEFAULT NULL,
  `body` text DEFAULT NULL,
  `author_id` int NULL REFERENCES `users`(id),
  PRIMARY KEY (`id`)
);

生成迁移文件后,可以使用版本控制工具(如Git)管理这些变更,这种方式可以做到开发环境修改了很多数据库表结构,等到要发版的时候,通过atlas命令比对开发环境和UAT环境生成数据库表结构迁移文件,把迁移文件放到UAT环境、生产环境分别执行,升级数据库即可。

这两种工作流程,Declarative和Versioned,为不同的开发和部署模式提供了灵活性,让团队可以选择最适合他们项目需求的方法来管理数据库架构的变更。

5. HCL 格式说明

5.1 简介

HCL是一种用于描述数据库表结构定义的声明性语言,Atlas 使用 HCL 格式编写数据库模式,提供了丰富的结构来描述数据库的不同方面。HCL的优势在于可读性好且易于维护,同时也支持变量注入和注解附加等特性。

提示:如果你开发的项目需要适配多个数据库,采用hcl这种数据库无关的方式,描述表结构会非常方便。

5.2 schema 对象

schema 对象用来描述一个数据库模式。在 MySQL 和 SQLite 中代表 DATABASE,在 PostgreSQL 中代表 SCHEMA。一个 HCL 文件可以包含一个或多个 schema 对象。

schema "public" {
  comment = "一个 schema 注释"
}

schema "private" {}

5.3 table 对象

table 对象用于描述 SQL 数据库中的表,它包含列、索引、约束以及其他各种由不同数据库驱动支持的额外属性。

table "users" {
  schema = schema.public
  column "id" {
    type = int
  }
  column "name" {
    type = varchar(255)
  }
  column "manager_id" {
    type = int
  }
  primary_key {
    columns = [
      column.id
    ]
  }
  index "idx_name" {
    columns = [
      column.name
    ]
    unique = true
  }
  foreign_key "manager_fk" {
    columns     = [column.manager_id]
    ref_columns = [table.users.column.id]
    on_delete   = CASCADE
    on_update   = NO_ACTION
  }
}

5.4 column 对象

columntable 的子资源,用于定义表中的列。

column "name" {
  type = text
  null = false
}

column "age" {
  type = integer
  default = 42
}

column "active" {
  type = tinyint(1)
  default = true
}

5.5 primary_key 对象

primary_keytable 的子资源,定义了表的主键。

primary_key {
  columns = [column.id]
}

5.6 foreign_key 对象

foreign_keytable 的子资源。这些对象定义了一些列,作为对其他表中列的引用。

table "orders" {
  schema = schema.market
  // ...
  column "owner_id" {
    type = integer
  }
  foreign_key "owner_id" {
    columns     = [column.owner_id]
    ref_columns = [table.users.column.id]
    on_update   = NO_ACTION
    on_delete   = NO_ACTION
  }
}

5.7 index 对象

index 对象代表表上的索引。

index "idx_name" {
  columns = [
    column.name
  ]
  unique = true
}

章节目录