Liquibase部分提交变更集

时间:2019-05-31 08:00:34

标签: mysql database liquibase

在MySQL上使用liquibase v3.6.3。如果我理解正确,默认情况下,每个CHANGESET都会运行到SQL事务中。但是,在我看来,事务是在CHANGE基础上提交的。运行此脚本时

databaseChangeLog:
  - changeSet:
      id: changeset-
      changes:        
         - renameTable:
            oldTableName: old_table
            newTableName: new_table
        - addColumn:
            columns:
              - column:
                  name: test_column_name
                  type: varchar(255)
                  tableName: other_table

如果addColumn标记由于某些SQL异常(即约束检查或其他)而失败,那么由于变更集失败,因此不会更改databasechangelog表,这是我不希望的。但是,firs语句DID通过了,我的表现在称为 new_table

当然,如果我纠正了导致第二个失败并重试更新的问题,则它将失败,因为old_table不再存在。

我知道liquibase文档中的这一段

  

Liquibase尝试执行以下事务中的每个changeSet:   最后提交,如果有错误则回滚。一些   数据库将自动提交会干扰此操作的语句   事务设置,并可能导致意外的数据库状态。   因此,通常最好每个changeSet仅更改一项   除非您要进行一组非自动提交的更改   应用于事务,例如插入数据。

https://www.liquibase.org/documentation/changeset.html

但是我不太了解。自动提交是指自动提交交易。如果所有变更集都包装在事务中,为什么只传递一些变更? liquibase是否应回滚整个交易?

是否有任何最佳做法?我们不能在liquibase中手动设置交易吗?

2 个答案:

答案 0 :(得分:1)

Mysql(和许多其他关系数据库)具有隐式提交概念。大多数数据库隐式触发提交(就像您自己调用COMMIT一样),以在执行DDL语句之前(或之后)结束当前活动事务。

Liquibase尝试在单个事务下应用一个变更集的指定变更。在您的情况下,有两个更改,并且都是一个更改集下的DDL语句(RENAME TABLE和ALTER TABLE)。这两个语句都将触发隐式提交,如果后面的语句失败,则将导致数据库处于不一致状态。

有关mysql implicit commit网站上的更多信息,包括触发隐式提交的SQL语句的完整列表。

希望有帮助。

答案 1 :(得分:1)

不是Liquibase正在部分提交变更集。 我曾经使用过许多数据库,而我使用的所有数据库的基本概念是,事务仅结合数据修改(DML)。

DDL绝不是事务的一部分。它总是立即执行,并且未执行的事务会在执行之前自动提交。 这样做的原因是数据库的rollback命令只能处理数据修改。它无法处理DDL。而且,如果不再可能进行回滚,则保持事务公开将变得毫无用处。

因此,Liquibase确实创建了一个事务并在文档状态结束时提交所有更改。但这仅在变更集仅包含DML而不包含DDL的情况下有效。

因此,永远不要将DDL和DML混合在一个变更集中,并且每个DDL语句都应该在单独的变更集中。否则,Liquibase无法阻止变更集部分成功并在尝试回滚时引起麻烦。