Liquibase中runAlways为true的changeset如何使用<preconditions>标签?
解决方案
1 基于<preconditions>标签的实现方式
核心思路是不修改已执行过的原有changeset,避免触发checksum校验规则,新增独立changeset通过前置条件实现DROP IF EXISTS的等效逻辑,完全不需要添加<validCheckSum>标签。
你之前的报错本质是修改了已经存入DATABASECHANGELOG表的changeset内容,导致新计算的checksum和历史记录不匹配,不改动原有changeset就能从根源避免这个问题。
实现代码如下:
<!-- 原有id为foo-1的changeset完整保留,不要做任何修改 --> <changeSet dbms="voltdb" author="foo" id="foo-1" runAlways="true"> <sql>DROP PROCEDURE BAR</sql> <rollback/> </changeSet> <!-- 新增独立的changeset,通过preconditions控制执行逻辑 --> <changeSet dbms="voltdb" author="foo" id="foo-2" runAlways="true"> <!-- 前置条件:校验BAR存储过程是否存在,不存在则直接标记为已执行,不报错 --> <preConditions onFail="MARK_RAN"> <sqlCheck expectedResult="1"> SELECT COUNT(*) FROM SYS.PROCEDURES WHERE UPPER(PROCEDURE_NAME) = 'BAR' </sqlCheck> </preConditions> <sql>DROP PROCEDURE BAR</sql> <rollback/> </changeSet>
参数说明:
onFail="MARK_RAN":如果前置条件不满足(存储过程不存在),Liquibase会直接将该changeset标记为已执行,跳过后续SQL执行,不会抛出错误,等效于IF EXISTS的效果- 适配VoltDB的系统表规则,使用
SYS.PROCEDURES查询存储过程是否存在,加UPPER避免大小写敏感问题
该方案符合Liquibase的最佳实践,所有变更均有独立记录,相比<validCheckSum>ANY</validCheckSum>完全跳过校验的逻辑安全性更高,避免后续误改changeset无法被发现的问题。
2 其他替代方案
如果一定要修改原有changeset的内容,不需要新增changeset,可以直接执行liquibase clearCheckSums命令,该命令会清空DATABASECHANGELOG表中所有历史checksum记录,下次执行时会重新计算所有changeset的checksum并写入表中,不会再触发校验失败错误。
注意该命令全局生效,执行前需确认所有现有changeset内容均为正确版本,避免误更新。
内容的提问来源于stack exchange,提问作者Deep Dalsania
相关产品推荐
相关产品推荐

