Deadlocks and DDL on Postgres
The framework with which I have the most professional experience is Django. It has a good ORM which will generate “migration” files for any changes you do to the models. Often this can lead to one file with multiple DDL changes. As I found out, this can cause deadlocks when you are running migrations on a live production system. With Django, if your database backend is Postgres or SQLite it will perform database migrations transactionally.
We had a large migration file generated with changes to multiple tables. If during the migration another process tries to access both tables, it can cause a deadlock and hence cause the query or migration to fail after a while.
This can be avoided if migrations in a transaction is only kept to a single
table. This can be done by having separate migration files for each table. In our
case, we had already run the migrations on staging and wanted to keep the
migrations in sync with the production database and could not have “different”
migrations (additional). We ended being able to modify the existing failed migration file
and made all the DDL changes non-atomic with the atomic = False
option.
from django.db import migrations
class Migration(migrations.Migration):
atomic = False # if this is not set, then both migrations will be run in the same transaction
operations = [
migrations.AddField(
model_name="model_1
name="column_1",
field=models.DecimalField(decimal_places=4, max_digits=16, null=True),
),
migrations.AddField(
model_name="model_2",
name="column_2",
field=models.DecimalField(decimal_places=4, max_digits=16, null=True),
),
...
]
Hopefully, this helps someone else out there who encounters a similar issue.