Reputation: 5242
By design the flyway migrations run in transactions and synchronously pretty early during startup of an application. This is usually desired, to ensure before business logic starts to execute the database is in a consistent state (migrated) or the migration fails and the app crashes.
In some cases I'd really like to be able to start the application without it waiting for some migrations to be completed (long running migrations, creating indexes or materialized views, etc.). This might also be needed when deploying from a CI-Server and using deploy-timeouts / health-checks (that can not be raised indefinitely) to ensure the deployment worked as expected.
Is there any configuration / convention / best practice to enable async migrations?
(i.e. naming the migration A2_00__UpdateSthLong.sql
instead of V2 (standard) or R2 (Repeatable migration).
Upvotes: 4
Views: 2669
Reputation: 874
Async Flyway migration
If you run a long Flyway migration on start up, the application will not start and will not accept requests until it's finished.
You can just run Flyway by yourself after the start.
To disable boot for Flyway, insert into resources/application.properties
:
spring.flyway.enabled=false
Add Configuration with a Timer
, make sure task starts after application is booted completely (After message Started Application in N seconds (JVM running for N)
):
@Configuration
public class FlywayConfiguration {
public FlywayConfiguration(DataSource dataSource) {
Flyway flyway = Flyway.configure().dataSource(dataSource).load();
TimerTask task = new TimerTask() {
public void run() {
flyway.migrate();
}
};
Timer timer = new Timer("Flyway-async-migration");
long delay = Duration.of(20, ChronoUnit.SECONDS).toMillis();
timer.schedule(task, delay);
}
}
Warning: Be careful with ALTER TABLE
migrations on large tables on running systems, better run them before the application starts. ADD COLUMN
without default value should be OK, but almost everything else not.
Async non-locking indexing
If you would like to create an index for a huge table, I would also recommend to use CREATE INDEX CONCURRENTLY
(Postgres) or something similar for other DBs for non-locking indexing. Otherwise it will lock the table until it's complete and requests/connections would hang waiting for it.
But to make it work (at least for Postgres) you have to add an extra conf file for such migrations.
V99__create-index-concurrently.sql
CREATE INDEX CONCURRENTLY ...;
V99__create-index-concurrently.sql.conf
:
executeInTransaction=false
For Flyway 9.12+ you also require to add to resources/application.properties
:
spring.flyway.postgresql.transactional-lock=false
Upvotes: 0
Reputation: 5242
Seems like its not possible (yet):
There is an issue requesting this on github: https://github.com/flyway/flyway/issues/950
Flyway for micronaut, seems to already support this: https://github.com/flyway/flyway/issues/950
A temp solution until support is integrated could be to use Java Migrations and spawn an async-Task from within the migrate
method yourself. The migration wouldn't be transactional then of course :(
Another solution might be to do the migration before actually starting up the application (i.e. by using the maven task).
Upvotes: 2