parts/django/docs/topics/db/transactions.txt
changeset 69 c6bca38c1cbf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/parts/django/docs/topics/db/transactions.txt	Sat Jan 08 11:20:57 2011 +0530
@@ -0,0 +1,328 @@
+==============================
+Managing database transactions
+==============================
+
+.. currentmodule:: django.db
+
+Django gives you a few ways to control how database transactions are managed,
+if you're using a database that supports transactions.
+
+Django's default transaction behavior
+=====================================
+
+Django's default behavior is to run with an open transaction which it
+commits automatically when any built-in, data-altering model function is
+called. For example, if you call ``model.save()`` or ``model.delete()``, the
+change will be committed immediately.
+
+This is much like the auto-commit setting for most databases. As soon as you
+perform an action that needs to write to the database, Django produces the
+``INSERT``/``UPDATE``/``DELETE`` statements and then does the ``COMMIT``.
+There's no implicit ``ROLLBACK``.
+
+Tying transactions to HTTP requests
+===================================
+
+The recommended way to handle transactions in Web requests is to tie them to
+the request and response phases via Django's ``TransactionMiddleware``.
+
+It works like this: When a request starts, Django starts a transaction. If the
+response is produced without problems, Django commits any pending transactions.
+If the view function produces an exception, Django rolls back any pending
+transactions.
+
+To activate this feature, just add the ``TransactionMiddleware`` middleware to
+your :setting:`MIDDLEWARE_CLASSES` setting::
+
+    MIDDLEWARE_CLASSES = (
+        'django.middleware.cache.UpdateCacheMiddleware',
+        'django.contrib.sessions.middleware.SessionMiddleware',
+        'django.middleware.common.CommonMiddleware',
+        'django.middleware.transaction.TransactionMiddleware',
+        'django.middleware.cache.FetchFromCacheMiddleware',
+    )
+
+The order is quite important. The transaction middleware applies not only to
+view functions, but also for all middleware modules that come after it. So if
+you use the session middleware after the transaction middleware, session
+creation will be part of the transaction.
+
+The various cache middlewares are an exception:
+:class:`~django.middleware.cache.CacheMiddleware`,
+:class:`~django.middleware.cache.UpdateCacheMiddleware`, and
+:class:`~django.middleware.cache.FetchFromCacheMiddleware` are never affected.
+Even when using database caching, Django's cache backend uses its own
+database cursor (which is mapped to its own database connection internally).
+
+Controlling transaction management in views
+===========================================
+
+For most people, implicit request-based transactions work wonderfully. However,
+if you need more fine-grained control over how transactions are managed, you
+can use Python decorators to change the way transactions are handled by a
+particular view function.  All of the decorators take an option ``using``
+parameter which should be the alias for a database connection for which the
+behavior applies to.  If no alias is specified then the ``"default"`` database
+is used.
+
+.. note::
+
+    Although the examples below use view functions as examples, these
+    decorators can be applied to non-view functions as well.
+
+.. _topics-db-transactions-autocommit:
+
+``django.db.transaction.autocommit``
+------------------------------------
+
+Use the ``autocommit`` decorator to switch a view function to Django's default
+commit behavior, regardless of the global transaction setting.
+
+Example::
+
+    from django.db import transaction
+
+    @transaction.autocommit
+    def viewfunc(request):
+        ....
+
+    @transaction.autocommit(using="my_other_database")
+    def viewfunc2(request):
+        ....
+
+Within ``viewfunc()``, transactions will be committed as soon as you call
+``model.save()``, ``model.delete()``, or any other function that writes to the
+database.  ``viewfunc2()`` will have this same behavior, but for the
+``"my_other_database"`` connection.
+
+``django.db.transaction.commit_on_success``
+-------------------------------------------
+
+Use the ``commit_on_success`` decorator to use a single transaction for
+all the work done in a function::
+
+    from django.db import transaction
+
+    @transaction.commit_on_success
+    def viewfunc(request):
+        ....
+
+    @transaction.commit_on_success(using="my_other_database")
+    def viewfunc2(request):
+        ....
+
+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.
+
+``django.db.transaction.commit_manually``
+-----------------------------------------
+
+Use the ``commit_manually`` decorator if you need full control over
+transactions. It tells Django you'll be managing the transaction on your own.
+
+If your view changes data and doesn't ``commit()`` or ``rollback()``, Django
+will raise a ``TransactionManagementError`` exception.
+
+Manual transaction management looks like this::
+
+    from django.db import transaction
+
+    @transaction.commit_manually
+    def viewfunc(request):
+        ...
+        # You can commit/rollback however and whenever you want
+        transaction.commit()
+        ...
+
+        # But you've got to remember to do it yourself!
+        try:
+            ...
+        except:
+            transaction.rollback()
+        else:
+            transaction.commit()
+
+    @transaction.commit_manually(using="my_other_database")
+    def viewfunc2(request):
+        ....
+
+.. admonition:: An important note to users of earlier Django releases:
+
+    The database ``connection.commit()`` and ``connection.rollback()`` methods
+    (called ``db.commit()`` and ``db.rollback()`` in 0.91 and earlier) no
+    longer exist. They've been replaced by ``transaction.commit()`` and
+    ``transaction.rollback()``.
+
+How to globally deactivate transaction management
+=================================================
+
+Control freaks can totally disable all transaction management by setting
+``DISABLE_TRANSACTION_MANAGEMENT`` to ``True`` in the Django settings file.
+
+If you do this, Django won't provide any automatic transaction management
+whatsoever. Middleware will no longer implicitly commit transactions, and
+you'll need to roll management yourself. This even requires you to commit
+changes done by middleware somewhere else.
+
+Thus, this is best used in situations where you want to run your own
+transaction-controlling middleware or do something really strange. In almost
+all situations, you'll be better off using the default behavior, or the
+transaction middleware, and only modify selected functions as needed.
+
+.. _topics-db-transactions-savepoints:
+
+Savepoints
+==========
+
+A savepoint is a marker within a transaction that enables you to roll back
+part of a transaction, rather than the full transaction. Savepoints are
+available to the PostgreSQL 8 and Oracle backends. Other backends will
+provide the savepoint functions, but they are empty operations - they won't
+actually do anything.
+
+Savepoints aren't especially useful if you are using the default
+``autocommit`` behaviour of Django. However, if you are using
+``commit_on_success`` or ``commit_manually``, each open transaction will build
+up a series of database operations, awaiting a commit or rollback. If you
+issue a rollback, the entire transaction is rolled back. Savepoints provide
+the ability to perform a fine-grained rollback, rather than the full rollback
+that would be performed by ``transaction.rollback()``.
+
+Each of these functions takes a ``using`` argument which should be the name of
+a database for which the behavior applies.  If no ``using`` argument is
+provided then the ``"default"`` database is used.
+
+Savepoints are controlled by three methods on the transaction object:
+
+.. method:: transaction.savepoint(using=None)
+
+    Creates a new savepoint. This marks a point in the transaction that
+    is known to be in a "good" state.
+
+    Returns the savepoint ID (sid).
+
+.. method:: transaction.savepoint_commit(sid, using=None)
+
+    Updates the savepoint to include any operations that have been performed
+    since the savepoint was created, or since the last commit.
+
+.. method:: transaction.savepoint_rollback(sid, using=None)
+
+    Rolls the transaction back to the last point at which the savepoint was
+    committed.
+
+The following example demonstrates the use of savepoints::
+
+    from django.db import transaction
+
+    @transaction.commit_manually
+    def viewfunc(request):
+
+      a.save()
+      # open transaction now contains a.save()
+      sid = transaction.savepoint()
+
+      b.save()
+      # open transaction now contains a.save() and b.save()
+
+      if want_to_keep_b:
+          transaction.savepoint_commit(sid)
+          # open transaction still contains a.save() and b.save()
+      else:
+          transaction.savepoint_rollback(sid)
+          # open transaction now contains only a.save()
+
+      transaction.commit()
+
+Transactions in MySQL
+=====================
+
+If you're using MySQL, your tables may or may not support transactions; it
+depends on your MySQL version and the table types you're using. (By
+"table types," we mean something like "InnoDB" or "MyISAM".) MySQL transaction
+peculiarities are outside the scope of this article, but the MySQL site has
+`information on MySQL transactions`_.
+
+If your MySQL setup does *not* support transactions, then Django will function
+in auto-commit mode: Statements will be executed and committed as soon as
+they're called. If your MySQL setup *does* support transactions, Django will
+handle transactions as explained in this document.
+
+.. _information on MySQL transactions: http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html
+
+Handling exceptions within PostgreSQL transactions
+==================================================
+
+When a call to a PostgreSQL cursor raises an exception (typically
+``IntegrityError``), all subsequent SQL in the same transaction will fail with
+the error "current transaction is aborted, queries ignored until end of
+transaction block". Whilst simple use of ``save()`` is unlikely to raise an
+exception in PostgreSQL, there are more advanced usage patterns which
+might, such as saving objects with unique fields, saving using the
+force_insert/force_update flag, or invoking custom SQL.
+
+There are several ways to recover from this sort of error.
+
+Transaction rollback
+--------------------
+
+The first option is to roll back the entire transaction. For example::
+
+    a.save() # Succeeds, but may be undone by transaction rollback
+    try:
+        b.save() # Could throw exception
+    except IntegrityError:
+        transaction.rollback()
+    c.save() # Succeeds, but a.save() may have been undone
+
+Calling ``transaction.rollback()`` rolls back the entire transaction. Any
+uncommitted database operations will be lost. In this example, the changes
+made by ``a.save()`` would be lost, even though that operation raised no error
+itself.
+
+Savepoint rollback
+------------------
+
+If you are using PostgreSQL 8 or later, you can use :ref:`savepoints
+<topics-db-transactions-savepoints>` to control the extent of a rollback.
+Before performing a database operation that could fail, you can set or update
+the savepoint; that way, if the operation fails, you can roll back the single
+offending operation, rather than the entire transaction. For example::
+
+    a.save() # Succeeds, and never undone by savepoint rollback
+    try:
+        sid = transaction.savepoint()
+        b.save() # Could throw exception
+        transaction.savepoint_commit(sid)
+    except IntegrityError:
+        transaction.savepoint_rollback(sid)
+    c.save() # Succeeds, and a.save() is never undone
+
+In this example, ``a.save()`` will not be undone in the case where
+``b.save()`` raises an exception.
+
+Database-level autocommit
+-------------------------
+
+.. versionadded:: 1.1
+
+With PostgreSQL 8.2 or later, there is an advanced option to run PostgreSQL
+with :doc:`database-level autocommit </ref/databases>`. If you use this option,
+there is no constantly open transaction, so it is always possible to continue
+after catching an exception. For example::
+
+    a.save() # succeeds
+    try:
+        b.save() # Could throw exception
+    except IntegrityError:
+        pass
+    c.save() # succeeds
+
+.. note::
+
+    This is not the same as the :ref:`autocommit decorator
+    <topics-db-transactions-autocommit>`. When using database level autocommit
+    there is no database transaction at all. The ``autocommit`` decorator
+    still uses transactions, automatically committing each transaction when
+    a database modifying operation occurs.