diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
index 649f807..c637640 100644
--- a/django/db/backends/__init__.py
+++ b/django/db/backends/__init__.py
@@ -106,11 +106,16 @@ class BaseDatabaseWrapper(object):
             self._dirty = False
         self._enter_transaction_management(managed)
 
-    def leave_transaction_management(self):
+    def leave_transaction_management(self, exception=None):
         """
         Leaves transaction management for a running thread. A dirty flag is carried
         over to the surrounding block, as a commit will commit all changes, even
         those from outside. (Commits are on connection level.)
+
+        If this function is called from within a finally block where an
+        exception is in the process of working its way up the stack, pass
+        the exception argument so we don't raise a new exception over the
+        pending one.
         """
         if self.transaction_state:
             del self.transaction_state[-1]
@@ -122,8 +127,9 @@ class BaseDatabaseWrapper(object):
         self._leave_transaction_management(self.is_managed())
         if self._dirty:
             self.rollback()
-            raise TransactionManagementError(
-                "Transaction managed block ended with pending COMMIT/ROLLBACK")
+            if exception is None:
+                raise TransactionManagementError(
+                    "Transaction managed block ended with pending COMMIT/ROLLBACK")
         self._dirty = False
 
     def validate_thread_sharing(self):
diff --git a/django/db/transaction.py b/django/db/transaction.py
index f3ce2b2..91744f7 100644
--- a/django/db/transaction.py
+++ b/django/db/transaction.py
@@ -39,7 +39,7 @@ def enter_transaction_management(managed=True, using=None):
     connection = connections[using]
     connection.enter_transaction_management(managed)
 
-def leave_transaction_management(using=None):
+def leave_transaction_management(using=None, exception=None):
     """
     Leaves transaction management for a running thread. A dirty flag is carried
     over to the surrounding block, as a commit will commit all changes, even
@@ -48,7 +48,7 @@ def leave_transaction_management(using=None):
     if using is None:
         using = DEFAULT_DB_ALIAS
     connection = connections[using]
-    connection.leave_transaction_management()
+    connection.leave_transaction_management(exception)
 
 def is_dirty(using=None):
     """
@@ -284,6 +284,6 @@ def commit_manually(using=None):
         managed(True, using=using)
 
     def exiting(exc_value, using):
-        leave_transaction_management(using=using)
+        leave_transaction_management(using=using, exception=exc_value)
 
     return _transaction_func(entering, exiting, using)
diff --git a/docs/topics/db/transactions.txt b/docs/topics/db/transactions.txt
index 9928354..2ca2265 100644
--- a/docs/topics/db/transactions.txt
+++ b/docs/topics/db/transactions.txt
@@ -190,6 +190,13 @@ managers, too.
         def viewfunc2(request):
             ....
 
+.. note::
+
+    If there's any uncaught exception raised from your function,
+    Django will rollback the transaction and reraise the exception.
+    This usually happened when a call to ``transaction.commit()``
+    itself from your function raised an exception.
+
 .. _topics-db-transactions-requirements:
 
 Requirements for transaction handling
diff --git a/tests/regressiontests/transactions_regress/tests.py b/tests/regressiontests/transactions_regress/tests.py
index 90b3df0..f2a3be1 100644
--- a/tests/regressiontests/transactions_regress/tests.py
+++ b/tests/regressiontests/transactions_regress/tests.py
@@ -1,6 +1,6 @@
 from __future__ import absolute_import
 
-from django.core.exceptions import ImproperlyConfigured
+from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
 from django.db import connection, connections, transaction, DEFAULT_DB_ALIAS
 from django.db.transaction import commit_on_success, commit_manually, TransactionManagementError
 from django.test import TransactionTestCase, skipUnlessDBFeature
@@ -228,6 +228,27 @@ class TestPostgresAutocommit(TransactionTestCase):
         self.assertEqual(connection.isolation_level, self._autocommit)
 
 
+class TestExceptionDuringTransaction(TransactionTestCase):
+    """ When an exception happens during a transaction, the transaction should
+        not swallow the original exception and replace it by a
+        TransactionManagementError. The original exception should have priority.
+    """
+
+    def test_commit_manually_exception_raised(self):
+        @commit_manually
+        def fun_with_exception():
+            _ = Mod.objects.get(fld=777)
+
+        self.assertRaises(ObjectDoesNotExist, fun_with_exception)
+
+    def test_commit_on_success_exception_raised(self):
+        @commit_on_success
+        def fun_with_exception():
+            _ = Mod.objects.get(fld=777)
+
+        self.assertRaises(ObjectDoesNotExist, fun_with_exception)
+
+
 class TestManyToManyAddTransaction(TransactionTestCase):
     def test_manyrelated_add_commit(self):
         "Test for https://code.djangoproject.com/ticket/16818"
