在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中手动设置交易吗?
答案 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无法阻止变更集部分成功并在尝试回滚时引起麻烦。