Skip to content

DB Migration ​

解决什么问题:schema 演化是状态变更——手动 ALTER 是生产事故的最大来源。迁移工具让 schema 变更可版本化、可回滚、可审计。

它是什么 ​

DB Migration(数据库迁移) = 用版本化脚本管理 schema 变更的工具链——

  • 每个迁移是一个文件(V001__create_orders.sql / V002__add_index.sql)
  • 迁移有序执行,有 checksum 校验
  • 工具:Flyway(Java 主流)/Liquibase(XML/YAML)/Alembic(Python)/Sqitch

SE@G Ch 7:"Schema migrations must be versioned, tested, and reversible when possible."

V2 视角(V2.7 B7 演化):schema = 系统的状态。迁移 = 状态空间的安全导航——必须可前进、可回退、可审计。

关键属性 ​

属性值/含义
形式顺序版本脚本(V001 / V002 / ...)
执行时机应用启动前 / CI 流水线 / 独立 job
回滚策略补偿迁移(V001_UP / V001_DOWN)/ 蓝绿迁移
关键原则前向兼容 + 向后兼容(deploy 时新旧版本共存)
反模式手动 ALTER / 不在 CI 跑 / 迁移无校验
核心约束每次迁移必须可逆 或 显式声明不可逆(删字段)
判错标准prod 改 schema 需要 DBA 手动执行 = 迁移失效

怎么用 ​

场景 1:Flyway 迁移(Java) ​

sql
-- src/main/resources/db/migration/V001__create_orders.sql
CREATE TABLE orders (
    id BIGSERIAL PRIMARY KEY,
    customer_id BIGINT NOT NULL,
    status VARCHAR(32) NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_orders_customer ON orders(customer_id);

-- V002__add_total_amount.sql
ALTER TABLE orders ADD COLUMN total_amount NUMERIC(19, 2);

应用启动:Flyway 自动检查 flyway_schema_history 表 → 跑未执行的迁移。

场景 2:零停机迁移(Expand-Contract) ​

问题:删除列 ALTER TABLE orders DROP COLUMN old_field 会让旧版应用崩溃。

解法:Expand-Contract 三步走

  1. Expand:新代码写双份(新旧字段都写)
  2. Migrate:回填旧数据 → 切读 → 切写
  3. Contract:确认无旧引用 → DROP COLUMN

V2 B7 视角:Expand-Contract = 演化中的安全过渡——永远保持前进方向可回退。

场景 3:迁移测试 ​

测试必须包含迁移:

java
@Test
void migration_V002_addsTotalAmount() {
    // 启动 H2 / Testcontainers
    // 跑迁移 V001 → V002
    // 断言 total_amount 列存在
    assertTrue(schema.columnExists("orders", "total_amount"));
}

V2 B5 视角:迁移测试 = 演化的反馈——上线前发现 schema 问题。

常见误区 ​

  1. "迁移 = 一次性脚本"——错。迁移是永久资产——上线后必须保留,不可删除
  2. "迁移不需要测试"——错。迁移 bug = 全站宕机。迁移必须有测试覆盖
  3. "先 DROP 再 ADD"——错。DROP 不可逆——必须 Expand-Contract
  4. "应用启动跑迁移"——对但要小心——多实例同时启动 = 竞争条件——用 Flyway lock / 独立 job
  5. "迁移工具 = 数据库无关"——半错。Flyway 部分数据库支持有限——大型迁移要 native + 工具结合

关键洞察 ​

DB Migration 是"schema 演化的安全导航"——可前进、可回退、可审计 = 控制论意义上的状态可控。

控制论视角:schema = 系统状态空间;迁移 = 状态空间的合法转移函数。没有合法转移 = 系统失稳。 IDDD Ch 12 视角:聚合的持久化 schema 是领域模型的物理映射——schema 演化 = 领域演化。 SE@G Ch 7 视角:Google 的 migration 必须经过 审查 + 灰度 + 监控——三者缺一不可。 EDM Ch 6 视角:事件 schema 演进和 DB schema 演进有相同原则——前向/后向兼容 + 版本化。

相关链接 ​

从名家方法论与工程化思路中蒸馏出自己的工程体系。