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
57 lines
3.7 KiB
Markdown
57 lines
3.7 KiB
Markdown
# 6. Baselining an existing database
|
|
|
|
[← 5. Repeatable migrations](05-repeatable-migrations.md) · [Index](../README.md) · Next: [7. Why there is no undo →](07-why-there-is-no-undo.md)
|
|
|
|
Every migration tool eventually meets a database it didn't create. Someone hand-ran DDL for five
|
|
years, and now the team wants Flyway to take over from here — without dropping the schema and
|
|
replaying history that never actually happened through Flyway.
|
|
|
|
[`FlywayBaselineTest`](../src/test/java/com/ankurm/dbmigrations/flyway/FlywayBaselineTest.java)
|
|
sets this up literally: a `legacy_account` table is created with plain JDBC, with one row already
|
|
in it, *before Flyway is ever involved*. Pointing an unconfigured Flyway at that database refuses
|
|
outright — this is the same safety check from chapter [1](01-the-problem-and-mental-model.md), and
|
|
it's what makes baselining necessary rather than optional:
|
|
|
|
```
|
|
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.
|
|
```
|
|
|
|
Turning on `spring.flyway.baseline-on-migrate=true` (with `baseline-version=1` and a
|
|
`baseline-description`) fixes it. `V1__init.sql` — written to describe the schema that *already
|
|
exists* — never actually runs; instead Flyway inserts a `BASELINE`-typed row claiming version 1 is
|
|
already accounted for, and only `V2__add_status_column.sql` executes for real:
|
|
|
|
```
|
|
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
|
|
```
|
|
|
|
(from [`docs/output/05-flyway-baseline.txt`](output/05-flyway-baseline.txt))
|
|
|
|
The pre-existing row survives untouched, and gains the new column:
|
|
|
|
```
|
|
ID | OWNER | STATUS
|
|
---+-----------------+-------
|
|
1 | pre-flyway-data | ACTIVE
|
|
```
|
|
|
|
<blockquote style="border-left:4px solid #ca8a04;background:#fefce8;padding:12px 16px;margin:16px 0;">
|
|
<strong>Trap:</strong> the baseline row's <code>description</code> is not a fixed string. It is
|
|
exactly whatever <code>spring.flyway.baseline-description</code> was set to — in this test,
|
|
literally <code>"pre-flyway schema"</code>. A different, fixed marker — <code><< Flyway
|
|
Schema History table created >></code> — belongs to a <em>different</em> row (rank
|
|
<code>-1</code>, type <code>TABLE</code>), created the moment the history table itself is created,
|
|
whether or not baselining ever happens. Confusing the two is an easy way to write a broken
|
|
assertion or a broken monitoring query — this module's own first draft did exactly that.
|
|
</blockquote>
|
|
|
|
## Going deeper
|
|
|
|
- **`baselineVersion` decides what "already accounted for" means**, and it matters which value you pick — chapter [14](14-running-both-at-once.md) shows the same mechanism used with `baseline-version=0` instead of `1`, for a database whose existing schema *doesn't* match any of your migration files at all.
|
|
- [Flyway `baseline` command reference](https://documentation.red-gate.com/flyway/flyway-cli-and-api/commands/baseline) (`rel="nofollow"`) — the one-time `flyway baseline` CLI/API call this test's `baselineOnMigrate=true` triggers automatically on first startup.
|
|
- Baselining is a one-way door in the sense that matters: once version 1 is marked as baselined, Flyway will never again check whether the schema it describes actually matches `V1__init.sql`'s content — that specific file's checksum is simply never looked at again for this database.
|