Liquibase变更集因关联列已删除无法重跑的解决方案咨询
解决方案(按优先级从高到低排序)
1. 用changelog-sync命令标记已执行变更(最优)
该方案完全不需要修改原有changelog,也不需要操作业务数据,适配所有数十个环境的自动化部署需求:
报错本质是目标环境已经执行过所有变更,但DATABASECHANGELOG执行记录表丢失了记录,导致Liquibase尝试重复执行历史变更。在部署脚本的Liquibase执行步骤前添加一行自动执行命令即可:
liquibase changelog-sync
该命令会自动比对当前数据库的实际结构和所有changeset的预期结果,将所有已经完成的变更自动标记为已执行,不会做任何业务数据修改,完全无人工操作。
该方案仅适用于所有目标环境已经完成过一次全量变更执行、仅缺失DATABASECHANGELOG执行记录的场景;如果需要同时兼容新环境初始化和老环境重跑,优先选择方案2或3。
2. 给变更集2添加合规的执行前置校验
Liquibase官方不建议修改已上线changeset的核心执行逻辑,但添加preConditions并配套validCheckSum属性属于合规修改,不会引发版本冲突:
给原有changeset 2添加如下配置:
<preConditions onFail="MARK_RAN"> <columnExists tableName="foo" columnName="domain"/> <not> <indexExists tableName="foo" indexName="你的原有索引名"/> </not> </preConditions> <validCheckSum>原有changeset 2的旧校验和值</validCheckSum>
逻辑说明:如果检测到domain列不存在,直接将该changeset标记为已执行跳过,不会实际运行建索引的逻辑,自然不会报错。添加validCheckSum是为了避免Liquibase判定该changeset被篡改而抛出校验和异常。
3. 新增临时补偿变更集
如果前两个方案都不满足你的场景,可以在整个changelog的最开头新增一个独立的changeset:
<changeSet id="temp-add-domain-column" author="yourname"> <preConditions onFail="MARK_RAN"> <tableExists tableName="foo"/> <not> <columnExists tableName="foo" columnName="domain"/> </not> </preConditions> <addColumn tableName="foo"> <column name="domain" type="varchar(255)"/> <!-- 保持和原来的字段类型一致 --> </addColumn> </changeSet>
该changeset会在所有历史变更执行前检测,如果foo表已存在但缺失domain列,就临时补建该列,后续原有3个changeset执行完成后,changeset 3会自动删除该临时字段,不需要额外处理。
内容的提问来源于stack exchange,提问作者Alexander
相关产品推荐
相关产品推荐

