Posts Liquibase Emergency Recocery

Liquibase Emergency Recocery

Today I spend most of my time migrating a database. Luckily the version-controlled with Liquibase. Liquibase prmotes on its website as:

Track, version, and deploy database changes

The single changes to apply can be described in different ways and grouped into so-called changesets. Changesets are the unit that liquibase tracks, so a once applied changeset is not run again. For further information dig into the documentation.

So updating should be nothing special, right? Well, there are some hurdles.

Know your Workflow

Working with liquibase is straightforward, but nothing prevents you from locking yourself. The must-know commands of liquibase are:

  1. update or for those using the maven plugin liquibase:update. This command executes all changesets which are not yet marked as executed.
  2. sync or maven liquibase:sync. Marks all local changesets as executed in the database.
  3. status or maven liquibase:status. Prints out which changesets are not yet marked as executed.

The basic workflow looks like this. Liquibase basic workflow You start developing your changes, check what to apply with status. Execute the updates with update and then mark the changes as executed with sync.

Lessons Learned 1: Never run sync without being sure that every local changeset applied successfully! If you are in doubt, run update again ;-).

Oh shit, I synced, not executed changes!

Yes, well, I did. Googled aaaaaannnd - Nothing besides “Don’t do this”. Well, no shit Sherlock! But don’t worry, I have your back ;-)

First of all, we need to identify changes that didn’t execute yet. If we have the list of not executed changesets, we can check the Databasechangelog table. This table contains all changesets which are executed and is the source on which the update command relies. For details find the documentation here.

In this situation, the column FILENAME, AUTHOR and ID are important. The filename corresponds to the changelog file. In the changeset definition within the changelog, we can find the author and id.

delete from databasechangelog where filename=:changelogFileName and author=:authorOfChangeset and id=:changeSetID

Now you can execute the changelogs with update and, if succeeded, run sync. Your changes should be applied now. Lessons learned 2: You can recover from ignoring lessons learned 1, but it is risky!

I was too hectically. I’ve cleaned the log..

Well, shit. But were there, done that and recovered!

We proceed like in the last section. But first, let’s refill the database changelog table. It is straightforward by executing sync. Remember it marks all locally present changes as executed. From here, we need to delete the rows with the not yet executed changes and apply them with update.

Lessons learned 3: You can recover from total screw-up-situation, but try to avoid them!


It was an exciting and challenging day. Liquibase is a very powerful tool and a must-have in every developer’s toolkit. Learning always involves failing, but sadly the internet lacks recovery guides for liquibase. I hope my three lessons learned can help you not do my faults or recover from them.

This post is licensed under CC BY 4.0 by the author.