Concurrent updating of databases is no longer possible since upgrading to liquibase 4.x

Hi all,
I’m new here. I’ve searched the forum, but couldn’t find the answer.
We have a Jakarta EE 8 application and are currently using liquibase 3.8.9 (liquibase-core) to update all the client databases via a startup bean.
The bean has a fixed threadpool of 10 connections.
When we upgrade the liquibase-core dependency to 4.8 or higher (no further changes) it is no longer possible to change more than 1 database concurrently (threadpool = 1).
Otherwise we get the following error:
Caused by: nl.tent.spectrum.platform.plugin.common.DatabaseSchemasUpdateException: Fout update brp :java.lang.RuntimeException: Cannot end scope yaulsszpdr when currently at scope aaeulhdqdk
2022-06-24T12:48:29.136741300Z at nl.tent.spectrum.brp.service.db.BrpPluginDB.initBrp(BrpPluginDB.java:49)
2022-06-24T12:48:29.136753200Z at nl.tent.spectrum.brp.service.db.BrpPluginDB.lambda$init$0(BrpPluginDB.java:33)
2022-06-24T12:48:29.136765800Z at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
2022-06-24T12:48:29.136783600Z at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
2022-06-24T12:48:29.136792500Z at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
2022-06-24T12:48:29.136802000Z at java.base/java.lang.Thread.run(Thread.java:829)
2022-06-24T12:48:29.136809300Z Caused by: liquibase.exception.LiquibaseException: java.lang.RuntimeException: Cannot end scope yaulsszpdr when currently at scope aaeulhdqdk
2022-06-24T12:48:29.136817700Z at liquibase.Liquibase.runInScope(Liquibase.java:2410)
2022-06-24T12:48:29.136826700Z at liquibase.Liquibase.update(Liquibase.java:211)
2022-06-24T12:48:29.136836100Z at liquibase.Liquibase.update(Liquibase.java:197)
2022-06-24T12:48:29.136844800Z at liquibase.Liquibase.update(Liquibase.java:193)
2022-06-24T12:48:29.136853900Z at liquibase.Liquibase.update(Liquibase.java:185)
2022-06-24T12:48:29.136863300Z at nl.tent.database.liquibase.LiquibaseHelper.update(LiquibaseHelper.java:44)
2022-06-24T12:48:29.136875200Z
Caused by: java.lang.RuntimeException: Cannot end scope yaulsszpdr when currently at scope aaeulhdqdk
2022-06-24T12:48:29.180951500Z at liquibase.Scope.exit(Scope.java:230)
2022-06-24T12:48:29.180957500Z at liquibase.Scope.child(Scope.java:191)
2022-06-24T12:48:29.180963900Z at liquibase.Scope.child(Scope.java:179)
2022-06-24T12:48:29.180971500Z at liquibase.Scope.child(Scope.java:158)
2022-06-24T12:48:29.180977300Z at liquibase.Liquibase.runInScope(Liquibase.java:2405)
2022-06-24T12:48:29.180983700Z … 11 more
2022-06-24T12:48:29.180989800Z

Can you tell me what we have to do in order to make the concurrent execution possible again. Thanks in advance.

I searched this term and found this post on GitHub. It is not resolved yet, so you could comment to add your voice to the thread. I’ll see if I can get this issue in front of the team this week.

Thnx tabbyfoo. I’ve seen the mentioned post on GitHub. And the fact that it has still not been solved. I’m no member of GitHub but hope you can put some pressure on the team to finally solve this problem.
It is really important for us. The liquibase 3.x has some vulnerabilities we want to get rid of.

It is something we’re wanting to look at, but we have a bunch of improvements we’re also working on, so always hard to balance.

Pre 4.0, the multi-threading support was also something we never looked hard at and so things that worked were sort of accidental. With 4.0 we started building our API/infrastructure to support threading more safely but unfortunately haven’t worked it all the way through yet.

The ScopeManager is the part that’s made to be replacable for different environments, and it’s working through those environments in the generic case that is hard. But you should be able to incorprate that example alternate ScopeManager from the github issue into your setup regardless of when we can get to it officially.

If you have questions, feel free to ask.

Nathan

1 Like

Hi Nathan.
I’ve made some changes as you suggested.

public void update() throws SQLException, LiquibaseException {
    logger.info("Start update schema " + schemaIdentification + " voor omgeving " + omgeving);

    Scope.setScopeManager(new ThreadLocalScopeManager());
    try (LiquibaseConnection connection = new LiquibaseConnection(dataSource.getConnection())) {
        Liquibase liquibase = new Liquibase(changeLogFile, new ClassLoaderResourceAccessor(), connection);
        if (changelogSync(dataSource)) {
            logger.info("Uitvoeren changelogSync schema " + schemaIdentification + " voor omgeving " + omgeving);
            liquibase.changeLogSync(omgeving);
        } else {
            liquibase.update(omgeving);
        }
    }
    logger.info("Einde update schema " + schemaIdentification + " voor omgeving " + omgeving);
}

When the application starts the 38 client databases are updated concurrently (thread-pool of 10). It seems to work just fine, but at the end a NPE occurs while updating a specific database (changeset 2 of 3).
Caused by: java.util.concurrent.ExecutionException: nl.tent.spectrum.platform.plugin.common.DatabaseSchemasUpdateException: Fout update berichtenbox-database [d865448abc8340f1a5ecb2acda093cbb] :java.lang.NullPointerException
2022-07-04T06:53:56.389417900Z at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
2022-07-04T06:53:56.389421500Z at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
2022-07-04T06:53:56.389426100Z at nl.tent.spectrum.platform.master.startup.DatabaseSchemasUpdateBean.executeTaken(DatabaseSchemasUpdateBean.java:177)
2022-07-04T06:53:56.389431700Z … 68 common frames omitted
2022-07-04T06:53:56.389439000Z Caused by: nl.tent.spectrum.platform.plugin.common.DatabaseSchemasUpdateException: Fout update berichtenbox-database [d865448abc8340f1a5ecb2acda093cbb] :java.lang.NullPointerException
2022-07-04T06:53:56.389445000Z at nl.tent.spectrum.platform.plugin.common.AbstractKlantDB.initDatabase(AbstractKlantDB.java:28)
2022-07-04T06:53:56.389450300Z at nl.tent.spectrum.bbx.service.db.BbxPluginKlantDB.initBerichtenboxDatabase(BbxPluginKlantDB.java:48)
2022-07-04T06:53:56.389465600Z at nl.tent.spectrum.bbx.service.db.BbxPluginKlantDB.lambda$init$0(BbxPluginKlantDB.java:37)
2022-07-04T06:53:56.389471400Z at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
2022-07-04T06:53:56.389475000Z at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
2022-07-04T06:53:56.389478700Z at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
2022-07-04T06:53:56.389482300Z at java.base/java.lang.Thread.run(Thread.java:829)
2022-07-04T06:53:56.389486900Z Caused by: liquibase.exception.LiquibaseException: java.lang.NullPointerException
2022-07-04T06:53:56.389490400Z at liquibase.Liquibase.runInScope(Liquibase.java:2410)
2022-07-04T06:53:56.389494000Z at liquibase.Liquibase.update(Liquibase.java:211)
2022-07-04T06:53:56.389497600Z at liquibase.Liquibase.update(Liquibase.java:197)
2022-07-04T06:53:56.389502100Z at liquibase.Liquibase.update(Liquibase.java:193)
2022-07-04T06:53:56.389509100Z at liquibase.Liquibase.update(Liquibase.java:185)
2022-07-04T06:53:56.389514100Z at nl.tent.database.liquibase.LiquibaseHelper.update(LiquibaseHelper.java:46)
2022-07-04T06:53:56.389520100Z at nl.tent.spectrum.platform.plugin.common.AbstractKlantDB.initDatabase(AbstractKlantDB.java:25)
2022-07-04T06:53:56.389527400Z … 6 common frames omitted
2022-07-04T06:53:56.389533100Z Caused by: java.lang.NullPointerException: null
2022-07-04T06:53:56.389542600Z at liquibase.Scope.exit(Scope.java:229)
2022-07-04T06:53:56.389550200Z at liquibase.Scope.child(Scope.java:191)
2022-07-04T06:53:56.389555400Z at liquibase.Scope.child(Scope.java:179)
2022-07-04T06:53:56.389560100Z at liquibase.Scope.child(Scope.java:158)
2022-07-04T06:53:56.389564700Z at liquibase.Liquibase.runInScope(Liquibase.java:2405)
2022-07-04T06:53:56.389569900Z … 12 common frames omitted
2022-07-04T06:53:56.389576300Z |#]
2022-07-04T06:53:56.389582300Z

What other changes are needed to make it work?

1 Like

the NPE is rised on 2022-07-04T06:53:56.389542600Z at liquibase.Scope.exit(Scope.java:229)
and it’s triggering a LiquibaseExceltion after, if you catch this exception and just ignore it, finally, the update works properly.
(at least it worked on my code)

I’ve implemented the suggested work-around and it works! Thanks a lot.

With 4.17.0 we have created ThreadLocalScopeManager (liquibase 4.17.0 API) as an alternative to the standard SingletonScopeManager which uses a single instance of everything across threads.

The ThreadLocalScopeManager keeps separate configurations per thread, and can be enabled by calling Scope.setScopeManager(new ThreadLocalScopeManager()) early in your setup, prior to the creation of the threads

Hey @nvoxland I see this same error after implementing ThreadLocalScopeManager (liquibase 4.17.0 API)

What should be done to fix this? It happens when attempting concurrent updates to a database, as the title suggests.