diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result
index 9c1816e295ce9bbd895e127db4c2514af65c9c15..bbbc607b6f817a0978fb2e6f5da95774ee46b4b3 100644
--- a/mysql-test/r/subselect_innodb.result
+++ b/mysql-test/r/subselect_innodb.result
@@ -96,3 +96,13 @@ id	value	(select t1.value from t1 where t1.id=t2.id)
 1	z	a
 2	x	b
 drop table t1,t2;
+create table t1 (a int, b int) engine=innodb;
+insert into t1 values (1,2), (1,3), (2,3), (2,4), (2,5), (3,4), (4,5), (4,100);
+create table t2 (a int) engine=innodb;
+insert into t2 values (1),(2),(3),(4);
+select a, sum(b) as b from t1 group by a having b > (select max(a) from t2);
+a	b
+1	5
+2	12
+4	105
+drop table t1, t2;
diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test
index 476428321586c946625ceed52e56448f59f00499..8c13171d221ecdc89fc73029efe29670061048ad 100644
--- a/mysql-test/t/subselect_innodb.test
+++ b/mysql-test/t/subselect_innodb.test
@@ -101,3 +101,13 @@ insert into t2 values (1,'z'),(2,'x');
 select t2.id,t2.value,(select t1.value from t1 where t1.id=t2.id) from t2;
 select t2.id,t2.value,(select t1.value from t1 where t1.id=t2.id) from t2;
 drop table t1,t2;
+
+#
+# unlocking tables with subqueries in HAVING
+#
+create table t1 (a int, b int) engine=innodb;
+insert into t1 values (1,2), (1,3), (2,3), (2,4), (2,5), (3,4), (4,5), (4,100);
+create table t2 (a int) engine=innodb;
+insert into t2 values (1),(2),(3),(4);
+select a, sum(b) as b from t1 group by a having b > (select max(a) from t2);
+drop table t1, t2;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 366865cf93eaf5317381ed7f5adeb0444fed83a2..4c1ffeecc97c96c8f8a499395286715e7945f111 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -74,6 +74,11 @@ void Item_subselect::init(st_select_lex *select_lex,
     else
       engine= new subselect_single_select_engine(select_lex, result, this);
   }
+  {
+    SELECT_LEX *upper= unit->outer_select();
+    if (upper->parsing_place == SELECT_LEX_NODE::IN_HAVING)
+      upper->subquery_in_having= 1;
+  }
   DBUG_VOID_RETURN;
 }
 
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index b6cb61fe10e25d603745ce574a9373e21a0ed3a4..d945eef14257977d5237cafd43a18a89f0ce7817 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1008,7 +1008,7 @@ void st_select_lex::init_query()
   ref_pointer_array= 0;
   select_n_having_items= 0;
   prep_where= 0;
-  explicit_limit= 0;
+  subquery_in_having= explicit_limit= 0;
 }
 
 void st_select_lex::init_select()
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 54d9a09c1f388e140df06e8fe208ee5ad279b182..328df2f6bb9da5625b40d01805bf3022a9c144e1 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -433,6 +433,11 @@ class st_select_lex: public st_select_lex_node
   bool having_fix_field;
   /* explicit LIMIT clause was used */
   bool explicit_limit;
+  /*
+    there are subquery in HAVING clause => we can't close tables before
+    query processing end even if we use temporary table
+  */
+  bool subquery_in_having;
 
   /* 
      SELECT for SELECT command st_select_lex. Used to privent scaning
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 151c25b0ccaccb2317896bb7775df2a38eda9b62..487c5bfd99de3d990f9261e10a269edd4c524b18 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3884,7 +3884,8 @@ JOIN::join_free(bool full)
   */
   if ((full || !select_lex->uncacheable) &&
       lock && thd->lock &&
-      !(select_options & SELECT_NO_UNLOCK))
+      !(select_options & SELECT_NO_UNLOCK) &&
+      !select_lex->subquery_in_having)
   {
     mysql_unlock_read_tables(thd, lock);// Don't free join->lock
     lock=0;