David Hang

Any sufficiently advanced technology is indistinguishable from magic - Arthur C. Clarke
< Previous -

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.

< Previous -
< Previous -