Index: django/db/models/query.py
===================================================================
--- django/db/models/query.py	(revision 12037)
+++ django/db/models/query.py	(working copy)
@@ -364,12 +364,14 @@
                 params = dict([(k, v) for k, v in kwargs.items() if '__' not in k])
                 params.update(defaults)
                 obj = self.model(**params)
-                sid = transaction.savepoint(using=self.db)
+                sid = transaction.savepoint(using=self.db, only_if_needed=True)
                 obj.save(force_insert=True, using=self.db)
-                transaction.savepoint_commit(sid, using=self.db)
+                transaction.savepoint_commit(sid, using=self.db,
+                                             only_if_needed=True)
                 return obj, True
             except IntegrityError, e:
-                transaction.savepoint_rollback(sid, using=self.db)
+                transaction.savepoint_rollback(sid, using=self.db,
+                                               only_if_needed=True)
                 try:
                     return self.get(**kwargs), False
                 except self.model.DoesNotExist:
Index: django/db/backends/postgresql/base.py
===================================================================
--- django/db/backends/postgresql/base.py	(revision 12037)
+++ django/db/backends/postgresql/base.py	(working copy)
@@ -67,6 +67,7 @@
 
 class DatabaseFeatures(BaseDatabaseFeatures):
     uses_savepoints = True
+    needs_savepoint_on_exception = True
 
 class DatabaseWrapper(BaseDatabaseWrapper):
     operators = {
@@ -124,6 +125,9 @@
             if self._version[0:2] < (8, 0):
                 # No savepoint support for earlier version of PostgreSQL.
                 self.features.uses_savepoints = False
+                # Transactions will just break on exceptions
+                # and there's nothing we can do about it
+                self.features.needs_savepoint_on_exception = False
         cursor.execute("SET client_encoding to 'UNICODE'")
         cursor = UnicodeCursorWrapper(cursor, 'utf-8')
         return cursor
Index: django/db/backends/__init__.py
===================================================================
--- django/db/backends/__init__.py	(revision 12037)
+++ django/db/backends/__init__.py	(working copy)
@@ -50,19 +50,25 @@
         """
         pass
 
-    def _savepoint(self, sid):
+    def _savepoint(self, sid, only_if_needed=False):
         if not self.features.uses_savepoints:
             return
+        if only_if_needed and not self.features.needs_savepoint_on_exception:
+            return
         self.cursor().execute(self.ops.savepoint_create_sql(sid))
 
-    def _savepoint_rollback(self, sid):
+    def _savepoint_rollback(self, sid, only_if_needed=False):
         if not self.features.uses_savepoints:
             return
+        if only_if_needed and not self.features.needs_savepoint_on_exception:
+            return
         self.cursor().execute(self.ops.savepoint_rollback_sql(sid))
 
-    def _savepoint_commit(self, sid):
+    def _savepoint_commit(self, sid, only_if_needed=False):
         if not self.features.uses_savepoints:
             return
+        if only_if_needed and not self.features.needs_savepoint_on_exception:
+            return
         self.cursor().execute(self.ops.savepoint_commit_sql(sid))
 
     def close(self):
@@ -92,6 +98,7 @@
     can_return_id_from_insert = False
     uses_autocommit = False
     uses_savepoints = False
+    needs_savepoint_on_exception = False
     # If True, don't use integer foreign keys referring to, e.g., positive
     # integer primary keys.
     related_fields_match_type = False
Index: django/db/backends/postgresql_psycopg2/base.py
===================================================================
--- django/db/backends/postgresql_psycopg2/base.py	(revision 12037)
+++ django/db/backends/postgresql_psycopg2/base.py	(working copy)
@@ -107,6 +107,9 @@
             if self._version[0:2] < (8, 0):
                 # No savepoint support for earlier version of PostgreSQL.
                 self.features.uses_savepoints = False
+                # Transactions will just break on exceptions
+                # and there's nothing we can do about it
+                self.features.needs_savepoint_on_exception = False
             if self.features.uses_autocommit:
                 if self._version[0:2] < (8, 2):
                     # FIXME: Needs extra code to do reliable model insert
@@ -149,3 +152,4 @@
         finally:
             self.isolation_level = level
             self.features.uses_savepoints = bool(level)
+            self.features.needs_savepoint_on_exception = bool(level)
Index: django/db/transaction.py
===================================================================
--- django/db/transaction.py	(revision 12037)
+++ django/db/transaction.py	(working copy)
@@ -209,7 +209,7 @@
     connection._rollback()
     set_clean(using=using)
 
-def savepoint(using=None):
+def savepoint(using=None, only_if_needed=False):
     """
     Creates a savepoint (if supported and required by the backend) inside the
     current transaction. Returns an identifier for the savepoint that will be
@@ -226,32 +226,34 @@
         savepoint_state[thread_ident][using] = [None]
     tid = str(thread_ident).replace('-', '')
     sid = "s%s_x%d" % (tid, len(savepoint_state[thread_ident][using]))
-    connection._savepoint(sid)
+    connection._savepoint(sid, only_if_needed)
     return sid
 
-def savepoint_rollback(sid, using=None):
+def savepoint_rollback(sid, using=None, only_if_needed=False):
     """
     Rolls back the most recent savepoint (if one exists). Does nothing if
-    savepoints are not supported.
+    savepoints are not supported, or if only_if_needed is set and the backend
+    does not need to use savepoints to recover from exceptions.
     """
     if using is None:
         using = DEFAULT_DB_ALIAS
     connection = connections[using]
     thread_ident = thread.get_ident()
     if thread_ident in savepoint_state and using in savepoint_state[thread_ident]:
-        connection._savepoint_rollback(sid)
+        connection._savepoint_rollback(sid, only_if_needed)
 
-def savepoint_commit(sid, using=None):
+def savepoint_commit(sid, using=None, only_if_needed=False):
     """
     Commits the most recent savepoint (if one exists). Does nothing if
-    savepoints are not supported.
+    savepoints are not supported, or if only_if_needed is set and the backend
+    does not need to use savepoints to recover from exceptions.
     """
     if using is None:
         using = DEFAULT_DB_ALIAS
     connection = connections[using]
     thread_ident = thread.get_ident()
     if thread_ident in savepoint_state and using in savepoint_state[thread_ident]:
-        connection._savepoint_commit(sid)
+        connection._savepoint_commit(sid, only_if_needed)
 
 ##############
 # DECORATORS #
Index: django/contrib/sessions/backends/db.py
===================================================================
--- django/contrib/sessions/backends/db.py	(revision 12037)
+++ django/contrib/sessions/backends/db.py	(working copy)
@@ -58,12 +58,13 @@
             session_data = self.encode(self._get_session(no_load=must_create)),
             expire_date = self.get_expiry_date()
         )
-        sid = transaction.savepoint(using=self.using)
+        sid = transaction.savepoint(using=self.using, only_if_needed=True)
         try:
             obj.save(force_insert=must_create)
         except IntegrityError:
             if must_create:
-                transaction.savepoint_rollback(sid, using=self.using)
+                transaction.savepoint_rollback(sid, using=self.using,
+                                               only_if_needed=True)
                 raise CreateError
             raise
 
Index: tests/modeltests/force_insert_update/models.py
===================================================================
--- tests/modeltests/force_insert_update/models.py	(revision 12037)
+++ tests/modeltests/force_insert_update/models.py	(working copy)
@@ -40,7 +40,7 @@
 >>> c1.save(force_insert=True)
 
 # Won't work because we can't insert a pk of the same value.
->>> sid = transaction.savepoint()
+>>> sid = transaction.savepoint(only_if_needed=True)
 >>> c.value = 5
 >>> try:
 ...     c.save(force_insert=True)
@@ -50,7 +50,7 @@
 ...     else:
 ...         print "Fail with %s" % type(e)
 Pass
->>> transaction.savepoint_rollback(sid)
+>>> transaction.savepoint_rollback(sid, only_if_needed=True)
 
 # Trying to update should still fail, even with manual primary keys, if the
 # data isn't in the database already.
Index: tests/modeltests/one_to_one/models.py
===================================================================
--- tests/modeltests/one_to_one/models.py	(revision 12037)
+++ tests/modeltests/one_to_one/models.py	(working copy)
@@ -180,7 +180,7 @@
 
 # This will fail because each one-to-one field must be unique (and link2=o1 was
 # used for x1, above).
->>> sid = transaction.savepoint()
+>>> sid = transaction.savepoint(only_if_needed=True)
 >>> try:
 ...     MultiModel(link1=p2, link2=o1, name="x1").save()
 ... except Exception, e:
@@ -189,6 +189,6 @@
 ...     else:
 ...         print "Fail with %s" % type(e)
 Pass
->>> transaction.savepoint_rollback(sid)
+>>> transaction.savepoint_rollback(sid, only_if_needed=True)
 
 """}
Index: tests/modeltests/custom_pk/models.py
===================================================================
--- tests/modeltests/custom_pk/models.py	(revision 12037)
+++ tests/modeltests/custom_pk/models.py	(working copy)
@@ -122,12 +122,12 @@
 # The primary key must also obviously be unique, so trying to create a new
 # object with the same primary key will fail.
 >>> try:
-...    sid = transaction.savepoint()
+...    sid = transaction.savepoint(only_if_needed=True)
 ...    Employee.objects.create(employee_code=123, first_name='Fred', last_name='Jones')
-...    transaction.savepoint_commit(sid)
+...    transaction.savepoint_commit(sid, only_if_needed=True)
 ... except Exception, e:
 ...    if isinstance(e, IntegrityError):
-...        transaction.savepoint_rollback(sid)
+...        transaction.savepoint_rollback(sid, only_if_needed=True)
 ...        print "Pass"
 ...    else:
 ...        print "Fail with %s" % type(e)
@@ -161,14 +161,14 @@
 # The primary key must be specified, so an error is raised if you try to create
 # an object without it.
 >>> try:
-...     sid = transaction.savepoint()
+...     sid = transaction.savepoint(only_if_needed=True)
 ...     Employee.objects.create(first_name='Tom', last_name='Smith')
 ...     print 'hello'
-...     transaction.savepoint_commit(sid)
+...     transaction.savepoint_commit(sid, only_if_needed=True)
 ...     print 'hello2'
 ... except Exception, e:
 ...     if isinstance(e, IntegrityError):
-...         transaction.savepoint_rollback(sid)
+...         transaction.savepoint_rollback(sid, only_if_needed=True)
 ...         print "Pass"
 ...     else:
 ...         print "Fail with %s" % type(e)
Index: docs/topics/db/transactions.txt
===================================================================
--- docs/topics/db/transactions.txt	(revision 12037)
+++ docs/topics/db/transactions.txt	(working copy)
@@ -191,23 +191,29 @@
 
 Savepoints are controlled by three methods on the transaction object:
 
-.. method:: transaction.savepoint(using=None)
+.. method:: transaction.savepoint(using=None, only_if_needed=False)
 
     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)
+.. method:: transaction.savepoint_commit(sid, using=None, only_if_needed=False)
 
     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)
+.. method:: transaction.savepoint_rollback(sid, using=None, only_if_needed=False)
 
     Rolls the transaction back to the last point at which the savepoint was
     committed.
 
+.. note::
+
+    The ``only_if_needed`` flag is an advanced option, which is used in the
+    context described under "Handling exceptions within PostgreSQL
+    transactions", below.
+
 The following example demonstrates the use of savepoints::
 
     from django.db import transaction
@@ -288,15 +294,17 @@
 
     a.save() # Succeeds, and never undone by savepoint rollback
     try:
-        sid = transaction.savepoint()
+        sid = transaction.savepoint(only_if_needed=True)
         b.save() # Could throw exception
-        transaction.savepoint_commit(sid)
+        transaction.savepoint_commit(sid, only_if_needed=True)
     except IntegrityError:
-        transaction.savepoint_rollback(sid)
+        transaction.savepoint_rollback(sid, only_if_needed=True)
     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.
+``b.save()`` raises an exception. The ``only_if_needed`` flag means that the
+savepoint code will only be executed on databases such as PostgreSQL which
+require it to recover from exceptions, not on other databases.
 
 Database-level autocommit
 -------------------------
