diff --git a/mysql-test/suite/perfschema/r/thread_cache.result b/mysql-test/suite/perfschema/r/thread_cache.result new file mode 100644 index 00000000000..de4d19f9c64 --- /dev/null +++ b/mysql-test/suite/perfschema/r/thread_cache.result @@ -0,0 +1,34 @@ +SET @saved_thread_cache_size = @@global.thread_cache_size; +set global thread_cache_size = 0; +show variables like "thread_cache_size"; +Variable_name Value +thread_cache_size 0 +select @id_increment; +@id_increment +1 +select @thread_id_increment; +@thread_id_increment +1 +select @id_increment; +@id_increment +1 +select @thread_id_increment; +@thread_id_increment +1 +set global thread_cache_size = 100; +show variables like "thread_cache_size"; +Variable_name Value +thread_cache_size 100 +select @id_increment; +@id_increment +1 +select @thread_id_increment; +@thread_id_increment +1 +select @id_increment; +@id_increment +1 +select @thread_id_increment; +@thread_id_increment +1 +set global thread_cache_size = @saved_thread_cache_size; diff --git a/mysql-test/suite/perfschema/t/thread_cache.test b/mysql-test/suite/perfschema/t/thread_cache.test new file mode 100644 index 00000000000..8c3271ba406 --- /dev/null +++ b/mysql-test/suite/perfschema/t/thread_cache.test @@ -0,0 +1,134 @@ +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA + +# Tests for PERFORMANCE_SCHEMA + +--source include/not_embedded.inc +--source include/have_perfschema.inc + +# Setup + +SET @saved_thread_cache_size = @@global.thread_cache_size; + +set global thread_cache_size = 0; + +show variables like "thread_cache_size"; + +connect (con1, localhost, root, , ); + +let $con1_ID=`select connection_id()`; + +let $con1_THREAD_ID=`select thread_id from performance_schema.PROCESSLIST + where ID = connection_id()`; + +connect (con2, localhost, root, , ); + +let $con2_ID=`select connection_id()`; + +let $con2_THREAD_ID=`select thread_id from performance_schema.PROCESSLIST + where ID = connection_id()`; + +connection default; + +--disable_query_log +eval select ($con2_ID - $con1_ID) into @id_increment; +eval select ($con2_THREAD_ID - $con1_THREAD_ID) into @thread_id_increment; +--enable_query_log + +# Expect 1, connection_id() is incremented for each new connection +select @id_increment; +# Expect 1, THREAD_ID is incremented for each new connection +select @thread_id_increment; + +disconnect con2; + +connect (con3, localhost, root, , ); + +let $con3_ID=`select connection_id()`; + +let $con3_THREAD_ID=`select thread_id from performance_schema.PROCESSLIST + where ID = connection_id()`; + +disconnect con3; +disconnect con1; + +connection default; + +--disable_query_log +eval select ($con3_ID - $con2_ID) into @id_increment; +eval select ($con3_THREAD_ID - $con2_THREAD_ID) into @thread_id_increment; +--enable_query_log + +select @id_increment; +select @thread_id_increment; + +set global thread_cache_size = 100; + +show variables like "thread_cache_size"; + +connect (con1, localhost, root, , ); + +let $con1_ID=`select connection_id()`; + +let $con1_THREAD_ID=`select thread_id from performance_schema.PROCESSLIST + where ID = connection_id()`; + +connect (con2, localhost, root, , ); + +let $con2_ID=`select connection_id()`; + +let $con2_THREAD_ID=`select thread_id from performance_schema.PROCESSLIST + where ID = connection_id()`; + +connection default; + +--disable_query_log +eval select ($con2_ID - $con1_ID) into @id_increment; +eval select ($con2_THREAD_ID - $con1_THREAD_ID) into @thread_id_increment; +--enable_query_log + +select @id_increment; +select @thread_id_increment; + +disconnect con2; + +connect (con3, localhost, root, , ); + +let $con3_ID=`select connection_id()`; + +let $con3_THREAD_ID=`select thread_id from performance_schema.PROCESSLIST + where ID = connection_id()`; + +disconnect con3; +disconnect con1; + +connection default; + +--disable_query_log +eval select ($con3_ID - $con2_ID) into @id_increment; +eval select ($con3_THREAD_ID - $con2_THREAD_ID) into @thread_id_increment; +--enable_query_log + +# When caching threads, the pthread that executed con2 was parked in the +# cache on disconnect, and then picked up con3. + +# Still expect a new connection_id() +select @id_increment; + +# And expect a new instrumentation: the THREAD_ID of old connections should not be reused. +select @thread_id_increment; + +set global thread_cache_size = @saved_thread_cache_size; + diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ddc5c17ba4b..099e533a560 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,4 +1,4 @@ -/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. +/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2068,6 +2068,16 @@ static bool cache_thread() /* Don't kill the thread, just put it in cache for reuse */ DBUG_PRINT("info", ("Adding thread to cache")); cached_thread_count++; + +#ifdef HAVE_PSI_INTERFACE + /* + Delete the instrumentation for the job that just completed, + before parking this pthread in the cache (blocked on COND_thread_cache). + */ + if (likely(PSI_server != NULL)) + PSI_server->delete_current_thread(); +#endif + while (!abort_loop && ! wake_thread && ! kill_cached_threads) mysql_cond_wait(&COND_thread_cache, &LOCK_thread_count); cached_thread_count--; @@ -2080,6 +2090,21 @@ static bool cache_thread() thd= thread_cache.get(); thd->thread_stack= (char*) &thd; // For store_globals (void) thd->store_globals(); + +#ifdef HAVE_PSI_INTERFACE + /* + Create new instrumentation for the new THD job, + and attach it to this running pthread. + */ + if (likely(PSI_server != NULL)) + { + PSI_thread *psi= PSI_server->new_thread(key_thread_one_connection, + thd, thd->thread_id); + if (likely(psi != NULL)) + PSI_server->set_thread(psi); + } +#endif + /* THD::mysys_var::abort is associated with physical thread rather than with THD object. So we need to reset this flag before using