Liquibase–JDBC driver: graceful cancellation and timeout handling for changeSets
0 reputation · 20 Sept 2026, 07:30 UTC
0 reputation · 20 Sept 2026, 07:30 UTC
Defining the expected behavior when a changeSet is cancelled or exceeds a time limit is the primary goal.
Liquibase currently lacks a native cancellation API; JDBC‑level socket or login timeouts can abort the statement but may leave the database in a partially applied state if the changeSet is not transactional.
The runInTransaction flag rolls back a failed changeSet, yet thread interruption is not handled, so hanging threads can remain.
An unresolved design decision is whether to introduce a changeSet‑level timeout property and how cancellation should be propagated to the driver and the Liquibase runtime.
When a Liquibase changeSet is cancelled or exceeds a time limit, the runtime behavior depends on the executor configuration and the transactional mode of the changeSet. Liquibase does not provide a native per-changeSet cancellation API; instead, timeout handling occurs at the JDBC statement level or through a global system property. If a changeSet runs with runInTransaction enabled (the default for most databases), any exception, including SQLTimeoutException, triggers a transactional rollback, leaving the database in the state prior to the changeSet's execution. However, if the changeSet declares runInTransaction=false, the failure is recorded as FAILED in the DATABASECHANGELOG, but any DDL or DML already transmitted to the database persists. This means non-idempotent changeSets can leave the database in a partially applied state, requiring manual rollback scripts or idempotent design. Additionally, JDBC-level timeouts via Statement.setQueryTimeout() can abort a statement after a configured duration, but the driver's SQLTimeoutException may not immediately cancel the underlying query; the database may continue processing until completion or until the connection is closed. Thread interruption in Liquibase's ChangeSetExecutor is not handled by default, so hanging threads may continue until the JVM process terminates or a custom ServiceListener aborts the connection.
Open questions remain:
Missing diagnostic detail: Does the changeSet use runInTransaction=true or false? This determines whether a transactional rollback can cleanly undo applied changes or whether manual intervention is required.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.