diff --git a/django/db/models/base.py b/django/db/models/base.py
index ebd67be..826b211 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -465,108 +465,115 @@ class Model(object):
 
     save.alters_data = True
 
-    def save_base(self, raw=False, cls=None, origin=None, force_insert=False,
-            force_update=False, using=None):
+    def save_base(self, raw=False, force_insert=False, force_update=False, using=None):
         """
-        Does the heavy-lifting involved in saving. Subclasses shouldn't need to
-        override this method. It's separate from save() in order to hide the
-        need for overrides of save() to pass around internal-only parameters
-        ('raw', 'cls', and 'origin').
+        This method does some setup unique to the first save (signals,
+        transaction handling etc).
+
+        The actual saving is delegated to _save_base.
         """
-        using = using or router.db_for_write(self.__class__, instance=self)
         assert not (force_insert and force_update)
-        if cls is None:
-            cls = self.__class__
-            meta = cls._meta
-            if not meta.proxy:
-                origin = cls
-        else:
-            meta = cls._meta
+        cls = self.__class__
+        using = using or router.db_for_write(cls, instance=self)
+        if not cls._meta.auto_created:
+            signals.pre_save.send(sender=cls, instance=self, raw=raw, using=using)
+
+        record_exists = self._save_base(raw, cls, force_insert, force_update, using)
+        # Store the database on which the object was saved
+        self._state.db = using
+        # Once saved, this is no longer a to-be-added instance.
+        self._state.adding = False
 
-        if origin and not meta.auto_created:
-            signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using)
+        # Commit the transaction & signal that the save is complete.
+        transaction.commit_unless_managed(using=using)
+        if not cls._meta.auto_created:
+            signals.post_save.send(sender=cls, instance=self,
+                created=(not record_exists), raw=raw, using=using)
+
+    save_base.alters_data = True
+
+    def _save_base(self, raw, cls, force_insert, force_update, using):
+        """
+        Does the heavy-lifting involved in saving. Subclasses shouldn't need to
+        override this method.
+
+        Internal parameters:
+         - raw: If set, save just the table used by self.__class__. That is, do
+           not follow inheritance chains, except for proxy-skipping.
+         - cls: The class we are currently saving. self.__class__ or one of its
+           parents.
+        """
+        meta = cls._meta
+        # Skip proxy chains. Defer the save of proxy objects to their actual
+        # underlying model.
+        if meta.proxy:
+            # A proxy model can have only one parent.
+            parent, field = meta.parents.items()[0]
+            return self._save_base(raw, parent, force_insert, force_update, using)
 
         # If we are in a raw save, save the object exactly as presented.
         # That means that we don't try to be smart about saving attributes
         # that might have come from the parent class - we just save the
         # attributes we have been given to the class we have been given.
-        # We also go through this process to defer the save of proxy objects
-        # to their actual underlying model.
-        if not raw or meta.proxy:
-            if meta.proxy:
-                org = cls
-            else:
-                org = None
+        if not raw:
             for parent, field in meta.parents.items():
                 # At this point, parent's primary key field may be unknown
                 # (for example, from administration form which doesn't fill
                 # this field). If so, fill it.
-                if field and getattr(self, parent._meta.pk.attname) is None and getattr(self, field.attname) is not None:
+                if (field and getattr(self, parent._meta.pk.attname) is None
+                        and getattr(self, field.attname) is not None):
                     setattr(self, parent._meta.pk.attname, getattr(self, field.attname))
 
-                self.save_base(cls=parent, origin=org, using=using)
-
+                # For multitable inheritance, the force_insert and force_update
+                # are in effect only for the topmost save. So override them to
+                # False.
+                self._save_base(raw, parent, False, False, using)
                 if field:
                     setattr(self, field.attname, self._get_pk_val(parent._meta))
-            if meta.proxy:
-                return
-
-        if not meta.proxy:
-            non_pks = [f for f in meta.local_fields if not f.primary_key]
-
-            # First, try an UPDATE. If that doesn't update anything, do an INSERT.
-            pk_val = self._get_pk_val(meta)
-            pk_set = pk_val is not None
-            record_exists = True
-            manager = cls._base_manager
-            if pk_set:
-                # Determine whether a record with the primary key already exists.
-                if (force_update or (not force_insert and
-                        manager.using(using).filter(pk=pk_val).exists())):
-                    # It does already exist, so do an UPDATE.
-                    if force_update or non_pks:
-                        values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
-                        if values:
-                            rows = manager.using(using).filter(pk=pk_val)._update(values)
-                            if force_update and not rows:
-                                raise DatabaseError("Forced update did not affect any rows.")
-                else:
-                    record_exists = False
-            if not pk_set or not record_exists:
-                if meta.order_with_respect_to:
-                    # If this is a model with an order_with_respect_to
-                    # autopopulate the _order field
-                    field = meta.order_with_respect_to
-                    order_value = manager.using(using).filter(**{field.name: getattr(self, field.attname)}).count()
-                    self._order = order_value
-
-                fields = meta.local_fields
-                if not pk_set:
-                    if force_update:
-                        raise ValueError("Cannot force an update in save() with no primary key.")
-                    fields = [f for f in fields if not isinstance(f, AutoField)]
 
+        non_pks = [f for f in meta.local_fields if not f.primary_key]
+
+        pk_val = self._get_pk_val(meta)
+        pk_set = pk_val is not None
+        record_exists = True
+        manager = cls._base_manager
+        if pk_set:
+            # Determine whether a record with the primary key already exists.
+            if (force_update or (not force_insert and
+                    manager.using(using).filter(pk=pk_val).exists())):
+                # It does already exist, so do an UPDATE.
+                if force_update or non_pks:
+                    values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
+                    if values:
+                        rows = manager.using(using).filter(pk=pk_val)._update(values)
+                        if force_update and not rows:
+                            raise DatabaseError("Forced update did not affect any rows.")
+            else:
                 record_exists = False
-
-                update_pk = bool(meta.has_auto_field and not pk_set)
-                result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
-
-                if update_pk:
-                    setattr(self, meta.pk.attname, result)
-            transaction.commit_unless_managed(using=using)
-
-        # Store the database on which the object was saved
-        self._state.db = using
-        # Once saved, this is no longer a to-be-added instance.
-        self._state.adding = False
-
-        # Signal that the save is complete
-        if origin and not meta.auto_created:
-            signals.post_save.send(sender=origin, instance=self,
-                created=(not record_exists), raw=raw, using=using)
-
-
-    save_base.alters_data = True
+        if not pk_set or not record_exists:
+            if meta.order_with_respect_to:
+                # If this is a model with an order_with_respect_to
+                # autopopulate the _order field
+                field = meta.order_with_respect_to
+                order_value = manager.using(using).filter(**{field.name: getattr(self, field.attname)}).count()
+                self._order = order_value
+
+            fields = meta.local_fields
+            if not pk_set:
+                if force_update:
+                    raise ValueError("Cannot force an update in save() with no primary key.")
+                fields = [f for f in fields if not isinstance(f, AutoField)]
+
+            record_exists = False
+
+            update_pk = bool(meta.has_auto_field and not pk_set)
+            result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)
+
+            if update_pk:
+                setattr(self, meta.pk.attname, result)
+        return record_exists
+
+    _save_base.alters_data = True
 
     def delete(self, using=None):
         using = using or router.db_for_write(self.__class__, instance=self)
diff --git a/tests/modeltests/proxy_models/tests.py b/tests/modeltests/proxy_models/tests.py
index 3ec8465..13b6a36 100644
--- a/tests/modeltests/proxy_models/tests.py
+++ b/tests/modeltests/proxy_models/tests.py
@@ -247,6 +247,14 @@ class ProxyModelTests(TestCase):
         resp = [u.name for u in UserProxy.objects.all()]
         self.assertEqual(resp, ['Bruce'])
 
+    def test_proxy_force_insert_update(self):
+        with self.assertNumQueries(1):
+            u = UserProxy(name='George')
+            u.save(force_insert=True)
+        with self.assertNumQueries(1):
+            u.name = 'Bruce'
+            u.save(force_update=True)
+
     def test_select_related(self):
         """
         We can still use `select_related()` to include related models in our
diff --git a/tests/modeltests/transactions/models.py b/tests/modeltests/transactions/models.py
index 66acb9f..b0bad3c 100644
--- a/tests/modeltests/transactions/models.py
+++ b/tests/modeltests/transactions/models.py
@@ -19,4 +19,10 @@ class Reporter(models.Model):
         ordering = ('first_name', 'last_name')
 
     def __unicode__(self):
-        return u"%s %s" % (self.first_name, self.last_name)
\ No newline at end of file
+        return u"%s %s" % (self.first_name, self.last_name)
+
+class BaseModel(models.Model):
+    pass
+
+class InheritedModel(BaseModel):
+    uniq_id = models.IntegerField(unique=True)
diff --git a/tests/modeltests/transactions/tests.py b/tests/modeltests/transactions/tests.py
index ed416e2..f4c6328 100644
--- a/tests/modeltests/transactions/tests.py
+++ b/tests/modeltests/transactions/tests.py
@@ -3,7 +3,7 @@ from __future__ import with_statement, absolute_import
 from django.db import connection, transaction, IntegrityError
 from django.test import TransactionTestCase, skipUnlessDBFeature
 
-from .models import Reporter
+from .models import Reporter, InheritedModel, BaseModel
 
 
 class TransactionTests(TransactionTestCase):
@@ -160,6 +160,26 @@ class TransactionTests(TransactionTestCase):
             using_manually_managed_mistake
         )
 
+    @skipUnlessDBFeature('supports_transactions')
+    def test_nonmanaged_inheritance_save(self):
+        """
+        When running in nonmanaged mode, Django commits transactions after
+        each save. It multitable inheritance case, test that the commit is
+        done only once, after all tables have been saved. Check it by making
+        forcing an IntegrityError, and see what happens.
+        """
+        InheritedModel(uniq_id=1).save()
+        try:
+            InheritedModel(uniq_id=1).save()
+            # Make sure there is an error!
+            self.assertFalse(True)
+        except IntegrityError:
+            pass
+        # Now, rollback the connection and see what got saved.
+        connection.rollback()
+        self.assertEquals(InheritedModel.objects.count(), 1)
+        self.assertEquals(BaseModel.objects.count(), 1)
+
 
 class TransactionRollbackTests(TransactionTestCase):
     def execute_bad_sql(self):
