Browse files

[1.0.X] Fixed #9206 -- Added documentation on savepoints, and how to …

…use them to recover from errors in PostgreSQL. Thanks to Richard Davies for the draft text.

Merge of r10791 from trunk.

git-svn-id: bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent 985c939 commit f5dcd07977a00ef84fc24ba5719ea86a453b1c8c @freakboy3742 freakboy3742 committed May 16, 2009
Showing with 105 additions and 19 deletions.
  1. +105 −19 docs/topics/db/transactions.txt
@@ -148,6 +148,67 @@ 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:
+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()``.
+Savepoints are controlled by three methods on the transaction object:
+.. method:: transaction.savepoint()
+ 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)
+ 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)
+ 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):
+ # open transaction now contains
+ sid = transaction.savepoint()
+ # open transaction now contains and
+ if want_to_keep_b:
+ transaction.savepoint_commit(sid)
+ # open transaction still contains and
+ else:
+ transaction.savepoint_rollback(sid)
+ # open transaction now contains only
+ transaction.commit()
Transactions in MySQL
@@ -164,28 +225,53 @@ handle transactions as explained in this document.
.. _information on MySQL transactions:
-Transactions and savepoints in PostgreSQL 8
+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.
-When a call to a PostgreSQL 8 cursor raises an exception, all subsequent SQL
-in the same transaction fails 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 many more advanced
-usage patterns which might: for example, 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.
-In any of these cases, you can wrap the command which may throw
-IntegrityError inside savepoints, which will then allow subsequent commands
-to proceed. Example::
+Transaction rollback
+The first option is to roll back the entire transaction. For example::
+ # Succeeds, but may be undone by transaction rollback
- sid = transaction.savepoint()
- transaction.savepoint_commit(sid)
+ # Could throw exception
+ except IntegrityError:
+ transaction.rollback()
+ # Succeeds, but 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 ```` would be lost, even though that operation raised no error
+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::
+ # Succeeds, and never undone by savepoint rollback
+ try:
+ sid = transaction.savepoint()
+ # Could throw exception
+ transaction.savepoint_commit(sid)
except IntegrityError:
- transaction.savepoint_rollback(sid)
- raise
+ transaction.savepoint_rollback(sid)
+ # Succeeds, and is never undone
-Savepoints are not implemented in PostgreSQL 7. If you experience an
-IntegrityError when using PostgreSQL 7, you will need to rollback to the
-start of the transaction.
+In this example, ```` will not be undone in the case where
+```` raises an exception.

0 comments on commit f5dcd07

Please sign in to comment.