Thread-safety of alembic.op #1163
-
We have an application with schema-based multi-tenancy. Migrations are run by our database tool which internally uses alembic . We need to migrate a lot of databases, so we would like to do in parallel. But there is an issue with alembic.op (and AFAIU alembic.context). It is not thread-safe. E. g. if one As far as I can see, there are multiple workarounds. E. g. we could pass I would be glad to hear any thoughts on this issue. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 4 replies
-
that's correct, alembic.op is a global variable that is established within the scope of where env.py calls upon
yes, you could do that, and it would not be too difficult. Look at the source (Well I think you did) to EnvironmentContext..run_migrations() and Operations.context() and we could write this to not use the global op namespace as: def run_migrations_online() -> None:
connectable = engine_from_config(
config.get_section(config.config_ini_section),
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata,
)
with context.begin_transaction():
migration_context = context.get_context()
op = Operations(migration_context)
migration_context.run_migrations(op=op) then you would have this is simple and useful enough that I could support adding a new template to Alembic for this; as a calling style, not as having any multithreading in the template itself. As far as running multiple threads, you would still need to be careful that this occurs only for upgrade/downgrade operations and not operations that write into the ScriptDirectory, etc. The other way to do it, and this might be better anyway for actual "parallelism", is to use multiprocessing instead of threading. Then you only need spin up workers inside of your env.py (I assume these databases all have their own for any of these approaches, the main thing to be concerned about is that you are not changing the scripts folder with multiple commands at once (should be fine for upgrade/downgrade) and for any particular database / alembic_version table, only one connection at a time upgrades that particular database. |
Beta Was this translation helpful? Give feedback.
that's correct, alembic.op is a global variable that is established within the scope of where env.py…