2012-12-30 28 views
4

我在研究如何使用Liquibase開發一個使用Oracle的新項目,我想知道如何確保我的changeSets足夠健壯以從任何類型的故障中恢復而無需手動干預。理想情況下,我將使用runInTransaction屬性,該屬性允許在失敗時回滾DDL,但Oracle會自動提交DDL。對於這種情況,文檔建議:關於Oracle DDL的Liquibase冪計算

因此,通常最好每個changeSet只有一個更改,除非有一組非自動提交的更改要作爲事務應用,例如插入數據。

每個changeSet有一個DDL可以減少問題發生的機率,但不會消除它們。如果DDL成功,但對DATABASECHANGELOG的更新失敗,那麼從我的測試中看來,Liquibase似乎卡住了,需要手動干預。

爲避免此問題,有必要在每一步中使用前提條件?這使得生成的changeSets非常冗長。這是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

在它自己的變更集中運行每個DDL是推薦的方法。你想要防禦的東西(缺少CHANGELOG表的更新)是非常偏執的,並且可以通過在你的changset中插入前提條件來解決。就像你所做的那樣....你對liquibase有什麼替代策略? –

+1

捍衛合理的失敗條件是強大的,而不是偏執。我用專有的數據庫升級框架解決了這個問題(特別是在長時間運行操作之後,比如在非常大的表上創建新的索引創建之後,數據庫會話可能已經過期)。我希望Liquibase支持該選項自動生成前提條件(例如,對於每個,隱含地包含的前提條件)。 – brucet

+0

聽起來像一個偉大的功能建議:http://www.liquibase.org/community –

回答

0

不幸的是在大多數RDBMS,DDL語句提交事務,並通過Liquibase剛剛回滾事務反應失敗。所以首先我要做的是將每個DDL語句包裝在一個單獨的變更集中。

在哪些情況下更新databaschangelog失敗?我很好奇,因爲這應該非常健壯。

無論如何,您可以通過爲Liquibase編寫一個小擴展來避免重複自己,Liquibase自動爲您的所有變更集自動執行。看看Precondition延伸點。