Schema 迁移 CI/CD(Flyway/Liquibase)
症状
目标:用带版本号的迁移文件管理数据库 schema 变更;在 CI/CD 中使用 Flyway 或 Liquibase 自动但可控地应用这些变更。
1. 创建带版本号的迁移文件(Vxxx__name.sql)
将每个 schema 变更写入一个带递增版本号的命名文件;Flyway 的约定是 V<version>__<description>.sql(例如 V1__initial_schemas.sql、V2__orders_table.sql)。这些文件保存在 Git 中,并按版本顺序应用。已应用的迁移会记录在跟踪表中(Flyway 中为 flyway_schema_history),因此每个迁移只运行一次。
PostgreSQL
-- V2__orders_table.sql
CREATE TABLE orders (
id bigserial PRIMARY KEY,
amount numeric(12,2) NOT NULL,
created_at timestamptz DEFAULT now()
);2. 用校验和保证不可变性
Flyway/Liquibase 会存储每个已应用迁移的校验和。若之后编辑已应用的文件,校验和将不再匹配,工具会报错。规则:切勿编辑已应用的迁移;用新的版本文件进行修正。这保证所有环境(dev/staging/prod)拥有相同的历史。
PostgreSQL
# repair on checksum mismatch (use with care):
flyway repair
# the right way: add the change in a new Vx file3. 为现有数据库设置基线(baseline)
将迁移工具接入已有数据但没有迁移历史的数据库时,使用 baseline;它将当前状态视为“起始版本”,不会尝试重新创建现有对象。baselineVersion 之后的迁移会被应用。在从零构建的环境中无需 baseline;迁移从 V1 开始运行。
PostgreSQL
flyway baseline -baselineVersion=1 -baselineDescription="existing schema"4. 在 CI 流水线中自动迁移
在 CI 步骤中运行迁移工具,将变更自动应用到测试和预发布数据库;migrate 命令只运行新的(未应用的)文件,且是幂等的。先将迁移应用到临时/一次性数据库并进行验证,可在有问题的 SQL 到达生产环境之前将其拦截。schema 必须在部署应用代码之前完成迁移(采用向后兼容的变更)。
PostgreSQL
# CI step (Flyway)
flyway -url=jdbc:postgresql://staging/appdb \
-user=ci -password=$PW migrateMySQL
flyway -url=jdbc:mysql://staging/appdb \
-user=ci -password=$PW migrate5. 为生产环境添加人工审批关卡
测试/预发布环境自动执行,但生产环境的 migrate 应要求人工审批;在 CI/CD 中添加“审批关卡”(人工审批)步骤。审批之前,用 'flyway info' 或 'liquibase status' 展示将要运行哪些迁移。应用到生产环境之前务必做一次新的备份,以便出问题时可以回退。
PostgreSQL
# what will run before approval?
flyway info
# liquibase equivalent:
liquibase status --verbose6. 定义可逆性和回退策略
Flyway Community 没有自动 undo;应采用只向前迁移的原则:不是撤销错误,而是编写一个新的迁移来修正它。Liquibase changeset 可以定义 rollback 块,并用 'liquibase rollback' 回退。最稳妥的策略:保持变更小而向后兼容,在高风险操作(删除列)之前做备份,并准备书面的回退方案。
PostgreSQL
-- Liquibase rollback example (inside a changeset)
--changeset dev:2
CREATE TABLE orders (...);
--rollback DROP TABLE orders;