Liquibase uses the DATABASECHANGELOGLOCK table to ensure only one instance of Liquibase is running at one time.
Because Liquibase simply reads from the DATABASECHANGELOG table to determine which changesets need to run, if multiple instances of Liquibase are executed against the same database concurrently you will get conflicts. This can happen if multiple developers use the same database instance or if there are multiple servers in a cluster which auto-run Liquibase on startup.
To get rid of the log you can start liquibase releaseLocks which in turn runs UPDATE DATABASECHANGELOGLOCK SET LOCKED=0 on DB level.
In theory you can disable the lock using https://github.com/liquibase/liquibase-nochangeloglock, but that is dangerous if you have several instances of your app/service runing in parallel.
There are cases where the lock gets in the way and you want to automate its release. Several pending PRs are with Liquibase at this moment (December 2021) that will make this lock bound to a particular process. Until these are merged however, your best option would be to use a Liquibase extension like https://github.com/oridool/liquibase-locking. This particular extension seems to be bound to PostgreSQL and in my case I was using different DB.
I wanted to keep the locking to prevent accidental changelog modified from two instances at the same time. But also I had to work with the following set of boundary conditions:
- only one instance of your service/application is usually running (monolith or scheduled task for instance)
- application is often killed or exits during startup, while applying Liquibase changelog
- PaaS health check or probe (K8s, Messos/Marathon, Cloud Foundry) does not allow Liquibase changelog changes to run more than a certain amount of time
So I decided to create a Liquibase extension that:
- releases the lock if it was created more than max-timeout minutes ago
- works with the default strategy (waits for the lock) otherwise
No comments:
Post a Comment