Schema Migration — 数据库架构迁移的本质、类型和工具

作者: IT Sectr 发布日期: 2026-06-15 阅读时间: 10 分钟

Schema Migration 是在应用程序开发过程中对数据库结构变化进行版本化管理的过程。每个更改都通过脚本描述,并依次应用于 dev、staging 和 production 环境。根据 JetBrains(2025)的数据,78% 的团队使用架构迁移工具,而 34% 仍通过控制台手动修改数据库——这是架构差异的主要来源。迁移自动化消除了人为因素,并保证了环境之间结构的一致性。

要点

  • Schema Migration — 通过脚本对数据库结构进行版本化更改。
  • Flyway — 用于 Java/Kotlin 的工具,带有简单的 SQL 迁移脚本。
  • Liquibase — XML/YAML/JSON 格式,支持回滚。
  • Alembic — 用于 SQLAlchemy 的 Python 工具,支持自动生成。
  • 架构冲突 — 多个开发人员在无迁移情况下工作时的主要问题。

什么是 Schema Migration

Schema Migration 是通过版本化文件管理数据库结构变化的实践,这些文件依次应用于不同环境。每个文件包含一组 SQL 命令:创建表、添加列、更改索引或更新约束。迁移工具跟踪已应用的版本,并保证每个更改恰好执行一次。

与迁移表内容的 Data Migration 不同,Schema Migration 只管理结构——DDL 操作。这是根本区别:Schema Migration 在 Data Migration 之前运行,创建目标架构,然后 Data Migration 用数据填充它。根据 Redgate(2024)的数据,生产数据库中 62% 的事件与没有迁移脚本的手动架构更改有关。

迁移版本控制

每个 Schema Migration 都获得一个唯一标识符——通常是版本(V1、V2)或时间戳。该工具在特殊表(flyway_schema_history、alembic_version)中存储已应用迁移的列表。启动时,它将列表与 classpath 中的文件进行比较,并仅应用新的迁移。幂等性是关键特性:重新运行不会产生副作用。

架构更改的类型

典型的 Schema Migration 操作:创建表(CREATE TABLE)、添加列(ALTER TABLE ADD COLUMN)、更改类型、创建索引、添加外键和更新序列。更复杂的迁移包括保留数据的同时重命名列、将表拆分为多个部分以及将架构复制到分片。

为什么需要数据库架构迁移

如果没有 Schema Migration,开发人员会手动修改数据库——在控制台中编写 DDL,在 dev 环境中添加列,然后凭记忆将其复制到 staging。结果:环境之间的架构差异、部署时更改丢失以及生产环境中迁移损坏。Schema Migration 解决了三个关键问题:一致性、可再现性和审计。

环境之间的一致性

当数据库结构在代码中描述时,它在 dev、staging 和 production 中是相同的。开发人员无法忘记应用更改——该工具将依次执行所有遗漏的迁移。如果生产环境中缺少某列,但代码需要它——应用程序将出错崩溃。自动检查消除了这种情况。

新开发人员的可再现性

团队新成员运行 flyway migrate 命令,并在几秒钟内获得当前架构——无需生产环境转储和手动 DDL 查询。这在使用微服务架构时尤为重要,因为每个服务都有自己的数据库,架构由数十个迁移组成。完全可再现性将入职时间从几天缩短到几分钟。

更改审计

每个 Schema Migration 都存储在版本控制系统中,与应用程序代码一起。您可以打开 Pull Request,查看架构更改的精确 SQL 命令,并执行代码审查。发生事件时,可以轻松确定最后一个应用的迁移及其作者。Git 历史记录提供项目整个生命周期中数据库更改的完整轨迹。

架构迁移工具

市场上有数十种适用于不同语言和平台的 Schema Migration 工具。选择取决于技术栈、迁移描述格式和回滚要求。让我们看看主要类别和流行工具。

工具语言格式回滚
FlywayJava、Kotlin、ScalaSQL、Java通过单独脚本
LiquibaseJava、Groovy、KotlinXML、YAML、JSON、SQL内置回滚
AlembicPythonPython、SQL自动生成降级
Active RecordRubyRuby DSL通过还原
Entity FrameworkC#C# Fluent API自动生成

如何选择工具

对于 Java/Kotlin 技术栈 — Flyway 是最轻量级和最可预测的工具。对于需要频繁回滚的项目 — Liquibase,其架构内置了回滚功能。对于 Python/Django — Alembic 是 SQLAlchemy 的标准工具。对于没有 DevOps 工程师的初创公司 — 选择配置最少的工具:Flyway 只需要一个脚本文件和 migrate 命令。

商业解决方案

除了开源工具之外,还有商业解决方案:Redgate SQL Change Automation、Datical DB 和 DBmaestro。它们提供可视化架构比较、自动冲突解决和 CI/CD 管道集成。然而,对于大多数项目,FlywayAlembic 无需额外许可证即可覆盖 100% 的需求。

使用 Flyway 进行迁移

让我们看看 Kotlin 中使用 Flyway 进行 Schema Migration 的实际示例。让我们创建一个将 orders 表添加到 PostgreSQL 数据库的迁移。Flyway 会自动创建 flyway_schema_history 表并跟踪应用的版本。

sql
-- V1__Create_Orders_Table.sql
CREATE TABLE orders (
    id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id         UUID NOT NULL,
    total_amount    DECIMAL(10,2) NOT NULL,
    currency        VARCHAR(3) NOT NULL DEFAULT 'USD',
    status          VARCHAR(20) NOT NULL DEFAULT 'pending',
    created_at     TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id)
);

通过 dataSource 配置在 Kotlin 项目中连接 Flyway。配置后,flyway:migrate 命令将应用 classpath 中的所有新迁移。

kotlin
// FlywayConfig.kt — Spring Boot 中的 Flyway 配置
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.flywaydb.core.Flyway

@Configuration
class FlywayConfig {
    @Bean
    fun flyway(dataSource: DataSource): Flyway {
        return Flyway.configure()
            .dataSource(dataSource)
            .locations("classpath:db/migration")
            .baselineOnMigrate(true)
            .load()
    }
}

用于 Python 项目的 Alembic

Alembic 是用于 Python 的 Schema Migration 工具,构建在 SQLAlchemy 之上。其主要特性是基于 SQLAlchemy 模型与当前数据库架构的比较自动生成脚本。Alembic 适用于 Django、FastAPI 和 Flask 项目。

初始化和创建迁移

初始化(alembic init alembic)和配置连接字符串后,alembic revision --autogenerate 命令扫描 SQLAlchemy 模型并生成迁移脚本。开发人员只需检查生成的代码并通过 alembic upgrade head 应用它。Autogenerate 节省了手动编写 DDL 的时间。

python
# models.py — 用于自动生成的 SQLAlchemy 模型
from sqlalchemy import Column, Integer, String, DateTime, Enum
from sqlalchemy.orm import DeclarativeBase
import enum

class OrderStatus(enum.Enum):
    pending = "pending"
    paid = "paid"
    shipped = "shipped"

class Base(DeclarativeBase):
    pass

class Order(Base):
    __tablename__ = "orders"
    id = Column(Integer, primary_key=True)
    status = Column(Enum(OrderStatus), nullable=False)
    created_at = Column(DateTime, nullable=False)

架构迁移的最佳实践

经验丰富的团队制定了一套 Schema Migration 规则,可降低故障风险并简化调试。遵循这些实践是成熟工程文化的标志。五个关键规则涵盖迁移的设计、测试和部署。

一次迁移——一次更改

每个 Schema Migration 应只进行一次逻辑更改:创建表、添加列或更改索引。在单个迁移中混合多个操作会使回滚复杂化——如果第二个操作失败,第一个操作已应用且需要单独回滚。小步走是可靠迁移的基础。

绝不编辑已发布的迁移

迁移应用到生产环境后,不能修改——只能创建修复问题的新迁移。编辑已发布的迁移会破坏跟踪器:拥有不同数据库的开发人员将看到哈希不匹配。不可变迁移可保证在所有环境中具有可预测的行为。

在生产副本上测试

在生产环境中应用 Schema Migration 之前,在生产数据副本上执行它。目的是检查执行速度、表锁定情况和更改的正确性。对于大型表,ALTER TABLE 可能会阻塞写入数小时——测试将提前发现这一点。Staging 环境配合生产转储是强制步骤。

避免对新列使用 NOT NULL

没有默认值的 NOT NULL 新列是迁移失败的常见原因。在现有记录中,值将为 NULL,而 NOT NULL 会导致错误。最佳实践:创建具有默认值和 nullable 的列,然后在数据填充后通过单独的迁移添加 NOT NULL

常见问题

Schema Migration 和 Data Migration 有什么区别?

Schema Migration 管理数据库结构(表、列、索引),Data Migration 管理内容(行、文档)。Schema Migration 始终首先执行,创建目标架构,然后 Data Migration 用数据填充它。工具不同:Flyway 用于架构,ETL 用于数据。

新项目应该选择哪个架构迁移工具?

对于 Java/Kotlin — Flyway 是最简单和最快速的。对于 Python — Alembic,与 SQLAlchemy 集成。对于 .NET — Entity Framework Migrations。对于多语言项目 — Liquibase 具有独立的描述格式。

如何回滚 Schema Migration?

Flyway 不支持自动回滚 — 需要编写单独的取消脚本。Liquibase 自动为 XML/YAML 格式生成回滚。Alembic 为每次迁移创建降级函数。不可变方法用新迁移代替回滚是现代化实践。

如果生产环境中的迁移失败会怎样?

该工具将迁移标记为失败。数据库保持在其应用之前的状态(如果没有自动提交)。需要在新迁移中修复错误并重新运行。绝不编辑失败的迁移——创建新的迁移。

是否必须使用架构迁移工具?

对于生产项目——是的。Git 之外的手动 DDL 更改会导致架构差异、部署损坏和数据丢失。即使对于 MVP,也要使用最小工具——例如,带有几个 SQL 脚本的 Flyway。这在首次部署到 staging 时就会得到回报。

总结

  • Schema Migration — 通过 Git 中的脚本对数据库结构进行版本化更改。
  • 解决 dev、staging 和 production 环境之间的架构一致性问题。
  • Flyway — Java/Kotlin 的标准,Alembic — Python 的标准,Liquibase — 多语言项目的标准。
  • 一次迁移 = 一次更改。不要编辑已发布的迁移。
  • 在应用之前对生产数据副本测试迁移。
  • 创建具有默认值的 nullable 新列,通过单独迁移添加 NOT NULL
  • 用新迁移的不可变方法比旧迁移的自动回滚更可靠。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读