Liquibase对Oracle DDL的幂等性

bru*_*cet 5 oracle liquibase database-update

我正在调查使用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>
Run Code Online (Sandbox Code Playgroud)

为了使这个幂等,我认为它必须改为如下:

<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>
Run Code Online (Sandbox Code Playgroud)

有没有更简单的方法来实现这一目标?我本以为Liquibase能够产生这些先决条件.

谢谢

Mir*_*ari 0

不幸的是,在大多数 RDBMS 中,DDL 语句提交事务,而 Liquibase 仅通过回滚事务来应对失败。因此,我首先要做的是将每个 DDL 语句包装在一个单独的变更集中。

哪些情况下更新databaschangelog失败?我很好奇,因为这应该非常强大。

无论如何,您可以通过为 Liquibase 编写一个小扩展来避免重复,该扩展会自动为您的所有变更集执行此操作。看一下前提条件扩展点。