diff --git a/mysql-test/r/query_cache_notembedded.result b/mysql-test/r/query_cache_notembedded.result index 8e5df012cfb..bf582bfaec6 100644 --- a/mysql-test/r/query_cache_notembedded.result +++ b/mysql-test/r/query_cache_notembedded.result @@ -345,3 +345,19 @@ id drop table t1; drop function f1; set GLOBAL query_cache_size=0; +DROP TABLE IF EXISTS t1; +FLUSH STATUS; +SET GLOBAL query_cache_size=1048576; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +SHOW STATUS LIKE 'Qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 0 +LOCK TABLES t1 WRITE; +SELECT * FROM t1; +UNLOCK TABLES; +SHOW STATUS LIKE 'Qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 0 +DROP TABLE t1; +SET GLOBAL query_cache_size= default; diff --git a/mysql-test/t/query_cache_notembedded.test b/mysql-test/t/query_cache_notembedded.test index a4f4144d9c6..c427e0d1afc 100644 --- a/mysql-test/t/query_cache_notembedded.test +++ b/mysql-test/t/query_cache_notembedded.test @@ -222,3 +222,34 @@ disconnect con2; connection default; set GLOBAL query_cache_size=0; + +# +# Bug#40264: Aborted cached query causes query to hang indefinitely on next cache hit +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +FLUSH STATUS; +SET GLOBAL query_cache_size=1048576; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +SHOW STATUS LIKE 'Qcache_queries_in_cache'; +LOCK TABLES t1 WRITE; +connect(con1,localhost,root,,); +--send SELECT * FROM t1 +connection default; +let $show_type= open tables where `table`='t1' and in_use=2; +let $show_pattern= '%t1%2%'; +--source include/wait_show_pattern.inc +dirty_close con1; +UNLOCK TABLES; +let $show_type= open tables where `table`='t1' and in_use=0; +let $show_pattern= '%t1%0%'; +--source include/wait_show_pattern.inc +SHOW STATUS LIKE 'Qcache_queries_in_cache'; +DROP TABLE t1; +SET GLOBAL query_cache_size= default; + +# End of 5.0 tests diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 4a521d83192..b55fa148e24 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -710,7 +710,12 @@ void query_cache_end_of_result(THD *thd) if (thd->net.query_cache_query == 0) DBUG_VOID_RETURN; - if (thd->killed) + /* + Check if the NET layer raised a unreported error -- my_error() and + as a consequence query_cache_abort() haven't been called. Abort the + cached result as it might be only partially complete. + */ + if (thd->killed || thd->net.report_error) { query_cache_abort(&thd->net); DBUG_VOID_RETURN;