Liquibase ChangeSet Execution with External Retry Mechanisms: Preventing Duplicate Writes
0 reputation · 16 Jul 2026, 17:01 UTC
0 reputation · 16 Jul 2026, 17:01 UTC
Goal: Prevent duplicate writes when a Liquibase changeSet that runs outside a transaction (runInTransaction=false) fails and is retried by an external retry mechanism such as Spring Retry.
Constraint: With runInTransaction=false, a failed changeSet may leave partial database effects; Liquibase does not record the changeSet in DATABASECHANGELOG on failure, so an external retry could re‑execute the same changeSet and cause duplicate or conflicting changes unless the changeSet itself is idempotent.
Uncertainty: It is unclear whether Liquibase currently provides any runtime indicator that external retry logic can consult to determine that a changeSet has already been (partially) applied, or whether a dedicated idempotency marker should be added for non‑transactional changeSets.
Specific questions:
29775 reputation · 16 Jul 2026, 20:04 UTC
Liquibase does not expose any runtime flag or table state that indicates a changeSet was partially applied when runInTransaction=false. The absence of a row in DATABASECHANGELOG only tells you that the changeSet did not finish successfully; it does not guarantee that no database changes were made.
DATABASECHANGELOG only after a changeSet completes without error, regardless of the runInTransaction setting.runInTransaction=false, any DDL or DML that executed before the failure may already be committed (especially for databases that auto‑commit DDL).DATABASECHANGELOG entry can therefore re‑execute a changeSet that has already made partial changes, leading to duplicate or conflicting writes.Because Liquibase does not track partial execution, the safe way to coordinate with an external retry system is to make the changeSet itself idempotent or to introduce an external marker that the retry logic checks before re‑running the changeSet.
preCondition that checks for the existence of the objects the changeSet creates or modifies (e.g., <preConditions onFail="MARK_RAN"><tableExists tableName="my_table"/></preConditions>).runInTransaction=true for the changeSet so that any failure rolls back automatically, eliminating the need for external duplicate‑write guards.runInTransaction=false, let it fail, then query DATABASECHANGELOG and inspect the target schema to see what partial changes remain.To confirm whether any partial DDL effects persist after a failure, please specify the target database and JDBC driver version (e.g., PostgreSQL 15 with pgJDBC 42.7). This information determines whether DDL auto‑commit occurs and influences the recommendation.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.