|
| 1 | += Aviate Database Migrations |
| 2 | + |
| 3 | +This guide explains how Aviate manages database schema migrations and how to validate that migrations have been applied successfully. |
| 4 | + |
| 5 | +For plugin installation steps, see |
| 6 | +link:https://docs.killbill.io/latest/how-to-install-the-aviate-plugin[How to Install the Aviate Plugin]. |
| 7 | + |
| 8 | +By default, Aviate runs database migrations automatically at startup. This behavior is controlled by the following property: |
| 9 | + |
| 10 | +---- |
| 11 | +com.killbill.billing.plugin.aviate.enableMigrations=true |
| 12 | +---- |
| 13 | + |
| 14 | +When enabled, Flyway initializes the Aviate schema and applies all pending migrations during plugin startup. |
| 15 | + |
| 16 | +== How Aviate Manages Database Migrations |
| 17 | + |
| 18 | +Aviate uses Flyway to version and apply database schema changes. |
| 19 | + |
| 20 | +At startup, Flyway: |
| 21 | + |
| 22 | +* Creates the `aviate_schema_history` table if it does not already exist |
| 23 | +* Applies migrations in version order |
| 24 | +* Tracks applied migrations to prevent duplicate or partial execution |
| 25 | + |
| 26 | + |
| 27 | +== Migration Scenarios |
| 28 | + |
| 29 | +=== Scenario 1: Fresh Install (No Existing Aviate Schema) |
| 30 | + |
| 31 | +This scenario applies to brand-new installations where Aviate has never been started against the target database. |
| 32 | + |
| 33 | +==== Symptoms |
| 34 | + |
| 35 | +* No `aviate_*` tables exist. |
| 36 | +* The `aviate_schema_history` table is not present. |
| 37 | + |
| 38 | +==== Expected Action |
| 39 | + |
| 40 | +Start the Aviate plugin. Flyway will automatically: |
| 41 | + |
| 42 | +* Create the schema history table |
| 43 | +* Apply all migrations |
| 44 | +* Initialize the Aviate schema |
| 45 | + |
| 46 | +No manual intervention is required. |
| 47 | + |
| 48 | +==== What to Verify |
| 49 | + |
| 50 | +After the plugin starts successfully: |
| 51 | + |
| 52 | + 1. Confirm that the schema history table exists: |
| 53 | + |
| 54 | + ---- |
| 55 | + SHOW TABLES LIKE 'aviate_schema_history'; |
| 56 | + ---- |
| 57 | + |
| 58 | + |
| 59 | + 2. Verify that migrations were applied: |
| 60 | + |
| 61 | + ---- |
| 62 | + SELECT version, description, success |
| 63 | + FROM aviate_schema_history |
| 64 | + ORDER BY installed_rank DESC; |
| 65 | + ---- |
| 66 | + |
| 67 | + All rows should show: |
| 68 | + |
| 69 | + ---- |
| 70 | + success = 1 |
| 71 | + ---- |
| 72 | + |
| 73 | + 3. Confirm that the expected `aviate_*` tables are present. |
| 74 | + |
| 75 | +==== Expected Logs |
| 76 | + |
| 77 | +Look for log entries similar to the following: |
| 78 | + |
| 79 | +---- |
| 80 | +Migrations are enabled. Starting migration process... |
| 81 | +Schema history table `killbill`.`aviate_schema_history` does not exist yet |
| 82 | +Successfully validated 16 migrations (execution time 00:00.026s) |
| 83 | +Successfully applied 16 migrations to schema `killbill`, now at version v1.16.0 (execution time 00:07.871s) |
| 84 | +Migration process completed successfully |
| 85 | +---- |
| 86 | + |
| 87 | +=== Scenario 2 — Existing Aviate Schema but No `aviate_schema_history` (Adopting into Flyway) |
| 88 | + |
| 89 | +This scenario occurs when Aviate tables already exist in the database, but Flyway has never been used to track migrations. |
| 90 | + |
| 91 | +This is common when the schema was created manually. |
| 92 | + |
| 93 | +==== Symptoms |
| 94 | + |
| 95 | +* `aviate_*` tables exist. |
| 96 | +* The `aviate_schema_history` table is missing. |
| 97 | + |
| 98 | +==== Failure Mode |
| 99 | + |
| 100 | +When the plugin starts, Flyway assumes the database is empty and attempts to run the initial migrations. |
| 101 | + |
| 102 | +Since the tables already exist, the migration fails with errors similar to: |
| 103 | + |
| 104 | +---- |
| 105 | +Schema history table `killbill`.`aviate_schema_history` does not exist yet |
| 106 | +Creating Schema History table `killbill`.`aviate_schema_history` with baseline ... |
| 107 | +Migrating schema `killbill` to version "1.1.0 - Initial version" |
| 108 | +Error: 1050-42S01: Table 'aviate_hosts' already exists |
| 109 | +---- |
| 110 | + |
| 111 | +Subsequent restarts continue to fail because Flyway retries the same migration. |
| 112 | + |
| 113 | +==== Root Cause |
| 114 | + |
| 115 | +Flyway has no record of previously applied migrations and cannot determine the current schema version. |
| 116 | + |
| 117 | +The database must be baselined so Flyway can begin tracking migrations from the correct version. |
| 118 | + |
| 119 | +Selecting the wrong baseline version can cause Flyway to either: |
| 120 | + |
| 121 | +* Re-run migrations against existing objects, or |
| 122 | +* Skip required migrations, leading to runtime failures. |
| 123 | + |
| 124 | +Always validate the baseline version before proceeding. |
| 125 | + |
| 126 | +==== Resolution — Align Flyway with the Existing Schema (Baselining) |
| 127 | + |
| 128 | +When migrations are enabled (`com.killbill.billing.plugin.aviate.enableMigrations=true`), Flyway automatically creates the `aviate_schema_history` table and attempts to apply migrations. |
| 129 | +If the schema already exists, Flyway must be aligned with the current database state by setting the correct baseline. |
| 130 | + |
| 131 | +===== Step 1 — Identify the Aviate Plugin Version That Created the Schema |
| 132 | + |
| 133 | +The KPM bundles directory contains the migration files packaged with each installed Aviate plugin version. |
| 134 | + |
| 135 | +The path is controlled by: |
| 136 | + |
| 137 | +---- |
| 138 | +org.killbill.billing.plugin.kpm.bundlesPath |
| 139 | +---- |
| 140 | + |
| 141 | +Default path: |
| 142 | + |
| 143 | +---- |
| 144 | +/var/lib/killbill/bundles |
| 145 | +---- |
| 146 | + |
| 147 | +Example: |
| 148 | + |
| 149 | +---- |
| 150 | +/var/lib/killbill/bundles/plugins/java/aviate-plugin/ |
| 151 | +├── 1.0.18 |
| 152 | +├── 1.0.19 |
| 153 | +├── 1.0.27 |
| 154 | +└── SET_DEFAULT |
| 155 | +---- |
| 156 | + |
| 157 | +Each version contains a plugin JAR: `aviate-plugin-<version>.jar` |
| 158 | + |
| 159 | +Locate the Aviate plugin version whose migrations most closely match the existing database schema. |
| 160 | + |
| 161 | +• If the schema origin is known, use that plugin version. |
| 162 | +• Otherwise, start with the latest installed version and compare its migrations against the database. |
| 163 | + |
| 164 | +Extract the plugin JAR: |
| 165 | +---- |
| 166 | +unzip aviate-plugin-1.0.19.jar -d aviate-plugin-1.0.19 |
| 167 | +---- |
| 168 | + |
| 169 | +Then inspect: |
| 170 | +---- |
| 171 | +db/migration/mysql |
| 172 | +
|
| 173 | +or |
| 174 | +
|
| 175 | +db/migration/postgresql |
| 176 | +---- |
| 177 | + |
| 178 | +Migration files follow the following format: |
| 179 | + |
| 180 | +---- |
| 181 | +aviateV1.1.0__Initial_version.sql |
| 182 | +aviateV1.2.0__catalog_usage.sql |
| 183 | +aviateV1.3.0__catalog_meter.sql |
| 184 | +---- |
| 185 | + |
| 186 | +The last migration file represents the schema version created by that plugin release. |
| 187 | + |
| 188 | +Example: |
| 189 | + |
| 190 | +---- |
| 191 | +aviateV1.7.0__ledger.sql |
| 192 | +---- |
| 193 | + |
| 194 | +✅ Baseline version = **1.7.0** |
| 195 | + |
| 196 | +===== Step 2 — Check for Failed Migrations |
| 197 | +---- |
| 198 | +SELECT * FROM aviate_schema_history; |
| 199 | +---- |
| 200 | +If a row shows: |
| 201 | +---- |
| 202 | +success = 0 |
| 203 | +---- |
| 204 | + |
| 205 | +remove **only that failed entry**: |
| 206 | + |
| 207 | +---- |
| 208 | +DELETE FROM aviate_schema_history |
| 209 | +WHERE success = 0; |
| 210 | +---- |
| 211 | + |
| 212 | +===== Step 3 — Insert the Correct Baseline |
| 213 | + |
| 214 | +Insert a row matching the schema already present in the database. |
| 215 | + |
| 216 | +Example: |
| 217 | + |
| 218 | +---- |
| 219 | +INSERT INTO aviate_schema_history |
| 220 | +(installed_rank, version, description, type, script, installed_by, execution_time, success) |
| 221 | +VALUES |
| 222 | +(2, '1.7.0', '<< Flyway Baseline >>', 'BASELINE', 'aviateV1.7.0__ledger.sql', CURRENT_USER(), 0, 1); |
| 223 | +---- |
| 224 | + |
| 225 | +===== Step 4 — Restart the Aviate Plugin |
| 226 | + |
| 227 | +On startup: |
| 228 | + |
| 229 | +* Flyway detects the baseline. |
| 230 | + |
| 231 | +* Older migrations are skipped. |
| 232 | + |
| 233 | +* Only newer migrations are applied. |
| 234 | + |
| 235 | +==== Verification |
| 236 | + |
| 237 | +---- |
| 238 | +SELECT installed_rank, version, success |
| 239 | +FROM aviate_schema_history; |
| 240 | +---- |
| 241 | + |
| 242 | +Confirm: |
| 243 | + |
| 244 | +* No rows with success = 0 |
| 245 | + |
| 246 | +* Baseline version is present |
| 247 | + |
| 248 | +* New migrations complete successfully |
0 commit comments