diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
index f54e360e3..7606b6ddc 100644
--- a/lib/ovsdb-idl.c
+++ b/lib/ovsdb-idl.c
@@ -385,6 +385,8 @@ static void ovsdb_idl_send_cond_change(struct ovsdb_idl *idl);
 static void ovsdb_idl_destroy_indexes(struct ovsdb_idl_table *);
 static void ovsdb_idl_add_to_indexes(const struct ovsdb_idl_row *);
 static void ovsdb_idl_remove_from_indexes(const struct ovsdb_idl_row *);
+static int ovsdb_idl_try_commit_loop_txn(struct ovsdb_idl_loop *loop,
+                                         bool *may_need_wakeup);
 
 static void
 ovsdb_idl_db_init(struct ovsdb_idl_db *db, const struct ovsdb_idl_class *class,
@@ -5340,6 +5342,12 @@ struct ovsdb_idl_txn *
 ovsdb_idl_loop_run(struct ovsdb_idl_loop *loop)
 {
     ovsdb_idl_run(loop->idl);
+
+    /* See if we can commit the loop->committing_txn. */
+    if (loop->committing_txn) {
+        ovsdb_idl_try_commit_loop_txn(loop, NULL);
+    }
+
     loop->open_txn = (loop->committing_txn
                       || ovsdb_idl_get_seqno(loop->idl) == loop->skip_seqno
                       ? NULL
@@ -5347,6 +5355,87 @@ ovsdb_idl_loop_run(struct ovsdb_idl_loop *loop)
     return loop->open_txn;
 }
 
+/* Attempts to commit the current transaction, if one is open.
+ *
+ * If a transaction was open, in this or a previous iteration of the main loop,
+ * and had not before finished committing (successfully or unsuccessfully), the
+ * return value is one of:
+ *
+ *  1: The transaction committed successfully (or it did not change anything in
+ *     the database).
+ *  0: The transaction failed.
+ * -1: The commit is still in progress.
+ *
+ * Thus, the return value is -1 if the transaction is in progress and otherwise
+ * true for success, false for failure.
+ *
+ * (In the corner case where the IDL sends a transaction to the database and
+ * the database commits it, and the connection between the IDL and the database
+ * drops before the IDL receives the message confirming the commit, this
+ * function can return 0 even though the transaction succeeded.)
+ */
+static int
+ovsdb_idl_try_commit_loop_txn(struct ovsdb_idl_loop *loop,
+                              bool *may_need_wakeup)
+{
+    if (!loop->committing_txn) {
+        /* Not a meaningful return value: no transaction was in progress. */
+        return 1;
+    }
+
+    int retval;
+    struct ovsdb_idl_txn *txn = loop->committing_txn;
+
+    enum ovsdb_idl_txn_status status = ovsdb_idl_txn_commit(txn);
+    if (status != TXN_INCOMPLETE) {
+        switch (status) {
+        case TXN_TRY_AGAIN:
+            /* We want to re-evaluate the database when it's changed from
+             * the contents that it had when we started the commit.  (That
+             * might have already happened.) */
+            loop->skip_seqno = loop->precommit_seqno;
+            if (ovsdb_idl_get_seqno(loop->idl) != loop->skip_seqno
+                && may_need_wakeup) {
+                *may_need_wakeup = true;
+            }
+            retval = 0;
+            break;
+
+        case TXN_SUCCESS:
+            /* Possibly some work on the database was deferred because no
+             * further transaction could proceed.  Wake up again. */
+            retval = 1;
+            loop->cur_cfg = loop->next_cfg;
+            if (may_need_wakeup) {
+                *may_need_wakeup =  true;
+            }
+            break;
+
+        case TXN_UNCHANGED:
+            retval = 1;
+            loop->cur_cfg = loop->next_cfg;
+            break;
+
+        case TXN_ABORTED:
+        case TXN_NOT_LOCKED:
+        case TXN_ERROR:
+            retval = 0;
+            break;
+
+        case TXN_UNCOMMITTED:
+        case TXN_INCOMPLETE:
+        default:
+            OVS_NOT_REACHED();
+        }
+        ovsdb_idl_txn_destroy(txn);
+        loop->committing_txn = NULL;
+    } else {
+        retval = -1;
+    }
+
+    return retval;
+}
+
 /* Attempts to commit the current transaction, if one is open, and sets up the
  * poll loop to wake up when some more work might be needed.
  *
@@ -5377,57 +5466,11 @@ ovsdb_idl_loop_commit_and_wait(struct ovsdb_idl_loop *loop)
         loop->precommit_seqno = ovsdb_idl_get_seqno(loop->idl);
     }
 
-    struct ovsdb_idl_txn *txn = loop->committing_txn;
-    int retval;
-    if (txn) {
-        enum ovsdb_idl_txn_status status = ovsdb_idl_txn_commit(txn);
-        if (status != TXN_INCOMPLETE) {
-            switch (status) {
-            case TXN_TRY_AGAIN:
-                /* We want to re-evaluate the database when it's changed from
-                 * the contents that it had when we started the commit.  (That
-                 * might have already happened.) */
-                loop->skip_seqno = loop->precommit_seqno;
-                if (ovsdb_idl_get_seqno(loop->idl) != loop->skip_seqno) {
-                    poll_immediate_wake();
-                }
-                retval = 0;
-                break;
-
-            case TXN_SUCCESS:
-                /* Possibly some work on the database was deferred because no
-                 * further transaction could proceed.  Wake up again. */
-                retval = 1;
-                loop->cur_cfg = loop->next_cfg;
-                poll_immediate_wake();
-                break;
-
-            case TXN_UNCHANGED:
-                retval = 1;
-                loop->cur_cfg = loop->next_cfg;
-                break;
-
-            case TXN_ABORTED:
-            case TXN_NOT_LOCKED:
-            case TXN_ERROR:
-                retval = 0;
-                break;
-
-            case TXN_UNCOMMITTED:
-            case TXN_INCOMPLETE:
-            default:
-                OVS_NOT_REACHED();
-            }
-            ovsdb_idl_txn_destroy(txn);
-            loop->committing_txn = NULL;
-        } else {
-            retval = -1;
-        }
-    } else {
-        /* Not a meaningful return value: no transaction was in progress. */
-        retval = 1;
+    bool may_need_wakeup = false;
+    int retval = ovsdb_idl_try_commit_loop_txn(loop, &may_need_wakeup);
+    if (may_need_wakeup) {
+        poll_immediate_wake();
     }
-
     ovsdb_idl_wait(loop->idl);
 
     return retval;
