Does Liquibase support dry run?

We have a couple of data schemas and we are exploring migration to Liquibase. (One of the data schemas has already been ported to Liquibase).

An important issue for us is that Liquibase maintains a dry run:

  • We need to run database changes on all schemas without committing to ensure that we have no problems.
  • If successful, all database changes are committed again with a commit.

(A question similar to this dry SQL Server query record , but related to Liquibase)

Added after reply

I read the documentation related to updateSQL and it does not meet the dry run requirements. It just generates SQL (on the command line, in the Ant task, and in the Maven plugin). I will clarify my question:

Does Liquibase support transaction control?

I want to open a transaction before executing Liquibase's change log and cancel the transaction after making the changes. Of course, I need to check the result of the execution.

Is it possible?

Added

Without transaction control (or dry run), we cannot migrate all our schemes to Liquibase.

Please, help.

+7
source share
4 answers

You can try "updateSQL", enable db (check permissions), get a db lock, generate / print the SQL statements that will be applied (based on the db state and the current Liquibase change sets) and it will print out There is no chageset id in the current db state and db lock.

+7
source

Unfortunately not.

By default, Liquibase completes a transaction that runs all of the changeset instructions. I assume that the migration paths you have in mind usually include more than one set of changes.

The only way to change the behavior of a transaction is with the runInTransaction attribute for the <changeset> , as described here . By setting it to false , you actually turn off transaction management, that is, turn on automatic commit mode, as you can see in ChangeSet.java .

I think this feature can be a useful complement to Liquibase, so I opened a feature request: CORE-1790 .

+8
source

I think your answer is: โ€œIt does not support dry runs,โ€ but the problem is mainly with the database and not with liberzase.

Liquibase launches each changeSet in a transaction and commits it after inserting it into the DATABASECHANGELOG table, so theoretically you can redefine Liquibase logic to roll back this transaction instead of committing it, but you will encounter a problem when most of SQL is powered by Liquibase is an automatic commit.

For example, if you have a changeSet from:

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

Performed:

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

but even if you changed the last command to ROLLBACK, the create table call will be automatically committed when it starts, and the only thing that will really be a rollback is INSERT.

NOTE. There are several databases that will roll back SQL DDL, such as postgresql, but most do not.

INSERT / UPDATE commands will be executed in a transaction and can be automatically rolled back at the end, but linibase does not have a postCondition command to check the status of a transaction that is required. This would be a useful feature ( https://liquibase.jira.com/browse/CORE-1793 ), but even it will not be used if there are tags in the changeset with automatic committing of changes. If you added a postcondition to create the above example table, the postcondition will fail and the update will fail, but the table will still be there.

+2
source

If your Liquibase migration is sufficiently independent of the database, you can simply run it in the H2 database in memory (or in another โ€œone-time databaseโ€), which can be easily untwisted using a few lines of code.

 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 spoke in detail about this approach here .

0
source

All Articles