summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorPankrat <lhaehne@gmail.com>2016-01-30 21:46:28 +0100
committerTim Graham <timograham@gmail.com>2016-02-05 09:09:05 -0500
commitf91a04621ea8d7a657ff755645d823026257e898 (patch)
tree2b06f3ce1cbb8e5f04499838154cf715ff76ce5b /docs
parent0edb8a146fd6c60f4c3b1ad0a4a89963962f22af (diff)
Fixed #25833 -- Added support for non-atomic migrations.
Added the Migration.atomic attribute which can be set to False for non-atomic migrations.
Diffstat (limited to 'docs')
-rw-r--r--docs/howto/writing-migrations.txt47
-rw-r--r--docs/ref/migration-operations.txt20
-rw-r--r--docs/releases/1.10.txt3
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
~~~~~~