在 DevOps 的世界中,”基础架构即代码”(Infrastructure as Code,IaC)作为一种定义基础设施的方式,已经成为一种被广泛接受的理念。通过 IaC,基础架构可以在配置文件中定义,并与编排工具结合自动部署和配置到你所选择的托管服务提供商中。
例如,以下代码片段可以通过 AWS Serverless Application Model (SAM) CLI 部署一个 Lambda 函数到 AWS,并配置一个 API Gateway 实例通过 HTTP 执行该函数:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-go-sample

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello-world/
      Handler: hello-world
      Runtime: go1.x
      Events:
        CatchAll:
          Type: Api
          Properties:
            Path: /hello
            Method: GET

上面的操作如果手动完成,虽然不会过于复杂,但显然需要比通过简单 CLI 命令部署这个配置文件的方式耗费更多时间。而且这个示例还相当简单,试想一下,如果需要配置和部署 20 个 Lambda 函数,手动操作将需要非常多的努力!

声明式 SQL 架构

类似于 IaC 工具,有几个工具可以以非常相似的方式管理你的数据库架构。这些工具允许你在特定格式的文件中定义 SQL 架构,然后简单使用 CLI 应用修改。例如,以下文件可以用于 Atlas CLI 定义架构:

table "hotels" {
  schema = schema.hotels_db
  column "id" {
    null           = false
    type           = int
    unsigned       = true
    auto_increment = true
  }
  column "name" {
    null = false
    type = varchar(50)
  }
  column "address" {
    null = false
    type = varchar(50)
  }
  primary_key {
    columns = [column.id]
  }
}
schema "hotels_db" {
  charset = "utf8mb4"
  collate = "utf8mb4_0900_ai_ci"
}

对架构进行修改也非常简单,只需调整文件并应用修改即可:

table "hotels" {
  schema = schema.hotels_db
  column "id" {
    null           = false
    type           = int
    unsigned       = true
    auto_increment = true
  }
  column "name" {
    null = false
    type = varchar(50)
  }
  column "address" {
    null = false
    type = varchar(50)
  }
  # 添加了 "stars" 列。
  column "stars" {
    null     = true
    type     = float
    unsigned = true
  }
  primary_key {
    columns = [column.id]
  }
}
schema "hotels_db" {
  charset = "utf8mb4"
  collate = "utf8mb4_0900_ai_ci"
}

声明式方法的优势

使用声明式方法管理架构迁移有以下几个主要好处:

  1. 单一真实来源(Single Source of Truth):这种方法符合 DevOps 鼓励的单一真实来源理念,其中主文件作为架构管理的唯一来源。
  2. 对开发者更友好:与版本化迁移相比,这种方法对开发者来说更容易理解。此外,它可能免除学习 DDL(用于定义 SQL 架构的语言)的需求。这对尚未熟悉 SQL 的开发者来说大大降低了学习门槛。
  3. 自动化更简单:应用更改的过程可以简单实现自动化,因为许多 CLI 工具是可以进行脚本化的。这使得将架构升级过程集成到持续部署工具中变得容易。

此策略的缺陷

虽然通过这种方法可以免除学习 DDL 的需求,但工具用来规避学习过程可能会让开发者形成依赖性。
此外,冲突的架构定义 也是需要注意的问题。考虑当多个开发者分别在不同的机器上修改架构定义文件时,一些开发者的更改可能会覆盖其他人的变更,从而引发关于数据库架构应该是什么的冲突。
需要特别注意的是,数据库本质上是有状态的,其中存储的数据和数据库的结构同样重要。因此,在应用修改时需要谨慎,以避免架构迁移导致意想不到的结果。

如何在 PlanetScale 中使用声明式迁移

PlanetScale 的数据库分支流本身就是一种架构迁移形式。在 PlanetScale 中修改数据库时,开发者通常会创建一个生产数据库分支的工作分支,以进行更改。
在 PlanetScale 中的一个最佳实践是启用安全迁移,以防止对数据库架构的意外修改。由于这些分支限制了 DDL 的使用(这些工具最终依赖于 DDL 进行修改),开发者应在开发分支中使用这些工具进行架构管理。
一个可能的团队策略是每次代码需要修改时开启一个新分支,通常在开发周期的开始。当需要对架构进行修改时,可以使用一个专门的代码仓库(我们可以称之为 db 仓库)供开发者检查对定义文件的变更。自动化工具可以监控 db 仓库中的更改,将架构更改应用到活跃的开发分支,并通知开发团队以便他们采取相应行动。
当需要将变更应用到生产数据库分支中时,可以使用部署请求(deploy requests)审查并应用变更,随后部署最新版本。



声明式架构迁移插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:http://folen.top/2025/09/13/declarative-shcema/