我正在调查使用Liquibase进行使用Oracle的新项目,我想知道如何确保我的changeSet足够强大,可以在没有人工干预的情况下从任何类型的故障中恢复。理想情况下,我会使用runInTransaction属性,这将允许DDL在失败时回滚,但Oracle会自动提交DDL。对于这种情况,文档建议:
因此,通常最好每个changeSet只进行一次更改,除非有一组非自动提交的更改要作为事务应用,例如插入数据。
每个changeSet有一个DDL可以减少出现问题的几率,但不会消除它们。如果DDL成功,但对DATABASECHANGELOG的更新失败,从我的测试中看来,Liquibase似乎卡住了,需要手动干预。
有必要在每一步使用前置条件来避免这个问题吗?这使得生成的changeSet非常冗长。这是Liquibase示例表定义之一:
<changeSet author="jsmith" id="1">
<createTable tableName="departments"
remarks="The departments of this company. Does not include geographical divisions.">
<column name="id" type="number(4,0)">
<constraints nullable="false" primaryKey="true"
primaryKeyName="DPT_PK"/>
</column>
<column name="dname" type="varchar2(14)"
remarks="The official department name as registered on the internal website."/>
</createTable>
<addUniqueConstraint constraintName="departments_uk1"
columnNames="dname" tableName="departments"/>
<createSequence sequenceName="departments_seq"/>
</changeSet>
为了使这个幂等,我认为它必须改为如下:
<changeSet author="jsmith" id="1">
<preConditions onFail="MARK_RAN">
<not>
<tableExists tableName="departments" />
</not>
</preConditions>
<createTable tableName="departments"
remarks="The departments of this company. Does not include geographical divisions.">
<column name="id" type="number(4,0)" / column>
<column name="dname" type="varchar2(14)"
remarks="The official department name as registered on the internal website." />
</createTable>
</changeSet>
<changeSet author="jsmith" id="2">
<preConditions onFail="MARK_RAN">
<not>
<primaryKeyExists primaryKeyName="pk_departments" />
</not>
</preConditions>
<addPrimaryKey tableName="departments" columnNames="id"
constraintName="pk_departments" />
</changeSet>
<changeSet author="jsmith" id="3">
<preConditions onFail="MARK_RAN">
<not>
<uniqueConstraintExists constraintName="departments_uk1" />
</not>
</preConditions>
<addUniqueConstraint constraintName="departments_uk1"
columnNames="dname" tableName="departments" />
</changeSet>
<changeSet author="jsmith" id="4">
<preConditions onFail="MARK_RAN">
<not>
<sequenceExists sequenceName="departments_seq" />
</not>
</preConditions>
<createSequence sequenceName="departments_seq" />
</changeSet>
有没有更简单的方法来实现这一目标?我原以为Liquibase能够产生这些先决条件。
由于
答案 0 :(得分:0)
不幸的是,在大多数RDBMS中,DDL语句提交事务,Liquibase通过回滚事务来对失败作出反应。首先,我要做的是将每个DDL语句包装在一个单独的变更集中。
在哪些情况下更新databaschangelog失败了?我很好奇,因为这应该非常强大。
无论如何,您可以通过为Liquibase编写一个小扩展来避免重复自己,该扩展会自动为您的所有更改集执行此操作。请查看Precondition扩展点。