|
@@ -502,222 +502,3 @@ transaction. For example::
|
|
|
|
|
|
In this example, ``a.save()`` will not be undone in the case where
|
|
|
``b.save()`` raises an exception.
|
|
|
-
|
|
|
-.. _transactions-upgrading-from-1.5:
|
|
|
-
|
|
|
-Changes from Django 1.5 and earlier
|
|
|
-===================================
|
|
|
-
|
|
|
-The features described below were deprecated in Django 1.6 and will be removed
|
|
|
-in Django 1.8. They're documented in order to ease the migration to the new
|
|
|
-transaction management APIs.
|
|
|
-
|
|
|
-Legacy APIs
|
|
|
------------
|
|
|
-
|
|
|
-The following functions, defined in ``django.db.transaction``, provided a way
|
|
|
-to control transactions on a per-function or per-code-block basis. They could
|
|
|
-be used as decorators or as context managers, and they accepted a ``using``
|
|
|
-argument, exactly like :func:`atomic`.
|
|
|
-
|
|
|
-.. function:: autocommit
|
|
|
-
|
|
|
- Enable Django's default autocommit behavior.
|
|
|
-
|
|
|
- Transactions will be committed as soon as you call ``model.save()``,
|
|
|
- ``model.delete()``, or any other function that writes to the database.
|
|
|
-
|
|
|
-.. function:: commit_on_success
|
|
|
-
|
|
|
- Use a single transaction for all the work done in a function.
|
|
|
-
|
|
|
- If the function returns successfully, then Django will commit all work done
|
|
|
- within the function at that point. If the function raises an exception,
|
|
|
- though, Django will roll back the transaction.
|
|
|
-
|
|
|
-.. function:: commit_manually
|
|
|
-
|
|
|
- Tells Django you'll be managing the transaction on your own.
|
|
|
-
|
|
|
- Whether you are writing or simply reading from the database, you must
|
|
|
- ``commit()`` or ``rollback()`` explicitly or Django will raise a
|
|
|
- :exc:`TransactionManagementError` exception. This is required when reading
|
|
|
- from the database because ``SELECT`` statements may call functions which
|
|
|
- modify tables, and thus it is impossible to know if any data has been
|
|
|
- modified.
|
|
|
-
|
|
|
-.. _transaction-states:
|
|
|
-
|
|
|
-Transaction states
|
|
|
-------------------
|
|
|
-
|
|
|
-The three functions described above relied on a concept called "transaction
|
|
|
-states". This mechanism was deprecated in Django 1.6, but it's still available
|
|
|
-until Django 1.8.
|
|
|
-
|
|
|
-At any time, each database connection is in one of these two states:
|
|
|
-
|
|
|
-- **auto mode**: autocommit is enabled;
|
|
|
-- **managed mode**: autocommit is disabled.
|
|
|
-
|
|
|
-Django starts in auto mode. ``TransactionMiddleware``,
|
|
|
-:func:`commit_on_success` and :func:`commit_manually` activate managed mode;
|
|
|
-:func:`autocommit` activates auto mode.
|
|
|
-
|
|
|
-Internally, Django keeps a stack of states. Activations and deactivations must
|
|
|
-be balanced.
|
|
|
-
|
|
|
-For example, :func:`commit_on_success` switches to managed mode when entering
|
|
|
-the block of code it controls; when exiting the block, it commits or
|
|
|
-rollbacks, and switches back to auto mode.
|
|
|
-
|
|
|
-So :func:`commit_on_success` really has two effects: it changes the
|
|
|
-transaction state and it defines a transaction block. Nesting will give the
|
|
|
-expected results in terms of transaction state, but not in terms of
|
|
|
-transaction semantics. Most often, the inner block will commit, breaking the
|
|
|
-atomicity of the outer block.
|
|
|
-
|
|
|
-:func:`autocommit` and :func:`commit_manually` have similar limitations.
|
|
|
-
|
|
|
-API changes
|
|
|
------------
|
|
|
-
|
|
|
-Transaction middleware
|
|
|
-~~~~~~~~~~~~~~~~~~~~~~
|
|
|
-
|
|
|
-In Django 1.6, ``TransactionMiddleware`` is deprecated and replaced by
|
|
|
-:setting:`ATOMIC_REQUESTS <DATABASE-ATOMIC_REQUESTS>`. While the general
|
|
|
-behavior is the same, there are two differences.
|
|
|
-
|
|
|
-With the previous API, it was possible to switch to autocommit or to commit
|
|
|
-explicitly anywhere inside a view. Since :setting:`ATOMIC_REQUESTS
|
|
|
-<DATABASE-ATOMIC_REQUESTS>` relies on :func:`atomic` which enforces atomicity,
|
|
|
-this isn't allowed any longer. However, at the top level, it's still possible
|
|
|
-to avoid wrapping an entire view in a transaction. To achieve this, decorate
|
|
|
-the view with :func:`non_atomic_requests` instead of :func:`autocommit`.
|
|
|
-
|
|
|
-The transaction middleware applied not only to view functions, but also to
|
|
|
-middleware modules that came after it. For instance, if you used the session
|
|
|
-middleware after the transaction middleware, session creation was part of the
|
|
|
-transaction. :setting:`ATOMIC_REQUESTS <DATABASE-ATOMIC_REQUESTS>` only
|
|
|
-applies to the view itself.
|
|
|
-
|
|
|
-Managing transactions
|
|
|
-~~~~~~~~~~~~~~~~~~~~~
|
|
|
-
|
|
|
-Starting with Django 1.6, :func:`atomic` is the only supported API for
|
|
|
-defining a transaction. Unlike the deprecated APIs, it's nestable and always
|
|
|
-guarantees atomicity.
|
|
|
-
|
|
|
-In most cases, it will be a drop-in replacement for :func:`commit_on_success`.
|
|
|
-
|
|
|
-During the deprecation period, it's possible to use :func:`atomic` within
|
|
|
-:func:`autocommit`, :func:`commit_on_success` or :func:`commit_manually`.
|
|
|
-However, the reverse is forbidden, because nesting the old decorators /
|
|
|
-context managers breaks atomicity.
|
|
|
-
|
|
|
-Managing autocommit
|
|
|
-~~~~~~~~~~~~~~~~~~~
|
|
|
-
|
|
|
-Django 1.6 introduces an explicit :ref:`API for managing autocommit
|
|
|
-<managing-autocommit>`.
|
|
|
-
|
|
|
-To disable autocommit temporarily, instead of::
|
|
|
-
|
|
|
- with transaction.commit_manually():
|
|
|
- # do stuff
|
|
|
-
|
|
|
-you should now use::
|
|
|
-
|
|
|
- transaction.set_autocommit(False)
|
|
|
- try:
|
|
|
- # do stuff
|
|
|
- finally:
|
|
|
- transaction.set_autocommit(True)
|
|
|
-
|
|
|
-To enable autocommit temporarily, instead of::
|
|
|
-
|
|
|
- with transaction.autocommit():
|
|
|
- # do stuff
|
|
|
-
|
|
|
-you should now use::
|
|
|
-
|
|
|
- transaction.set_autocommit(True)
|
|
|
- try:
|
|
|
- # do stuff
|
|
|
- finally:
|
|
|
- transaction.set_autocommit(False)
|
|
|
-
|
|
|
-Unless you're implementing a transaction management framework, you shouldn't
|
|
|
-ever need to do this.
|
|
|
-
|
|
|
-Disabling transaction management
|
|
|
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
-
|
|
|
-Instead of setting ``TRANSACTIONS_MANAGED = True``, set the ``AUTOCOMMIT`` key
|
|
|
-to ``False`` in the configuration of each database, as explained in
|
|
|
-:ref:`deactivate-transaction-management`.
|
|
|
-
|
|
|
-Backwards incompatibilities
|
|
|
----------------------------
|
|
|
-
|
|
|
-Since version 1.6, Django uses database-level autocommit in auto mode.
|
|
|
-Previously, it implemented application-level autocommit by triggering a commit
|
|
|
-after each ORM write.
|
|
|
-
|
|
|
-As a consequence, each database query (for instance, an ORM read) started a
|
|
|
-transaction that lasted until the next ORM write. Such "automatic
|
|
|
-transactions" no longer exist in Django 1.6.
|
|
|
-
|
|
|
-There are four known scenarios where this is backwards-incompatible.
|
|
|
-
|
|
|
-Note that managed mode isn't affected at all. This section assumes auto mode.
|
|
|
-See the :ref:`description of modes <transaction-states>` above.
|
|
|
-
|
|
|
-Sequences of custom SQL queries
|
|
|
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
-
|
|
|
-If you're executing several :ref:`custom SQL queries <executing-custom-sql>`
|
|
|
-in a row, each one now runs in its own transaction, instead of sharing the
|
|
|
-same "automatic transaction". If you need to enforce atomicity, you must wrap
|
|
|
-the sequence of queries in :func:`atomic`.
|
|
|
-
|
|
|
-To check for this problem, look for calls to ``cursor.execute()``. They're
|
|
|
-usually followed by a call to ``transaction.commit_unless_managed()``, which
|
|
|
-isn't useful any more and should be removed.
|
|
|
-
|
|
|
-Select for update
|
|
|
-~~~~~~~~~~~~~~~~~
|
|
|
-
|
|
|
-If you were relying on "automatic transactions" to provide locking between
|
|
|
-:meth:`~django.db.models.query.QuerySet.select_for_update` and a subsequent
|
|
|
-write operation — an extremely fragile design, but nonetheless possible — you
|
|
|
-must wrap the relevant code in :func:`atomic`. Since Django 1.6.3, executing
|
|
|
-a query with :meth:`~django.db.models.query.QuerySet.select_for_update` in
|
|
|
-autocommit mode will raise a
|
|
|
-:exc:`~django.db.transaction.TransactionManagementError`.
|
|
|
-
|
|
|
-Using a high isolation level
|
|
|
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
-
|
|
|
-If you were using the "repeatable read" isolation level or higher, and if you
|
|
|
-relied on "automatic transactions" to guarantee consistency between successive
|
|
|
-reads, the new behavior might be backwards-incompatible. To enforce
|
|
|
-consistency, you must wrap such sequences in :func:`atomic`.
|
|
|
-
|
|
|
-MySQL defaults to "repeatable read" and SQLite to "serializable"; they may be
|
|
|
-affected by this problem.
|
|
|
-
|
|
|
-At the "read committed" isolation level or lower, "automatic transactions"
|
|
|
-have no effect on the semantics of any sequence of ORM operations.
|
|
|
-
|
|
|
-PostgreSQL and Oracle default to "read committed" and aren't affected, unless
|
|
|
-you changed the isolation level.
|
|
|
-
|
|
|
-Using unsupported database features
|
|
|
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
-
|
|
|
-With triggers, views, or functions, it's possible to make ORM reads result in
|
|
|
-database modifications. Django 1.5 and earlier doesn't deal with this case and
|
|
|
-it's theoretically possible to observe a different behavior after upgrading to
|
|
|
-Django 1.6 or later. In doubt, use :func:`atomic` to enforce integrity.
|