问题
Please say something about this problem:
We are supporting several microservices written in Java using Spring Boot and deployed in OpenShift. Some microservices communacates with databases. We often run a single microservice in multiple pods in a single deployment. When each microservice starts, it starts liquibase, which tries to update the database. The problem is that sometimes one pod fails with waiting for the changelog lock issue. When for some reason this happens in production OpenShift cluster, we expect other pods to fail while restarting because of the same problem with changelog lock issue. So in the worst case scenario, all pods will wait for the lock to be lifted.
We want liquidbase automatically prepare our database schemas when pod is starting.
So please tell the best way to solve this problem? Is it good to store this logic in every microservice? How can we automatically solve the problem when the liquidbase changelog lock problem appears? Do we need to put the database preparation logic in a separate deployment?
Thanks
#Updated
So maybe I should paraphrase my question. What is the best way to run db migration in term of microservice architecture? Maybe we should not use db migration in each pod? Maybe it is better to do it with separate deployment or do it with some extra Jenkins job not in OpenShift at all?
回答1:
We're running liquibase migrations as an init-container in Kubernetes. The problem with running Liquibase in micro-services is that Kubernetes will terminate the pod if the readiness probe is not successful before the configured timeout. In our case this happened sometimes during large DB migrations, which could take a few minutes to complete. Kubernetes will terminate the pod, leaving DATABASECHANGELOGLOCK in a locked state. With init-containers you will not have this problem. See https://www.liquibase.org/blog/using-liquibase-in-kubernetes for a detailed explanation.
UPDATE Please take a look at this Liquibase extension, which replaces the StandardLockService, by using database locks: https://github.com/blagerweij/liquibase-sessionlock
This extension uses MySQL or Postgres user lock statements, which are automatically released when the database connection is closed (e.g. when the container is stopped unexpectedly). The only thing required to use the extension is to add a dependency to the library. Liquibase will automatically detect the improved LockService.
I'm not the author of the library, but I stumbled upon the library when I was searching for a solution. I helped the author by releasing the library to Maven central. Currently supports MySQL and PostgreSQL, but should be fairly easy to support other RDBMS.
回答2:
When Liquibase kicks in during the spring-boot app deployment, it performs (on a very high level) the following steps:
- lock the database (create a record in
databasechangeloglock
) - execute changeLogs;
- remove database lock;
So if you interrupt application deployment while Liquibase is between steps 1 and 3, then your database will remain locked. So when you'll try to redeploy your app, Liquibase will fail, because it will treat your database as locked.
So you have to unlock the database before deploying the app again.
There are two options that I'm aware of:
- Clear
databasechangeloglock
table or setlocked
tofalse
. Which isDELETE FROM databasechangeloglock
orUPDATE databasechangeloglock SET locked=0
- Execute
liquibase releaseLocks
command. You can find documentation about it here and here.
回答3:
Finally we solved this problem in another project by removing liquibase migration at microservice start time. Now separate Jenkins job apply the migration and separate Jenkins job deploy and start microservice after migration apply. So now microservice itself doesn’t apply database update
来源:https://stackoverflow.com/questions/61387510/how-to-solve-liquibase-waiting-for-changelog-lock-problem-in-several-pods-in-ope