liquibase更改主键粒度

时间:2019-06-10 12:21:28

标签: java mysql liquibase change-management

我需要更改表以添加一列并将其包括在主键中。 所以我有一个luiqbase变更集:

我想知道如何分离问题并正确实施回滚。

  1. addColumn和PK在一个变更集中的变更
<changeSet author="rahul" id="change_pk">
        <addColumn tableName="posts">
            <column name="aux_id" type="INT" defaultValue="0"/>
        </addColumn>
        <dropPrimaryKey tableName="posts"/>
        <addPrimaryKey tableName="posts" columnNames="id,aux_id"/>
        <rollback>
          <dropPrimaryKey tableName="posts"/>
          <addPrimaryKey tableName="posts" columnNames="id"/>
        </rollback>
    </changeSet>

这种方法让我担心的是,如果我无法创建列,则假定表很大,我将删除PK并重新创建它,这可能会影响数据库的响应时间。但是,这使得所有这些更改都是原子性的。

  1. 将PK更改移动到其他更改集
<changeSet author="rahul" id="add_col">
        <addColumn tableName="posts">
            <column name="aux_id" type="INT" defaultValue="0"/>
        </addColumn>
</changeSet>
<changeSet author="rahul" id="change_pk">
        <dropPrimaryKey tableName="posts"/>
        <addPrimaryKey tableName="posts" columnNames="id,aux_id"/>
        <rollback>
          <dropPrimaryKey tableName="posts"/>
          <addPrimaryKey tableName="posts" columnNames="id"/>
        </rollback>
</changeSet>

因此,我将能够对PK更改的回滚有更多控制,它将删除并重新创建旧的PK。但是,存在一个问题,当未应用change_pk变更集时-我有一个列,应将其包含在PK中,但事实并非如此,这会使系统容易受到唯一约束冲突的影响。

1 个答案:

答案 0 :(得分:0)

您可以使用runAlways属性执行以下操作。另外,签出不同的onFail选项

<changeSet author="rahul" id="add_col" runAlways="true">
    <preConditions (perhaps, some non-default onFail option) >
        <not>
            <columnExists tableName="posts" columnName="aux_id"/>
        </not>
    </preConditions>
    <addColumn tableName="posts">
        <column name="aux_id" type="INT" defaultValue="0"/>
    </addColumn>
</changeSet>

<changeSet author="rahul" id="change_pk">
    <preConditions>
        <and>
            <columnExists tableName="posts" columnName="aux_id"/>
            <!-- perhaps some other precondition --> 
            <sqlCheck expectedResult="id">
                SELECT key_column_usage.column_name
                FROM   information_schema.key_column_usage
                WHERE  table_schema = SCHEMA()     
                AND    constraint_name = 'PRIMARY' 
                AND    table_name = 'posts' 
            </sqlCheck>
        </and>
    </preConditions>
    <dropPrimaryKey tableName="posts"/>
    <addPrimaryKey tableName="posts" columnNames="id,aux_id"/>
    <rollback>
        <dropPrimaryKey tableName="posts"/>
        <addPrimaryKey tableName="posts" columnNames="id"/>
        <dropColumn tableName="posts" columnName="aux_id">
    </rollback>
</changeSet>