diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result
index 9db03855c01fb15761c17c00f18831166c14fc7e..7ad0f212d99367c28aa7fbec107bf77b5bad07d3 100644
--- a/mysql-test/r/heap_btree.result
+++ b/mysql-test/r/heap_btree.result
@@ -336,4 +336,11 @@ a	b
 NULL	NULL
 NULL	1
 drop table t1;
+#
+# bug#39918 - memory (heap) engine crashing while executing self join with delete
+#
+CREATE TABLE t1(a INT, KEY USING BTREE (a)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES(1),(1);
+DELETE a1 FROM t1 AS a1, t1 AS a2 WHERE a1.a=a2.a;
+DROP TABLE t1;
 End of 5.0 tests
diff --git a/mysql-test/t/heap_btree.test b/mysql-test/t/heap_btree.test
index b51eeb27331aa4dc89095abf89bfce240aab9da4..637c6ba1c81b471ef5e91f14afb4958fb983fbd2 100644
--- a/mysql-test/t/heap_btree.test
+++ b/mysql-test/t/heap_btree.test
@@ -253,5 +253,13 @@ insert into t1 values (1, 1), (3, 3), (2, 2), (NULL, 1), (NULL, NULL), (0, 0);
 select * from t1 where a is null;
 drop table t1;
 
+-- echo #
+-- echo # bug#39918 - memory (heap) engine crashing while executing self join with delete
+-- echo #
+
+CREATE TABLE t1(a INT, KEY USING BTREE (a)) ENGINE=MEMORY;
+INSERT INTO t1 VALUES(1),(1);
+DELETE a1 FROM t1 AS a1, t1 AS a2 WHERE a1.a=a2.a;
+DROP TABLE t1;
 --echo End of 5.0 tests
 
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 1b42e5224914782780e7c372c4bc709f57cc8db1..7b967206305b7e753ed3c78f816695cc15983792 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -582,6 +582,11 @@ int mysql_multi_delete_prepare(THD *thd)
       }
     }
   }
+  /*
+    Reset the exclude flag to false so it doesn't interfare
+    with further calls to unique_table
+  */
+  lex->select_lex.exclude_from_table_unique_test= FALSE;
   DBUG_RETURN(FALSE);
 }
 
@@ -617,11 +622,24 @@ multi_delete::initialize_tables(JOIN *join)
     DBUG_RETURN(1);
 
   table_map tables_to_delete_from=0;
+  delete_while_scanning= 1;
   for (walk= delete_tables; walk; walk= walk->next_local)
+  {
     tables_to_delete_from|= walk->table->map;
+    if (delete_while_scanning &&
+        unique_table(thd, walk, join->tables_list, false))
+    {
+      /*
+        If the table we are going to delete from appears
+        in join, we need to defer delete. So the delete
+        doesn't interfers with the scaning of results.
+      */
+      delete_while_scanning= 0;
+    }
+  }
+
 
   walk= delete_tables;
-  delete_while_scanning= 1;
   for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
        tab < end;
        tab++)