后端如何做数据库版本迁移管理(Flyway/Liquibase)?
结论:后端数据库版本迁移用 Flyway 或 Liquibase,把每次 DDL/DML 变更写成带版本号、进 Git、随应用发布自动执行的脚本,核心纪律是「脚本只增不改、出错向前修复、生产环境永不禁用校验、永不执行 flyway clean」。
Flyway 和 Liquibase 有什么区别,该怎么选?
结论:纯 SQL 团队、追求简单可预测选 Flyway;需要多数据库兼容、自动回滚、按环境条件执行选 Liquibase。
Flyway 以原生 SQL 为主体,脚本命名 V1__init.sql、V2__add_user_index.sql(V 大写、双下划线分隔),按版本号顺序执行,只记录到 flyway_schema_history 表;社区版没有 undo 脚本,回滚要靠自己写反向 SQL(Teams 版才有 U2__xxx.sql)。
Liquibase 用 changelog(变更日志,一串 changeSet)描述变更,支持 XML/YAML/JSON/SQL 四种格式,记录表是 DATABASECHANGELOG,加锁表是 DATABASECHANGELOGLOCK。它支持 context、label 做条件执行,XML/YAML 写的 changeSet 可自动生成回滚语句,写原生 SQL 的 changeSet 必须手写 rollback。
迁移脚本的目录和命名规范怎么定?
结论:版本号全局唯一、单调递增,禁止改历史脚本,一个脚本只做一类变更。
Flyway 默认扫描 classpath:db/migration,Liquibase 默认入口 classpath:db/changelog/db.changelog-master.yaml。推荐按 V{版本}__{动词}_{对象}.sql 命名,例如 V20240901__create_order_table.sql。历史脚本一旦合并进主干就不能再改——Flyway 会把内容算成 checksum(校验和),改了会在启动时报 Migration checksum mismatch;Liquibase 同理,只能通过 validCheckSum 打补丁,属于下策。
DDL(建表改表)和 DML(数据订正)分开写两个脚本,数据订正脚本要写成可重复执行的幂等语句,避免重跑二次插入。
Spring Boot 里怎么接 Flyway?
结论:加依赖 + 放脚本 + 三行配置就能跑,注意 Spring Boot 3.2 之后要单独引数据库模块。
spring:
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: true
baseline-version: 0
validate-on-migrate: true
依赖上,Flyway 10 起 Maven 坐标做了模块化拆分:flyway-core 之外还要按数据库加 flyway-mysql、flyway-database-postgresql 等,Spring Boot 3.2 及以上版本必须补这一条,否则启动报找不到数据库支持。Liquibase 侧只需 spring.liquibase.change-log 指向 master 文件。
生产环境多实例并发启动时,两个工具都会用锁表/行锁保证只有一个实例执行迁移,其余实例等待,这一点不用自己实现。
生产环境迁移最容易踩的坑有哪些?
结论:大表 DDL 会锁表,必须用在线 DDL 或分批;多环境必须走同一套脚本。
MySQL 8.0.12 起 ADD COLUMN 支持 INSTANT 算法,只在表末尾加列时生效,加索引、改列类型仍可能触发表重建。PostgreSQL 的 CREATE INDEX CONCURRENTLY 不能跑在事务里,Liquibase 要在 changeSet 上加 runInTransaction: false,Flyway 从 9 起可用脚本内注释 -- flyway:executeInTransaction=false 关闭事务。表超过千万行,优先用 pt-online-schema-change 或 gh-ost 在应用外完成,迁移脚本只做记录。
另一类坑是手工改库:有人在生产直接 ALTER TABLE 却没留脚本,下次发布迁移就会因版本号或校验和不匹配而失败。dev/test/prod 必须跑同一套 Git 脚本,flyway clean(删除 schema 下全部对象)只能出现在本地测试环境。
迁移失败了怎么回滚?
结论:默认向前修复,写一个新版本号脚本把状态改回来,而不是删脚本。
Flyway 社区版没有 rollback 命令,唯一可靠做法是新增 V{n+1}__revert_xxx.sql。Liquibase 提供 liquibase rollback-count 1、rollback --tag=v1.2,前提是 changeSet 有可解析的 rollback 内容;发布前用 liquibase update-sql 或 flyway migrate -dryRunOutput 打印将要执行的 SQL 做评审,是成本最低的保险。
把这几条串起来就是一套可用的迁移管理:脚本进 Git、只增不改、版本号单调递增、发布前 dry-run 评审、生产只向前修复、大表变更交给在线 DDL 工具。做到这些,数据库变更就和代码发布一样可追溯、可复现。
原文链接:https://www.gj0.com/thread-843.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。