diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
index ebe8875..c943ff0 100644
--- a/django/db/backends/__init__.py
+++ b/django/db/backends/__init__.py
@@ -108,12 +108,15 @@ class BaseDatabaseWrapper(object):
         over to the surrounding block, as a commit will commit all changes, even
         those from outside. (Commits are on connection level.)
         """
-        self._leave_transaction_management(self.is_managed())
-        if self.transaction_state:
-            del self.transaction_state[-1]
-        else:
+        try:
+            self.transaction_state.pop()
+        except IndexError:
             raise TransactionManagementError("This code isn't under transaction "
-                "management")
+                                             "management")
+        # Note that it is intentional we pop first one entry from the
+        # transaction_state stack, and then use the topmost entry (given by
+        # is_managed()) for _leave_transaction_management(). Refs #16047.
+        self._leave_transaction_management(self.is_managed())
         if self._dirty:
             self.rollback()
             raise TransactionManagementError("Transaction managed block ended with "
diff --git a/tests/regressiontests/transactions_regress/tests.py b/tests/regressiontests/transactions_regress/tests.py
index 5972263..202051d 100644
--- a/tests/regressiontests/transactions_regress/tests.py
+++ b/tests/regressiontests/transactions_regress/tests.py
@@ -1,11 +1,11 @@
 from __future__ import absolute_import
 
 from django.core.exceptions import ImproperlyConfigured
-from django.db import connection, transaction
+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
 from django.test.utils import override_settings
-from django.utils.unittest import skipIf
+from django.utils.unittest import skipIf, skipUnless
 
 from .models import Mod, M2mA, M2mB
 
@@ -174,6 +174,42 @@ class TestTransactionClosing(TransactionTestCase):
         """
         self.test_failing_query_transaction_closed()
 
+class TestAutocommit(TransactionTestCase):
+    @skipUnless(connection.vendor == 'postgresql',
+                "This test only valid for PostgreSQL")
+    def test_autocommit_restored(self):
+        """
+        If autocommit is enabled, the isolation level should return to
+        autocommit when leaving transaction management. Refs #16047.
+
+        NOTE: The PostgreSQL specific part is the isolation
+        level constants.
+        """
+        try:
+            # We want a clean backend with autocommit = True, so
+            # first we need to do a bit of work to have that.
+            old_backend = connections[DEFAULT_DB_ALIAS]
+            settings = old_backend.settings_dict.copy()
+            settings['OPTIONS']['autocommit'] = True
+            new_backend = old_backend.__class__(settings, DEFAULT_DB_ALIAS)
+            connections[DEFAULT_DB_ALIAS] = new_backend
+            self.assertTrue(connection.features.uses_autocommit)
+            # Ready to do the actual test.
+            transaction.enter_transaction_management()
+            # Ok, are we in isolation level read committed
+            self.assertEqual(connection.isolation_level, 2)
+            transaction.managed(True)
+            # Test stacking
+            transaction.enter_transaction_management()
+            transaction.leave_transaction_management()
+            # We should still be in isolation level 2
+            self.assertEqual(connection.isolation_level, 2)
+            transaction.leave_transaction_management()
+            # And finally back in autocommit
+            self.assertEqual(connection.isolation_level, 0)
+        finally:
+            connections[DEFAULT_DB_ALIAS] = old_backend
+
 
 class TestManyToManyAddTransaction(TransactionTestCase):
     def test_manyrelated_add_commit(self):
