Add db-migrations-flyway-liquibase: Flyway vs Liquibase migrations, rollbacks and baselines on Spring Boot 4.1
Companion code for the Flyway vs Liquibase article: checksum validation, out-of-order and repeatable migrations, baselining an existing schema, Flyway Community's undo/diff/deploy stubs, concurrent-startup locking for both tools, Liquibase changeset identity and rollback (auto-generated vs explicit), a verified Liquibase 5.0.3 filename-caching defect, the new OSS license service, the FSL license change, and running both tools against one database. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Q6XdRjtsp4862EM44T7i9a
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
========================================================
|
||||
Flyway: two versioned migrations, applied on startup
|
||||
========================================================
|
||||
captured: 2026-09-15T07:07:26.946024742Z
|
||||
|
||||
|
||||
-- flyway_schema_history --
|
||||
installed_rank | version | description | type | checksum | success
|
||||
---------------+---------+-------------------------------------------+-------+-------------+--------
|
||||
-1 | NULL | << Flyway Schema History table created >> | TABLE | NULL | true
|
||||
1 | 1 | create customer | SQL | 1461549807 | true
|
||||
2 | 2 | seed customer | SQL | -1214875726 | true
|
||||
(3 rows)
|
||||
|
||||
-- customer table --
|
||||
ID | NAME | EMAIL
|
||||
---+--------------+------------------
|
||||
1 | Ada Lovelace | [email protected]
|
||||
2 | Grace Hopper | [email protected]
|
||||
(2 rows)
|
||||
@@ -0,0 +1,16 @@
|
||||
=====================================================
|
||||
Flyway: editing an already-applied migration file
|
||||
=====================================================
|
||||
captured: 2026-09-15T07:07:27.074690371Z
|
||||
|
||||
|
||||
-- first startup — V1 applied as originally written --
|
||||
context started cleanly, V1__init.sql applied
|
||||
|
||||
-- second startup — V1__init.sql edited after being applied --
|
||||
FlywayValidateException: Validate failed: Migrations have failed validation
|
||||
Migration checksum mismatch for migration version 1
|
||||
-> Applied to database : -712784830
|
||||
-> Resolved locally : 756220147
|
||||
Either revert the changes to the migration, or run repair to update the schema history.
|
||||
Need more flexibility with validation rules? Learn more: https://help.red-gate.com/help/flyway-cli12/help_4.aspx?topic=flyway-blog/older-posts/customize-validation-rules-with-ignoremigrationpatterns
|
||||
@@ -0,0 +1,29 @@
|
||||
==============================================================================
|
||||
Flyway: a lower-versioned migration lands after a higher one is already applied
|
||||
==============================================================================
|
||||
captured: 2026-09-15T07:07:28.552801366Z
|
||||
|
||||
|
||||
-- first startup — V1 and V3 only --
|
||||
applied: V1, V3
|
||||
|
||||
-- second startup — outOfOrder=false (Flyway default) --
|
||||
context failed to start: FlywayValidateException: Validate failed: Migrations have failed validation
|
||||
Detected resolved migration not applied to database: 2.
|
||||
To ignore this migration, set -ignoreMigrationPatterns='*:ignored'. To allow executing this migration, set -outOfOrder=true.
|
||||
Need more flexibility with validation rules? Learn more: https://help.red-gate.com/help/flyway-cli12/help_4.aspx?topic=flyway-blog/older-posts/customize-validation-rules-with-ignoremigrationpatterns
|
||||
installed_rank | version | description | success
|
||||
---------------+---------+-------------------------------------------+--------
|
||||
-1 | NULL | << Flyway Schema History table created >> | true
|
||||
1 | 1 | init | true
|
||||
2 | 3 | add note index | true
|
||||
(3 rows)
|
||||
|
||||
-- third startup — outOfOrder=true --
|
||||
installed_rank | version | description | success
|
||||
---------------+---------+-------------------------------------------+--------
|
||||
-1 | NULL | << Flyway Schema History table created >> | true
|
||||
1 | 1 | init | true
|
||||
2 | 3 | add note index | true
|
||||
3 | 2 | add note length check | true
|
||||
(4 rows)
|
||||
@@ -0,0 +1,36 @@
|
||||
==================================================================
|
||||
Flyway: a repeatable migration reruns on checksum change alone
|
||||
==================================================================
|
||||
captured: 2026-09-15T07:07:28.316653172Z
|
||||
|
||||
|
||||
-- first startup --
|
||||
installed_rank | version | description | type | checksum
|
||||
---------------+---------+-------------------------------------------+-------+------------
|
||||
-1 | NULL | << Flyway Schema History table created >> | TABLE | NULL
|
||||
1 | 1 | init | SQL | -192856793
|
||||
2 | NULL | invoice summary view | SQL | -2025099931
|
||||
(3 rows)
|
||||
|
||||
-- invoice_summary right after creation --
|
||||
STATUS | CNT
|
||||
--------+----
|
||||
PAID | 1
|
||||
PENDING | 1
|
||||
(2 rows)
|
||||
|
||||
-- second startup — only R__invoice_summary_view.sql changed --
|
||||
installed_rank | version | description | type | checksum
|
||||
---------------+---------+-------------------------------------------+-------+------------
|
||||
-1 | NULL | << Flyway Schema History table created >> | TABLE | NULL
|
||||
1 | 1 | init | SQL | -192856793
|
||||
2 | NULL | invoice summary view | SQL | -2025099931
|
||||
3 | NULL | invoice summary view | SQL | 750256380
|
||||
(4 rows)
|
||||
|
||||
-- invoice_summary after the repeatable migration reran --
|
||||
STATUS | CNT | TOTAL_CENTS
|
||||
--------+-----+------------
|
||||
PAID | 1 | 5000
|
||||
PENDING | 1 | 3000
|
||||
(2 rows)
|
||||
@@ -0,0 +1,22 @@
|
||||
==================================================
|
||||
Flyway: adopting an existing, unmanaged schema
|
||||
==================================================
|
||||
captured: 2026-09-15T07:07:29.126413637Z
|
||||
|
||||
|
||||
-- migrate() with no baseline configuration, against a non-empty schema --
|
||||
FlywayException: Found non-empty schema(s) "PUBLIC" but no schema history table. Use baseline() or set baselineOnMigrate to true to initialize the schema history table.
|
||||
|
||||
-- migrate() with baselineOnMigrate=true, baselineVersion=1 --
|
||||
installed_rank | version | description | type | success
|
||||
---------------+---------+-------------------------------------------+----------+--------
|
||||
-1 | NULL | << Flyway Schema History table created >> | TABLE | true
|
||||
1 | 1 | pre-flyway schema | BASELINE | true
|
||||
2 | 2 | add status column | SQL | true
|
||||
(3 rows)
|
||||
|
||||
-- legacy_account keeps its pre-existing row and gains the new column --
|
||||
ID | OWNER | STATUS
|
||||
---+-----------------+-------
|
||||
1 | pre-flyway-data | ACTIVE
|
||||
(1 row)
|
||||
@@ -0,0 +1,8 @@
|
||||
==============================================================
|
||||
Flyway: calling the public undo() API on the Community jar
|
||||
==============================================================
|
||||
captured: 2026-09-15T07:07:29.409916017Z
|
||||
|
||||
flyway.undo() threw: org.flywaydb.core.internal.license.FlywayRedgateEditionRequiredException
|
||||
message: Flyway Redgate Edition Required: undo is not supported by OSS Edition
|
||||
Download Redgate Edition for free: https://rd.gt/3GGIXhh
|
||||
@@ -0,0 +1,17 @@
|
||||
==============================================================================
|
||||
Flyway: every command name that resolves to a Redgate-edition-required stub in flyway-core
|
||||
==============================================================================
|
||||
captured: 2026-09-15T07:07:26.936295299Z
|
||||
|
||||
- auth
|
||||
- check
|
||||
- deploy
|
||||
- diff
|
||||
- difftext
|
||||
- generate
|
||||
- licensingconfigurationextensionstub.class
|
||||
- model
|
||||
- offlinepermitconfigurationextensionstub.class
|
||||
- pattokenconfigurationextensionstub.class
|
||||
- prepare
|
||||
- undo
|
||||
@@ -0,0 +1,15 @@
|
||||
==============================================================
|
||||
Flyway: two instances calling migrate() at the same moment
|
||||
==============================================================
|
||||
captured: 2026-09-15T07:07:28.249758300Z
|
||||
|
||||
instance A migrate() took 932ms
|
||||
instance B migrate() took 910ms
|
||||
wall-clock time for both, run concurrently: 937ms
|
||||
|
||||
-- flyway_schema_history after both finished --
|
||||
installed_rank | version | description | success
|
||||
---------------+---------+-------------------------------------------+--------
|
||||
-1 | NULL | << Flyway Schema History table created >> | true
|
||||
1 | 1 | SlowMigration | true
|
||||
(2 rows)
|
||||
@@ -0,0 +1,18 @@
|
||||
=================================================
|
||||
Liquibase: two changesets, applied on startup
|
||||
=================================================
|
||||
captured: 2026-09-15T07:07:15.896321149Z
|
||||
|
||||
|
||||
-- databasechangelog --
|
||||
ID | AUTHOR | FILENAME | ORDEREXECUTED | EXECTYPE
|
||||
-----------------+--------+-------------+---------------+---------
|
||||
1-create-account | ankurm | master.yaml | 1 | EXECUTED
|
||||
2-seed-account | ankurm | master.yaml | 2 | EXECUTED
|
||||
(2 rows)
|
||||
|
||||
-- account table --
|
||||
ID | OWNER
|
||||
---+------------------
|
||||
1 | Katherine Johnson
|
||||
(1 row)
|
||||
@@ -0,0 +1,12 @@
|
||||
======================================================
|
||||
Liquibase: auto-generated rollback for createTable
|
||||
======================================================
|
||||
captured: 2026-09-15T07:07:16.057288822Z
|
||||
|
||||
after update(): session table exists = true
|
||||
after rollback(1): session table exists = false
|
||||
|
||||
-- databasechangelog after rollback --
|
||||
ID | EXECTYPE
|
||||
---+---------
|
||||
(0 rows)
|
||||
@@ -0,0 +1,8 @@
|
||||
========================================================================
|
||||
Liquibase: rolling back an insert changeset with no <rollback> block
|
||||
========================================================================
|
||||
captured: 2026-09-15T07:07:26.800580455Z
|
||||
|
||||
after update(): both changesets applied
|
||||
rollback(1) threw: liquibase.exception.CommandExecutionException
|
||||
message: liquibase.exception.LiquibaseException: liquibase.exception.RollbackFailedException: liquibase.exception.RollbackImpossibleException: No inverse to liquibase.change.core.InsertDataChange created
|
||||
@@ -0,0 +1,16 @@
|
||||
===================================================================
|
||||
Liquibase: the same insert, now with an explicit rollback block
|
||||
===================================================================
|
||||
captured: 2026-09-15T07:07:16.370040970Z
|
||||
|
||||
|
||||
-- audit_log right after update() --
|
||||
ID | EVENT
|
||||
---+-------------
|
||||
1 | system-start
|
||||
(1 row)
|
||||
|
||||
-- audit_log after rollback(1) — table still exists, the row is gone --
|
||||
ID | EVENT
|
||||
---+------
|
||||
(0 rows)
|
||||
@@ -0,0 +1,20 @@
|
||||
================================================================
|
||||
Liquibase: two instances calling update() at the same moment
|
||||
================================================================
|
||||
captured: 2026-09-15T07:07:26.705434740Z
|
||||
|
||||
instance A update() took 874ms
|
||||
instance B update() took 10097ms
|
||||
wall-clock time for both, run concurrently: 10099ms
|
||||
|
||||
-- databasechangeloglock after both finished --
|
||||
ID | LOCKED | LOCKEDBY
|
||||
---+--------+---------
|
||||
1 | false | NULL
|
||||
(1 row)
|
||||
|
||||
-- databasechangelog after both finished --
|
||||
ID | AUTHOR | EXECTYPE
|
||||
--------------+--------+---------
|
||||
1-slow-change | ankurm | EXECUTED
|
||||
(1 row)
|
||||
@@ -0,0 +1,9 @@
|
||||
==============================================================================
|
||||
Liquibase: the LicenseService actually wired up on the classpath Boot uses
|
||||
==============================================================================
|
||||
captured: 2026-09-15T07:07:16.051670223Z
|
||||
|
||||
implementation: liquibase.license.OSSLicenseService
|
||||
licenseIsInstalled(): false
|
||||
licenseIsValid("any"): false
|
||||
getLicenseInfo(): ""
|
||||
@@ -0,0 +1,34 @@
|
||||
=======================================================================
|
||||
Flyway and Liquibase, both enabled: the naive failure, then the fix
|
||||
=======================================================================
|
||||
captured: 2026-09-15T07:07:11.366831858Z
|
||||
|
||||
|
||||
-- naive: both enabled, no other configuration --
|
||||
context failed to start: FlywayException: Found non-empty schema(s) "PUBLIC" but no schema history table. Use baseline() or set baselineOnMigrate to true to initialize the schema history table.
|
||||
|
||||
-- fixed: spring.flyway.baseline-on-migrate=true, spring.flyway.baseline-version=0 --
|
||||
TABLE_NAME
|
||||
---------------------
|
||||
CUSTOMER
|
||||
DATABASECHANGELOG
|
||||
DATABASECHANGELOGLOCK
|
||||
PRODUCT
|
||||
flyway_schema_history
|
||||
(5 rows)
|
||||
|
||||
-- flyway_schema_history — baseline row at 0, then V1/V2 ran for real --
|
||||
version | description | type | success
|
||||
--------+-------------------------------------------+----------+--------
|
||||
NULL | << Flyway Schema History table created >> | TABLE | true
|
||||
0 | << Flyway Baseline >> | BASELINE | true
|
||||
1 | create customer | SQL | true
|
||||
2 | seed customer | SQL | true
|
||||
(4 rows)
|
||||
|
||||
-- databasechangelog — Liquibase's own bookkeeping, untouched by Flyway --
|
||||
ID | AUTHOR | EXECTYPE
|
||||
-----------------+--------+---------
|
||||
1-create-product | ankurm | EXECUTED
|
||||
2-seed-product | ankurm | EXECUTED
|
||||
(2 rows)
|
||||
Reference in New Issue
Block a user