Liquibase优化:合并未部署至生产的非可重运行变更集
数据库变更集合并与多环境部署方案问题
背景
我的master-changelog.yaml初始内容如下:
databaseChangeLog: - include: relativeToChangelogFile: true file: db_ver_1.0/scripts.yaml
对应的db_ver_1.0/scripts.yaml内容:
databaseChangeLog: - include: relativeToChangelogFile: true file: tables/001_table1_create.sql - include: relativeToChangelogFile: true file: tables/002_table2_create.sql - include: relativeToChangelogFile: true file: functions/001_function1.sql - include: relativeToChangelogFile: true file: functions/002_function2.sql
我给函数变更集设置了runOnChange:true,方便变更时重新执行。但对于表,比如table1先在开发环境创建,之后我新增了tables/003_table1_alter.sql变更集来给它加列,修改后的scripts.yaml变成这样:
databaseChangeLog: - include: relativeToChangelogFile: true file: tables/001_table1_create.sql - include: relativeToChangelogFile: true file: tables/002_table2_create.sql - include: relativeToChangelogFile: true file: functions/001_function1.sql - include: relativeToChangelogFile: true file: functions/002_function2.sql - include: relativeToChangelogFile: true file: tables/003_table1_alter.sql
随着时间推移,scripts.yaml里的变更集越来越长,而有些只在开发环境执行的变更集可以合并。
问题
部署到测试/生产环境时,我希望只保留合并后的001_table1_create.sql(包含新增列),而不是原创建脚本加修改脚本,最优方案是什么?我考虑的是创建db_ver_2.0/scripts.yaml,然后在master-changelog.yaml里移除db_ver_1.0/scripts.yaml,改成:
databaseChangeLog: - include: relativeToChangelogFile: true file: db_ver_2.0/scripts.yaml
其中db_ver_2.0/scripts.yaml内容为:
databaseChangeLog: - include: relativeToChangelogFile: true file: tables/001_table1_create.sql # 该文件已包含新增列 - include: relativeToChangelogFile: true file: tables/002_table2_create.sql - include: relativeToChangelogFile: true file: functions/001_function1.sql - include: relativeToChangelogFile: true file: functions/002_function2.sql
这个方案可行吗?有没有更优的做法?
方案评估与最优实践
你的版本化拆分方案是可行的,但还有更灵活的优化方向,核心要兼顾环境差异化部署和变更历史可追溯:
1. 你的版本化方案的优缺点
- 优点:版本边界清晰,测试/生产环境直接用合并后的脚本,避免执行冗余的ALTER语句,部署效率更高。
- 缺点:后续小变更可能会频繁新增版本目录,管理成本上升;开发与生产环境的变更集结构差异大,容易混淆。
2. 更优的环境专属配置方案
推荐用环境专属的changelog文件实现,不用频繁重构版本目录:
- 保留
master-changelog.yaml作为基础入口,再创建dev-changelog.yaml、prod-changelog.yaml分别对应开发、生产环境。 - 开发环境用
dev-changelog.yaml,包含所有细粒度变更集(原创建脚本+ALTER脚本),方便迭代调试。 - 测试/生产环境用
prod-changelog.yaml,直接引用合并后的表创建脚本,以及最新的函数脚本。
示例目录结构:
├── master-changelog.yaml ├── dev-changelog.yaml ├── prod-changelog.yaml ├── db_scripts/ │ ├── tables/ │ │ ├── 001_table1_create_dev.sql # 开发环境用,包含创建+多次ALTER历史 │ │ ├── 001_table1_create_prod.sql # 生产环境用,合并后的最终表结构 │ │ ├── 002_table2_create.sql │ ├── functions/ │ │ ├── 001_function1.sql │ │ ├── 002_function2.sql
prod-changelog.yaml示例内容:
databaseChangeLog: - include: relativeToChangelogFile: true file: db_scripts/tables/001_table1_create_prod.sql - include: relativeToChangelogFile: true file: db_scripts/tables/002_table2_create.sql - include: relativeToChangelogFile: true file: db_scripts/functions/001_function1.sql runOnChange: true - include: relativeToChangelogFile: true file: db_scripts/functions/002_function2.sql runOnChange: true
3. 版本化方案的优化建议(若坚持你的思路)
- 不要删除
db_ver_1.0目录,保留作为历史归档,方便后续排查问题。 - 利用
profiles参数在master-changelog.yaml中控制不同环境加载不同版本脚本,无需修改主文件:
databaseChangeLog: - include: relativeToChangelogFile: true file: db_ver_1.0/scripts.yaml profiles: dev - include: relativeToChangelogFile: true file: db_ver_2.0/scripts.yaml profiles: prod,test
部署时指定对应的profile即可切换环境的变更集。
关键注意事项
- 无论哪种方案,生产环境的变更集必须经过严格测试,合并后的表结构要与开发环境最终状态完全一致。
- 函数的
runOnChange:true要保留,确保函数变更能在所有环境自动更新。 - 所有变更脚本要做好版本标记和注释,方便追溯历史变更。
内容的提问来源于stack exchange,提问作者user6266816
相关产品推荐
相关产品推荐

