Liquibase支持干运行吗?

时间:2014-02-18 08:00:58

标签: sql transactions liquibase

我们有几个数据模式,我们调查迁移到Liquibase。 (其中一个数据模式已经迁移到Liquibase)。

对我们来说,重要的问题是Liquibase是否支持干运行:

  • 我们需要在没有提交的情况下对所有模式运行数据库更改,以确保我们没有问题。
  • 如果成功,所有数据库更改将再次使用commit运行。

(类似于此SQL Server query dry run但与Liquibase相关的问题)

在答案后添加

我阅读了与updateSQL相关的文档,并没有回答“干运行”的要求。 它只是生成SQL(在命令行中,在Ant任务和Maven插件中)。 我会澄清我的问题:

Liquibase是否支持对交易的控制?

我想在执行Liquibase changelog之前打开事务,并在更改日志执行后回滚事务。 当然,我需要验证执行的结果。

有可能吗?

如果不对交易(或干运行)进行控制,我们就无法将所有模式迁移到Liquibase。

请帮忙。

4 个答案:

答案 0 :(得分:7)

不幸的是,没有。

默认情况下,Liquibase提交执行变更集的所有语句的事务。我假设您考虑的迁移路径通常涉及多个变更集。

您可以修改交易行为的唯一方法是runInTransaction代码的<changeset>属性,为documented here。通过将其设置为false,您可以有效地禁用事务管理,即它可以启用自动提交模式,如ChangeSet.java中所示。

我认为此功能可能是Liquibase的一个有价值的补充,所以我打开了一个功能请求:CORE-1790

答案 1 :(得分:6)

您可以尝试“updateSQL”模式,它将连接db(检查您的访问权限),获取数据库锁定,生成/打印要应用的SQL语句(基于db状态和您当前的liquibase更改集)也会打印在当前的db状态和释放db锁中缺少chageset id。

答案 2 :(得分:2)

我认为你的答案是“它不支持干运行”,但问题主要在于数据库而不是liquibase。

Liquibase在事务中运行每个changeSet并在插入DATABASECHANGELOG表后提交它,所以理论上你可以覆盖liquibase逻辑来回滚该事务而不是提交它,但是你会遇到大多数SQL运行的问题liquibase是自动提交的。

例如,如果您的changeSet为:

<changeSet>
  <createTable name="test">
   ...
   </createTable>
</changeSet>

运行的是:

START TRANSACTION
CREATE TABLE NAME ...
INSERT INTO DATABASECHANGELOG...
COMMIT

但即使您将最后一个命令更改为ROLLBACK,create table调用也会在运行时自动提交,而实际回滚的唯一内容是INSERT。

注意:有些数据库会回滚DDL SQL,例如postgresql,但大多数数据库都没有。

INSERT / UPDATE命令将在事务中运行,并且可以在结尾处自动回滚,但是liquibase没有postCondition命令来执行对所需状态的事务内检查。这将是一个有用的功能(https://liquibase.jira.com/browse/CORE-1793),但即使它在变更集中有任何自动提交更改标记也不可用。如果您添加了一个后置条件以创建上面的表示例,则后置条件将失败并且更新将失败,但该表仍将存在。

答案 3 :(得分:0)

如果您的Liquibase迁移完全独立于数据库,则可以在内存中的H2数据库(或其他“丢弃数据库”)上运行它,只需使用几行代码即可轻松启动。

var info = new Properties();
info.put("user", "sa");
info.put("password", "");

try (var con = new org.h2.Driver().connect("jdbc:h2:mem:db", info)) {
    var accessor = new FileSystemResourceAccessor();
    var jdbc = new JdbcConnection(con);
    var database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(jdbc);

    Liquibase liquibase = new Liquibase("/path/to/liquibase.xml", accessor, database);
    liquibase.update("");
}

I've blogged about this approach more in detail here