Flask-migrate: Should be easier to run upgrades with one transaction per version

Created on 21 Feb 2018  路  11Comments  路  Source: miguelgrinberg/Flask-Migrate

When starting from a blank database, some data migration versions fail because they rely on tables created by previous versions. This seems to be because all version upgrades are done in a single transaction.

Example:

  • Version 1 initialises the database by creating a "contact" table for the Contact class.
  • Version 2 creates a bunch of pre-defined Contact objects in the database.

When starting from a blank (PostgreSQL) database, version 2 fails because the relation "contact" does not exist yet. If you run the two versions as separate upgrades then it works fine.

It's possible to get Alembic to run migrations with one transaction per version. This makes a lot of sense because each version should stand alone, so if one fails you want to roll-back that one but not all the previous versions that succeeded. However, it's difficult to work out how to configure flask-migrate to do a transaction per version.

IMHO one transaction per version should be the default, but I'd be happy just with an easy way to enable it.

auto-closed question

Most helpful comment

Digging through the code I reckon the option can be included here:

migrate = Migrate(app, db, transaction_per_migration=True)

Maybe just add a docstring to Migrate.__init__ explaining that the kwargs are MigrationContext options?

All 11 comments

Suggested solution: add an option to the upgrade command.

flask db upgrade --commit-versions

You should post this on the Alembic bug tracker, Flask-Migrate is just a wrapper that has no way to alter how migrations are created or executed.

Sorry, I thought the migrations/env.py module was a flask-migrate thing, not provided out of the box by Alembic but created specifically for the integration with Flask.

My understanding is that you'd have to change that module to get per-version transactions. It currently runs them like this, creating a single transaction across all versions:

with context.begin_transaction():
    context.run_migrations()

The Alembic documentation on Runtime Objects mentions a transaction_per_migration option, but I couldn't work out how to pass that through the flask-migrate wrapper.

The env.py that ships with Flask-Migrate is the default env.py from Alembic with some minor changes that help the Flask integration. It is totally fine for you to make changes to it.

You can add the transaction_per_migration=True argument in env.py, right in this place.

Excellent, thanks I will give that a try.

Looks like I could also include the option in current_app.extensions['migrate'].configure_args but where is that set up?

Also, the spirit of this issue is to make it easier for people to work this out, so even though you've explained how to do it, I think the package needs to have this information in the docs or comments, or better still as an option on the db upgrade command.

Digging through the code I reckon the option can be included here:

migrate = Migrate(app, db, transaction_per_migration=True)

Maybe just add a docstring to Migrate.__init__ explaining that the kwargs are MigrationContext options?

I have added the transaction_per_migration=True argument in env.py, but I have one transaction per sql operation:

INFO [sqlalchemy.engine.base.Engine] COMMIT
INFO [sqlalchemy.engine.base.Engine] ALTER TABLE client ADD COLUMN name VARCHAR(80)
INFO [sqlalchemy.engine.base.Engine] {}
INFO [sqlalchemy.engine.base.Engine] COMMIT
INFO [sqlalchemy.engine.base.Engine] ALTER TABLE client MODIFY company VARCHAR(16) NULL
INFO [sqlalchemy.engine.base.Engine] {}
INFO [sqlalchemy.engine.base.Engine] COMMIT
INFO [sqlalchemy.engine.base.Engine] ALTER TABLE client MODIFY external_id INTEGER(11) NULL
INFO [sqlalchemy.engine.base.Engine] {}
INFO [sqlalchemy.engine.base.Engine] COMMIT

Why would this be, any idea?

@FJAbellan I honestly don't know. You are asking the wrong person, this is the issue board for Flask-Migrate, which is just a Flask friendly wrapper for Alembic. It seems you are having an issue with Alembic.

This issue will be automatically closed due to being inactive for more than six months. Please reopen if you need more assistance.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

felipejfc picture felipejfc  路  6Comments

themantalope picture themantalope  路  3Comments

asldevi picture asldevi  路  4Comments

medavis picture medavis  路  5Comments

nayefc picture nayefc  路  4Comments