PageRenderTime 426ms CodeModel.GetById 201ms app.highlight 3ms RepoModel.GetById 218ms app.codeStats 0ms

/docs/topics/db/transactions.txt

https://code.google.com/p/mango-py/
Plain Text | 378 lines | 277 code | 101 blank | 0 comment | 0 complexity | 790d06a34bebfd6c5ef444b0bd022f1a MD5 | raw file
  1==============================
  2Managing database transactions
  3==============================
  4
  5.. module:: django.db.transaction
  6
  7Django gives you a few ways to control how database transactions are managed,
  8if you're using a database that supports transactions.
  9
 10Django's default transaction behavior
 11=====================================
 12
 13Django's default behavior is to run with an open transaction which it
 14commits automatically when any built-in, data-altering model function is
 15called. For example, if you call ``model.save()`` or ``model.delete()``, the
 16change will be committed immediately.
 17
 18This is much like the auto-commit setting for most databases. As soon as you
 19perform an action that needs to write to the database, Django produces the
 20``INSERT``/``UPDATE``/``DELETE`` statements and then does the ``COMMIT``.
 21There's no implicit ``ROLLBACK``.
 22
 23Tying transactions to HTTP requests
 24===================================
 25
 26The recommended way to handle transactions in Web requests is to tie them to
 27the request and response phases via Django's ``TransactionMiddleware``.
 28
 29It works like this: When a request starts, Django starts a transaction. If the
 30response is produced without problems, Django commits any pending transactions.
 31If the view function produces an exception, Django rolls back any pending
 32transactions.
 33
 34To activate this feature, just add the ``TransactionMiddleware`` middleware to
 35your :setting:`MIDDLEWARE_CLASSES` setting::
 36
 37    MIDDLEWARE_CLASSES = (
 38        'django.middleware.cache.UpdateCacheMiddleware',
 39        'django.contrib.sessions.middleware.SessionMiddleware',
 40        'django.middleware.common.CommonMiddleware',
 41        'django.middleware.transaction.TransactionMiddleware',
 42        'django.middleware.cache.FetchFromCacheMiddleware',
 43    )
 44
 45The order is quite important. The transaction middleware applies not only to
 46view functions, but also for all middleware modules that come after it. So if
 47you use the session middleware after the transaction middleware, session
 48creation will be part of the transaction.
 49
 50The various cache middlewares are an exception:
 51:class:`~django.middleware.cache.CacheMiddleware`,
 52:class:`~django.middleware.cache.UpdateCacheMiddleware`, and
 53:class:`~django.middleware.cache.FetchFromCacheMiddleware` are never affected.
 54Even when using database caching, Django's cache backend uses its own
 55database cursor (which is mapped to its own database connection internally).
 56
 57.. _transaction-management-functions:
 58
 59Controlling transaction management in views
 60===========================================
 61
 62.. versionchanged:: 1.3
 63   Transaction management context managers are new in Django 1.3.
 64
 65For most people, implicit request-based transactions work wonderfully. However,
 66if you need more fine-grained control over how transactions are managed, you can
 67use a set of functions in ``django.db.transaction`` to control transactions on a
 68per-function or per-code-block basis.
 69
 70These functions, described in detail below, can be used in two different ways:
 71
 72    * As a decorator_ on a particular function. For example::
 73
 74            from django.db import transaction
 75
 76            @transaction.commit_on_success
 77            def viewfunc(request):
 78                # ...
 79                # this code executes inside a transaction
 80                # ...
 81
 82      This technique works with all supported version of Python (that is, with
 83      Python 2.4 and greater).
 84
 85    * As a `context manager`_ around a particular block of code::
 86
 87            from django.db import transaction
 88
 89            def viewfunc(request):
 90                # ...
 91                # this code executes using default transaction management
 92                # ...
 93
 94                with transaction.commit_on_success():
 95                    # ...
 96                    # this code executes inside a transaction
 97                    # ...
 98
 99      The ``with`` statement is new in Python 2.5, and so this syntax can only
100      be used with Python 2.5 and above.
101
102.. _decorator: http://docs.python.org/glossary.html#term-decorator
103.. _context manager: http://docs.python.org/glossary.html#term-context-manager
104
105For maximum compatibility, all of the examples below show transactions using the
106decorator syntax, but all of the follow functions may be used as context
107managers, too.
108
109.. note::
110
111    Although the examples below use view functions as examples, these
112    decorators and context managers can be used anywhere in your code
113    that you need to deal with transactions.
114
115.. _topics-db-transactions-autocommit:
116
117.. function:: autocommit
118
119    Use the ``autocommit`` decorator to switch a view function to Django's
120    default commit behavior, regardless of the global transaction setting.
121
122    Example::
123
124        from django.db import transaction
125
126        @transaction.autocommit
127        def viewfunc(request):
128            ....
129
130        @transaction.autocommit(using="my_other_database")
131        def viewfunc2(request):
132            ....
133
134    Within ``viewfunc()``, transactions will be committed as soon as you call
135    ``model.save()``, ``model.delete()``, or any other function that writes to
136    the database.  ``viewfunc2()`` will have this same behavior, but for the
137    ``"my_other_database"`` connection.
138
139.. function:: commit_on_success
140
141    Use the ``commit_on_success`` decorator to use a single transaction for all
142    the work done in a function::
143
144        from django.db import transaction
145
146        @transaction.commit_on_success
147        def viewfunc(request):
148            ....
149
150        @transaction.commit_on_success(using="my_other_database")
151        def viewfunc2(request):
152            ....
153
154    If the function returns successfully, then Django will commit all work done
155    within the function at that point. If the function raises an exception,
156    though, Django will roll back the transaction.
157
158.. function:: commit_manually
159
160    Use the ``commit_manually`` decorator if you need full control over
161    transactions. It tells Django you'll be managing the transaction on your
162    own.
163
164    If your view changes data and doesn't ``commit()`` or ``rollback()``,
165    Django will raise a ``TransactionManagementError`` exception.
166
167    Manual transaction management looks like this::
168
169        from django.db import transaction
170
171        @transaction.commit_manually
172        def viewfunc(request):
173            ...
174            # You can commit/rollback however and whenever you want
175            transaction.commit()
176            ...
177
178            # But you've got to remember to do it yourself!
179            try:
180                ...
181            except:
182                transaction.rollback()
183            else:
184                transaction.commit()
185
186        @transaction.commit_manually(using="my_other_database")
187        def viewfunc2(request):
188            ....
189
190.. _topics-db-transactions-requirements:
191
192Requirements for transaction handling
193=====================================
194
195.. versionadded:: 1.3
196
197Django requires that every transaction that is opened is closed before
198the completion of a request. If you are using :func:`autocommit` (the
199default commit mode) or :func:`commit_on_success`, this will be done
200for you automatically. However, if you are manually managing
201transactions (using the :func:`commit_manually` decorator), you must
202ensure that the transaction is either committed or rolled back before
203a request is completed.
204
205This applies to all database operations, not just write operations. Even
206if your transaction only reads from the database, the transaction must
207be committed or rolled back before you complete a request.
208
209How to globally deactivate transaction management
210=================================================
211
212Control freaks can totally disable all transaction management by setting
213``DISABLE_TRANSACTION_MANAGEMENT`` to ``True`` in the Django settings file.
214
215If you do this, Django won't provide any automatic transaction management
216whatsoever. Middleware will no longer implicitly commit transactions, and
217you'll need to roll management yourself. This even requires you to commit
218changes done by middleware somewhere else.
219
220Thus, this is best used in situations where you want to run your own
221transaction-controlling middleware or do something really strange. In almost
222all situations, you'll be better off using the default behavior, or the
223transaction middleware, and only modify selected functions as needed.
224
225.. _topics-db-transactions-savepoints:
226
227Savepoints
228==========
229
230A savepoint is a marker within a transaction that enables you to roll back
231part of a transaction, rather than the full transaction. Savepoints are
232available to the PostgreSQL 8 and Oracle backends. Other backends will
233provide the savepoint functions, but they are empty operations - they won't
234actually do anything.
235
236Savepoints aren't especially useful if you are using the default
237``autocommit`` behavior of Django. However, if you are using
238``commit_on_success`` or ``commit_manually``, each open transaction will build
239up a series of database operations, awaiting a commit or rollback. If you
240issue a rollback, the entire transaction is rolled back. Savepoints provide
241the ability to perform a fine-grained rollback, rather than the full rollback
242that would be performed by ``transaction.rollback()``.
243
244Each of these functions takes a ``using`` argument which should be the name of
245a database for which the behavior applies.  If no ``using`` argument is
246provided then the ``"default"`` database is used.
247
248Savepoints are controlled by three methods on the transaction object:
249
250.. method:: transaction.savepoint(using=None)
251
252    Creates a new savepoint. This marks a point in the transaction that
253    is known to be in a "good" state.
254
255    Returns the savepoint ID (sid).
256
257.. method:: transaction.savepoint_commit(sid, using=None)
258
259    Updates the savepoint to include any operations that have been performed
260    since the savepoint was created, or since the last commit.
261
262.. method:: transaction.savepoint_rollback(sid, using=None)
263
264    Rolls the transaction back to the last point at which the savepoint was
265    committed.
266
267The following example demonstrates the use of savepoints::
268
269    from django.db import transaction
270
271    @transaction.commit_manually
272    def viewfunc(request):
273
274      a.save()
275      # open transaction now contains a.save()
276      sid = transaction.savepoint()
277
278      b.save()
279      # open transaction now contains a.save() and b.save()
280
281      if want_to_keep_b:
282          transaction.savepoint_commit(sid)
283          # open transaction still contains a.save() and b.save()
284      else:
285          transaction.savepoint_rollback(sid)
286          # open transaction now contains only a.save()
287
288      transaction.commit()
289
290Transactions in MySQL
291=====================
292
293If you're using MySQL, your tables may or may not support transactions; it
294depends on your MySQL version and the table types you're using. (By
295"table types," we mean something like "InnoDB" or "MyISAM".) MySQL transaction
296peculiarities are outside the scope of this article, but the MySQL site has
297`information on MySQL transactions`_.
298
299If your MySQL setup does *not* support transactions, then Django will function
300in auto-commit mode: Statements will be executed and committed as soon as
301they're called. If your MySQL setup *does* support transactions, Django will
302handle transactions as explained in this document.
303
304.. _information on MySQL transactions: http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html
305
306Handling exceptions within PostgreSQL transactions
307==================================================
308
309When a call to a PostgreSQL cursor raises an exception (typically
310``IntegrityError``), all subsequent SQL in the same transaction will fail with
311the error "current transaction is aborted, queries ignored until end of
312transaction block". Whilst simple use of ``save()`` is unlikely to raise an
313exception in PostgreSQL, there are more advanced usage patterns which
314might, such as saving objects with unique fields, saving using the
315force_insert/force_update flag, or invoking custom SQL.
316
317There are several ways to recover from this sort of error.
318
319Transaction rollback
320--------------------
321
322The first option is to roll back the entire transaction. For example::
323
324    a.save() # Succeeds, but may be undone by transaction rollback
325    try:
326        b.save() # Could throw exception
327    except IntegrityError:
328        transaction.rollback()
329    c.save() # Succeeds, but a.save() may have been undone
330
331Calling ``transaction.rollback()`` rolls back the entire transaction. Any
332uncommitted database operations will be lost. In this example, the changes
333made by ``a.save()`` would be lost, even though that operation raised no error
334itself.
335
336Savepoint rollback
337------------------
338
339If you are using PostgreSQL 8 or later, you can use :ref:`savepoints
340<topics-db-transactions-savepoints>` to control the extent of a rollback.
341Before performing a database operation that could fail, you can set or update
342the savepoint; that way, if the operation fails, you can roll back the single
343offending operation, rather than the entire transaction. For example::
344
345    a.save() # Succeeds, and never undone by savepoint rollback
346    try:
347        sid = transaction.savepoint()
348        b.save() # Could throw exception
349        transaction.savepoint_commit(sid)
350    except IntegrityError:
351        transaction.savepoint_rollback(sid)
352    c.save() # Succeeds, and a.save() is never undone
353
354In this example, ``a.save()`` will not be undone in the case where
355``b.save()`` raises an exception.
356
357Database-level autocommit
358-------------------------
359
360With PostgreSQL 8.2 or later, there is an advanced option to run PostgreSQL
361with :doc:`database-level autocommit </ref/databases>`. If you use this option,
362there is no constantly open transaction, so it is always possible to continue
363after catching an exception. For example::
364
365    a.save() # succeeds
366    try:
367        b.save() # Could throw exception
368    except IntegrityError:
369        pass
370    c.save() # succeeds
371
372.. note::
373
374    This is not the same as the :ref:`autocommit decorator
375    <topics-db-transactions-autocommit>`. When using database level autocommit
376    there is no database transaction at all. The ``autocommit`` decorator
377    still uses transactions, automatically committing each transaction when
378    a database modifying operation occurs.