diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/howto/writing-migrations.txt | 47 | ||||
| -rw-r--r-- | docs/ref/migration-operations.txt | 20 | ||||
| -rw-r--r-- | docs/releases/1.10.txt | 3 |
3 files changed, 64 insertions, 6 deletions
diff --git a/docs/howto/writing-migrations.txt b/docs/howto/writing-migrations.txt index 552035b7c2..adef507fa8 100644 --- a/docs/howto/writing-migrations.txt +++ b/docs/howto/writing-migrations.txt @@ -184,6 +184,53 @@ the respective field according to your needs. migration is running. Objects created after the ``AddField`` and before ``RunPython`` will have their original ``uuid``’s overwritten. +.. _non-atomic-migrations: + +Non-atomic migrations +~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 1.10 + +On databases that support DDL transactions (SQLite and PostgreSQL), migrations +will run inside a transaction by default. For use cases such as performing data +migrations on large tables, you may want to prevent a migration from running in +a transaction by setting the ``atomic`` attribute to ``False``:: + + from django.db import migrations + + class Migration(migrations.Migration): + atomic = False + +Within such a migration, all operations are run without a transaction. It's +possible to execute parts of the migration inside a transaction using +:func:`~django.db.transaction.atomic()` or by passing ``atomic=True`` to +``RunPython``. + +Here's an example of a non-atomic data migration that updates a large table in +smaller batches:: + + import uuid + + from django.db import migrations, transaction + + def gen_uuid(apps, schema_editor): + MyModel = apps.get_model('myapp', 'MyModel') + while MyModel.objects.filter(uuid__isnull=True).exists(): + with transaction.atomic(): + for row in MyModel.objects.filter(uuid__isnull=True)[:1000]: + row.uuid = uuid.uuid4() + row.save() + + class Migration(migrations.Migration): + atomic = False + + operations = [ + migrations.RunPython(gen_uuid), + ] + +The ``atomic`` attribute doesn't have an effect on databases that don't support +DDL transactions (e.g. MySQL, Oracle). + Controlling the order of migrations =================================== diff --git a/docs/ref/migration-operations.txt b/docs/ref/migration-operations.txt index e7fb9793e2..c8668d108e 100644 --- a/docs/ref/migration-operations.txt +++ b/docs/ref/migration-operations.txt @@ -269,7 +269,7 @@ be removed (elided) when :ref:`squashing migrations <migration-squashing>`. ``RunPython`` ------------- -.. class:: RunPython(code, reverse_code=None, atomic=True, hints=None, elidable=False) +.. class:: RunPython(code, reverse_code=None, atomic=None, hints=None, elidable=False) Runs custom Python code in a historical context. ``code`` (and ``reverse_code`` if supplied) should be callable objects that accept two arguments; the first is @@ -354,16 +354,19 @@ the ``schema_editor`` provided on these backends; in this case, pass On databases that do support DDL transactions (SQLite and PostgreSQL), ``RunPython`` operations do not have any transactions automatically added -besides the transactions created for each migration (the ``atomic`` parameter -has no effect on these databases). Thus, on PostgreSQL, for example, you should -avoid combining schema changes and ``RunPython`` operations in the same -migration or you may hit errors like ``OperationalError: cannot ALTER TABLE -"mytable" because it has pending trigger events``. +besides the transactions created for each migration. Thus, on PostgreSQL, for +example, you should avoid combining schema changes and ``RunPython`` operations +in the same migration or you may hit errors like ``OperationalError: cannot +ALTER TABLE "mytable" because it has pending trigger events``. If you have a different database and aren't sure if it supports DDL transactions, check the ``django.db.connection.features.can_rollback_ddl`` attribute. +If the ``RunPython`` operation is part of a :ref:`non-atomic migration +<non-atomic-migrations>`, the operation will only be executed in a transaction +if ``atomic=True`` is passed to the ``RunPython`` operation. + .. warning:: ``RunPython`` does not magically alter the connection of the models for you; @@ -382,6 +385,11 @@ attribute. The ``elidable`` argument was added. +.. versionchanged:: 1.10 + + The ``atomic`` argument default was changed to ``None``, indicating that + the atomicity is controlled by the ``atomic`` attribute of the migration. + ``SeparateDatabaseAndState`` ---------------------------- diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index 76729a23be..9bfc8e4517 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -258,6 +258,9 @@ Migrations :class:`~django.db.migrations.operations.RunPython` operations to allow them to be removed when squashing migrations. +* Added support for :ref:`non-atomic migrations <non-atomic-migrations>` by + setting the ``atomic`` attribute on a ``Migration``. + Models ~~~~~~ |
