diff --git a/lib/ovsdb-idl-provider.h b/lib/ovsdb-idl-provider.h
index 2eee4fd..30d1d08 100644
--- a/lib/ovsdb-idl-provider.h
+++ b/lib/ovsdb-idl-provider.h
@@ -73,6 +73,7 @@ struct ovsdb_idl_row {
     struct ovs_list dst_arcs;   /* Backward arcs (ovsdb_idl_arc.dst_node). */
     struct ovsdb_idl_table *table; /* Containing table. */
     struct ovsdb_datum *old_datum; /* Committed data (null if orphaned). */
+    bool parsed; /* Whether the row is parsed. */
 
     /* Transactional data. */
     struct ovsdb_datum *new_datum; /* Modified data (null to delete row). */
@@ -88,6 +89,7 @@ struct ovsdb_idl_row {
     unsigned int change_seqno[OVSDB_IDL_CHANGE_MAX];
     struct ovs_list track_node; /* Rows modified/added/deleted by IDL */
     unsigned long int *updated; /* Bitmap of columns updated by IDL */
+    struct ovsdb_datum *tracked_old_datum; /* Old deleted data. */
 };
 
 struct ovsdb_idl_column {
diff --git a/lib/ovsdb-idl.c b/lib/ovsdb-idl.c
index 9ab5d67..a796847 100644
--- a/lib/ovsdb-idl.c
+++ b/lib/ovsdb-idl.c
@@ -1705,7 +1705,16 @@ ovsdb_idl_db_track_clear(struct ovsdb_idl_db *db)
                 }
                 ovs_list_remove(&row->track_node);
                 ovs_list_init(&row->track_node);
-                if (ovsdb_idl_row_is_orphan(row)) {
+                if (ovsdb_idl_row_is_orphan(row) && row->tracked_old_datum) {
+                    ovsdb_idl_row_unparse(row);
+                    const struct ovsdb_idl_table_class *class =
+                                                        row->table->class_;
+                    for (size_t c = 0; c < class->n_columns; c++) {
+                        ovsdb_datum_destroy(&row->tracked_old_datum[c],
+                                            &class->columns[c].type);
+                    }
+                    free(row->tracked_old_datum);
+                    row->tracked_old_datum = NULL;
                     free(row);
                 }
             }
@@ -2432,10 +2441,14 @@ ovsdb_idl_row_parse(struct ovsdb_idl_row *row)
     const struct ovsdb_idl_table_class *class = row->table->class_;
     size_t i;
 
+    if (row->parsed) {
+        ovsdb_idl_row_unparse(row);
+    }
     for (i = 0; i < class->n_columns; i++) {
         const struct ovsdb_idl_column *c = &class->columns[i];
         (c->parse)(row, &row->old_datum[i]);
     }
+    row->parsed = true;
 }
 
 static void
@@ -2444,10 +2457,14 @@ ovsdb_idl_row_unparse(struct ovsdb_idl_row *row)
     const struct ovsdb_idl_table_class *class = row->table->class_;
     size_t i;
 
+    if (!row->parsed) {
+        return;
+    }
     for (i = 0; i < class->n_columns; i++) {
         const struct ovsdb_idl_column *c = &class->columns[i];
         (c->unparse)(row);
     }
+    row->parsed = false;
 }
 
 /* The OVSDB-IDL Compound Indexes feature allows for the creation of custom
@@ -2775,13 +2792,18 @@ ovsdb_idl_row_clear_old(struct ovsdb_idl_row *row)
 {
     ovs_assert(row->old_datum == row->new_datum);
     if (!ovsdb_idl_row_is_orphan(row)) {
-        const struct ovsdb_idl_table_class *class = row->table->class_;
-        size_t i;
+        if (ovsdb_idl_track_is_set(row->table)) {
+            row->tracked_old_datum = row->old_datum;
+        } else {
+            const struct ovsdb_idl_table_class *class = row->table->class_;
+            size_t i;
 
-        for (i = 0; i < class->n_columns; i++) {
-            ovsdb_datum_destroy(&row->old_datum[i], &class->columns[i].type);
+            for (i = 0; i < class->n_columns; i++) {
+                ovsdb_datum_destroy(&row->old_datum[i],
+                                    &class->columns[i].type);
+            }
+            free(row->old_datum);
         }
-        free(row->old_datum);
         row->old_datum = row->new_datum = NULL;
     }
 }
@@ -2957,6 +2979,7 @@ ovsdb_idl_row_destroy_postprocess(struct ovsdb_idl_db *db)
             LIST_FOR_EACH_SAFE(row, next, track_node, &table->track_list) {
                 if (!ovsdb_idl_track_is_set(row->table)) {
                     ovs_list_remove(&row->track_node);
+                    ovsdb_idl_row_unparse(row);
                     free(row);
                 }
             }
@@ -2987,7 +3010,6 @@ static void
 ovsdb_idl_delete_row(struct ovsdb_idl_row *row)
 {
     ovsdb_idl_remove_from_indexes(row);
-    ovsdb_idl_row_unparse(row);
     ovsdb_idl_row_clear_arcs(row, true);
     ovsdb_idl_row_clear_old(row);
     if (ovs_list_is_empty(&row->dst_arcs)) {
