Search code examples
javaspringlockingdatabase-migrationliquibase

Liquibase Double-Checked Locking Pattern ? (make liquibase not acquiring lock if everything is up-to-date)


If an application crashes (OOM / power failure / kill -9) after liquibase acquired a lock, but before releasing the lock, the lock will remain in the databasechangeloglock table forever and we'll need to manually remove it.

I wonder if it's possible to force the application with liquibase do this:

  1. check if it needs to apply any changesets WITHOUT taking a lock
  2. if so, acquire the lock, check the need again, and so on as usual. If everything is up to date - do not acquire lock and continue the boot strap.

I want it to speed up application bootstrap (when there's no new migrations) and reduce chances to get stuck lock in the databasechangeloglock.

Currently I just create a liquibase.integration.spring.SpringLiquibase Spring bean. I assume I need to create some custom tricky @ConditionalOn... annotation


Solution

  • You can provide your own implementation of liquibase.lockservice.LockService using the ServiceLoader mechanism. This allows you to implement a custom lock and unlock mechanism. For PostgreSQL, you can use the pg_try_advisory_lock and pg_advisory_unlock functions. When the connection is lost, the lock is automatically released, allowing another connection to acquire it. And attempt to do migration. Following library has support for following databases:

    • MySQL
    • MariaDB
    • PostgreSQL
    • Oracle
    • MSSQL

    https://github.com/blagerweij/liquibase-sessionlock