Liquibase 部分提交变更集
Liquibase commits changeset partially
在 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 异常(即约束检查或其他)而失败,则数据库更改日志 table 将不会更新,我不希望这样做,因为变更集失败。但是,第一个语句 DID 通过了,我的 table 现在称为 new_table.
当然,如果我纠正导致第二个更新失败的问题并重试更新,它将失败,因为 old_table 不再存在。
我在 liquibase 文档中知道这一段
Liquibase attempts to execute each changeSet in a transaction that is
committed at the end, or rolled back if there is an error. Some
databases will auto-commit statements which interferes with this
transaction setup and could lead to an unexpected database state.
Therefore, it is usually best to have just one change per changeSet
unless there is a group of non-auto-committing changes that you want
applied as a transaction such as inserting data.
https://www.liquibase.org/documentation/changeset.html
但是我不是很懂。自动提交意味着自动提交一个事务。如果所有的变更集都包含在一个事务中,为什么只有一些变更通过了? liquibase 应该回滚整个事务吗?
对此有什么最佳做法吗?我们不能在liquibase中手动设置交易吗?
Mysql(以及许多其他关系数据库)具有 隐式提交 概念。大多数数据库隐式触发提交(就像您自己调用 COMMIT 一样)以在执行 DDL 语句之前(或之后)结束当前活动事务。
Liquibase 尝试在单个事务下应用一个变更集的指定变更。在您的情况下,有两个更改,并且都是 DDL 语句(RENAME TABLE 和 ALTER TABLE),在一个更改集下。这两个语句都将触发隐式提交,如果后面的语句失败,这将使数据库处于不一致状态。
他们网站上 mysql implicit commit 的更多信息,包括触发隐式提交的 SQL 语句的完整列表。
希望对您有所帮助。
不是 Liquibase 正在部分提交变更集。
我使用过许多数据库,我使用的所有数据库的基本概念是事务仅结合数据修改 (DML)。
DDL 永远不是事务的一部分。它总是立即执行,并且在执行之前自动提交打开的事务。
这是因为数据库的回滚命令只能处理数据修改。它无法处理 DDL。如果回滚不再可能,那么保持事务打开就没有用了。
因此,Liquibase 确实创建了一个事务,并在最后按照文档说明提交了所有更改。但这只有在变更集仅包含 DML 而没有 DDL 时才有效。
因此,永远不要将 DDL 和 DML 混合在一个变更集中,每个 DDL 语句都应该在一个单独的变更集中。否则,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 异常(即约束检查或其他)而失败,则数据库更改日志 table 将不会更新,我不希望这样做,因为变更集失败。但是,第一个语句 DID 通过了,我的 table 现在称为 new_table.
当然,如果我纠正导致第二个更新失败的问题并重试更新,它将失败,因为 old_table 不再存在。
我在 liquibase 文档中知道这一段
Liquibase attempts to execute each changeSet in a transaction that is committed at the end, or rolled back if there is an error. Some databases will auto-commit statements which interferes with this transaction setup and could lead to an unexpected database state. Therefore, it is usually best to have just one change per changeSet unless there is a group of non-auto-committing changes that you want applied as a transaction such as inserting data.
https://www.liquibase.org/documentation/changeset.html
但是我不是很懂。自动提交意味着自动提交一个事务。如果所有的变更集都包含在一个事务中,为什么只有一些变更通过了? liquibase 应该回滚整个事务吗?
对此有什么最佳做法吗?我们不能在liquibase中手动设置交易吗?
Mysql(以及许多其他关系数据库)具有 隐式提交 概念。大多数数据库隐式触发提交(就像您自己调用 COMMIT 一样)以在执行 DDL 语句之前(或之后)结束当前活动事务。
Liquibase 尝试在单个事务下应用一个变更集的指定变更。在您的情况下,有两个更改,并且都是 DDL 语句(RENAME TABLE 和 ALTER TABLE),在一个更改集下。这两个语句都将触发隐式提交,如果后面的语句失败,这将使数据库处于不一致状态。
他们网站上 mysql implicit commit 的更多信息,包括触发隐式提交的 SQL 语句的完整列表。
希望对您有所帮助。
不是 Liquibase 正在部分提交变更集。 我使用过许多数据库,我使用的所有数据库的基本概念是事务仅结合数据修改 (DML)。
DDL 永远不是事务的一部分。它总是立即执行,并且在执行之前自动提交打开的事务。 这是因为数据库的回滚命令只能处理数据修改。它无法处理 DDL。如果回滚不再可能,那么保持事务打开就没有用了。
因此,Liquibase 确实创建了一个事务,并在最后按照文档说明提交了所有更改。但这只有在变更集仅包含 DML 而没有 DDL 时才有效。
因此,永远不要将 DDL 和 DML 混合在一个变更集中,每个 DDL 语句都应该在一个单独的变更集中。否则,Liquibase 无法阻止变更集部分成功并在尝试回滚时造成麻烦。