@@ -6,41 +6,45 @@ Transactions
6
6
7
7
.. module :: django_mongodb_backend.transaction
8
8
9
- MongoDB supports :doc: `transactions <manual:core/transactions >` if it's configured as a
10
- :doc: `replica set <manual:replication >` or a :doc: `sharded cluster <manual:sharding >`.
9
+ MongoDB supports :doc: `transactions <manual:core/transactions >` if it's
10
+ configured as a :doc: `replica set <manual:replication >` or a :doc: `sharded
11
+ cluster <manual:sharding>`.
11
12
12
- Because MongoDB transactions have some limitations and are not meant to be used as
13
- freely as SQL transactions, :doc: `Django's transactions APIs
13
+ Because MongoDB transactions have some limitations and are not meant to be used
14
+ as freely as SQL transactions, :doc: `Django's transactions APIs
14
15
<django:topics/db/transactions>`, including most notably
15
16
:func: `django.db.transaction.atomic `, function as no-ops.
16
17
17
18
Instead, Django MongoDB Backend provides its own
18
19
:func: `django_mongodb_backend.transaction.atomic ` function.
19
20
20
- Outside of a transaction, query execution uses Django and MongoDB's default behavior of
21
- autocommit mode. Each query is immediately committed to the database.
21
+ Outside of a transaction, query execution uses Django and MongoDB's default
22
+ behavior of autocommit mode. Each query is immediately committed to the
23
+ database.
22
24
23
25
Controlling transactions
24
26
========================
25
27
26
28
.. function :: atomic(using=None)
27
29
28
- Atomicity is the defining property of database transactions. ``atomic `` allows
29
- creating a block of code within which the atomicity on the database is guaranteed.
30
- If the block of code is successfully completed, the changes are committed to the
31
- database. If there is an exception, the changes are rolled back.
30
+ Atomicity is the defining property of database transactions. ``atomic ``
31
+ allows creating a block of code within which the atomicity on the database
32
+ is guaranteed. If the block of code is successfully completed, the changes
33
+ are committed to the database. If there is an exception, the changes are
34
+ rolled back.
32
35
33
- On databases that support savepoints, ``atomic `` blocks can be nested, such that
34
- the outermost ``atomic `` starts a transaction and inner ``atomic ``\s create
35
- savepoints. Since MongoDB doesn't support savepoints, inner ``atomic `` blocks
36
- don't have any effect. The transaction commits once the outermost ``atomic `` exits.
36
+ On databases that support savepoints, ``atomic `` blocks can be nested, such
37
+ that the outermost ``atomic `` starts a transaction and inner ``atomic ``\s
38
+ create savepoints. Since MongoDB doesn't support savepoints, inner
39
+ ``atomic `` blocks don't have any effect. The transaction commits once the
40
+ outermost ``atomic `` exits.
37
41
38
42
``atomic `` is usable both as a :py:term: `decorator `::
39
43
40
44
from django_mongodb_backend import transaction
41
45
42
46
43
- @atomic
47
+ @transaction. atomic
44
48
def viewfunc(request):
45
49
# This code executes inside a transaction.
46
50
do_stuff()
@@ -54,31 +58,32 @@ Controlling transactions
54
58
# This code executes in autocommit mode (Django's default).
55
59
do_stuff()
56
60
57
- with atomic():
61
+ with transaction. atomic():
58
62
# This code executes inside a transaction.
59
63
do_more_stuff()
60
64
61
65
.. admonition :: Avoid catching exceptions inside ``atomic``!
62
66
63
- When exiting an ``atomic `` block, Django looks at whether it's exited normally
64
- or with an exception to determine whether to commit or roll back. If you catch
65
- and handle exceptions inside an ``atomic `` block, you may hide from Django the
66
- fact that a problem has happened. This can result in unexpected behavior.
67
+ When exiting an ``atomic `` block, Django looks at whether it's exited
68
+ normally or with an exception to determine whether to commit or roll
69
+ back. If you catch and handle exceptions inside an ``atomic `` block,
70
+ you may hide from Django the fact that a problem has happened. This can
71
+ result in unexpected behavior.
67
72
68
- This is mostly a concern for :exc: `~django.db.DatabaseError ` and its subclasses
69
- such as :exc: `~django.db.IntegrityError `. After such an error, the transaction
70
- is broken and Django will perform a rollback at the end of the `` atomic ``
71
- block.
73
+ This is mostly a concern for :exc: `~django.db.DatabaseError ` and its
74
+ subclasses such as :exc: `~django.db.IntegrityError `. After such an
75
+ error, the transaction is broken and Django will perform a rollback at
76
+ the end of the `` atomic `` block.
72
77
73
78
.. admonition :: You may need to manually revert app state when rolling back a transaction.
74
79
75
- The values of a model's fields won't be reverted when a transaction rollback
76
- happens. This could lead to an inconsistent model state unless you manually
77
- restore the original field values.
80
+ The values of a model's fields won't be reverted when a transaction
81
+ rollback happens. This could lead to an inconsistent model state unless
82
+ you manually restore the original field values.
78
83
79
- For example, given ``MyModel `` with an ``active `` field, this snippet ensures
80
- that the ``if obj.active `` check at the end uses the correct value if updating
81
- ``active `` to ``True `` fails in the transaction::
84
+ For example, given ``MyModel `` with an ``active `` field, this snippet
85
+ ensures that the ``if obj.active `` check at the end uses the correct
86
+ value if updating ``active `` to ``True `` fails in the transaction::
82
87
83
88
from django_mongodb_backend import transaction
84
89
from django.db import DatabaseError
@@ -94,11 +99,12 @@ Controlling transactions
94
99
if obj.active:
95
100
...
96
101
97
- This also applies to any other mechanism that may hold app state, such as
98
- caching or global variables. For example, if the code proactively updates data
99
- in the cache after saving an object, it's recommended to use
100
- :ref: `transaction.on_commit() <performing-actions-after-commit >` instead, to
101
- defer cache alterations until the transaction is actually committed.
102
+ This also applies to any other mechanism that may hold app state, such
103
+ as caching or global variables. For example, if the code proactively
104
+ updates data in the cache after saving an object, it's recommended to
105
+ use :ref: `transaction.on_commit() <performing-actions-after-commit >`
106
+ instead, to defer cache alterations until the transaction is actually
107
+ committed.
102
108
103
109
``atomic `` takes a ``using `` argument which should be the name of a
104
110
database. If this argument isn't provided, Django uses the ``"default" ``
@@ -111,17 +117,27 @@ Controlling transactions
111
117
112
118
.. admonition :: Performance considerations
113
119
114
- Open transactions have a performance cost for your database server. To minimize
115
- this overhead, keep your transactions as short as possible. This is especially
116
- important if you're using :func: `atomic ` in long-running processes, outside of
117
- Django's request / response cycle.
120
+ Open transactions have a performance cost for your database server. To
121
+ minimize this overhead, keep your transactions as short as possible. This
122
+ is especially important if you're using :func: `atomic ` in long-running
123
+ processes, outside of Django's request / response cycle.
118
124
119
125
Performing actions after commit
120
126
===============================
121
127
122
- The :func: `atomic ` function supports Django's :func: `~django.db.transaction.on_commit `
123
- API to :ref: `perform actions after a transaction successfully commits
124
- <performing-actions-after-commit>`.
128
+ The :func: `atomic ` function supports Django's
129
+ :func: `~django.db.transaction.on_commit ` API to :ref: `perform actions after a
130
+ transaction successfully commits <performing-actions-after-commit>`.
131
+
132
+ For convenience, :func: `~django.db.transaction.on_commit ` is aliased at
133
+ ``django_mongodb_backend.transaction.on_commit `` so you can use both::
134
+
135
+ from django_mongodb_backend import transaction
136
+
137
+
138
+ transaction.atomic()
139
+ transaction.on_commit(...)
140
+
125
141
126
142
.. _transactions-limitations :
127
143
@@ -132,17 +148,7 @@ MongoDB's transaction limitations that are applicable to Django are:
132
148
133
149
- :meth: `QuerySet.union() <django.db.models.query.QuerySet.union> ` is not
134
150
supported inside a transaction.
135
- - If a transaction raises an exception, the transaction is no longer usable.
136
- For example, if the update stage of :meth: `QuerySet.update_or_create()
137
- <django.db.models.query.QuerySet.update_or_create> ` fails with
138
- :class: `~django.db.IntegrityError ` due to a unique constraint violation, the
139
- create stage won't be able to proceed.
140
- :class: `pymongo.errors.OperationFailure ` is raised, wrapped by
141
- :class: `django.db.DatabaseError `.
142
151
- Savepoints (i.e. nested :func: `~django.db.transaction.atomic ` blocks) aren't
143
152
supported. The outermost :func: `~django.db.transaction.atomic ` will start
144
153
a transaction while any subsequent :func: `~django.db.transaction.atomic `
145
154
blocks will have no effect.
146
- - Migration operations aren't :ref: `wrapped in a transaction
147
- <topics/migrations:transactions>` because of MongoDB restrictions such as
148
- adding indexes to existing collections while in a transaction.
0 commit comments