Description:
After changing innodb_thread_concurrency from 16 to 0 , I noticed some threads stall at srv_conc_enter_innodb.
output of pt-pmp:
96 read,my_real_read,my_net_read,do_command,do_handle_one_connection,handle_one_connection,start_thread,clone
10 libaio::??,os_aio_linux_collect,os_aio_linux_handle,fil_aio_wait,io_handler_thread,start_thread,clone
5 pthread_cond_wait,os_cond_wait,os_event_wait_low,srv_conc_enter_innodb,ha_innobase::index_read,handler::index_read_idx_map,join_read_,join_read__table,make_join_statistics,JOIN::optimize,mysql_select,handle_select,execute_sqlcom_select,mysql_execute_command,mysql_parse,dispatch_command,do_handle_one_connection,handle_one_connection,start_thread,clone
1 sigwait,signal_hand,start_thread,clone
1 pthread_cond_wait,os_cond_wait,os_event_wait_low,srv_master_thread,start_thread,clone
1 pthread_cond_wait,inline_mysql_cond_wait,cache_thread,one_thread_per_connection_end,do_handle_one_connection,handle_one_connection,start_thread,clone
1 pthread_cond_timedwait,os_cond_wait_timed,os_event_wait_time_low,srv_monitor_thread,start_thread,clone
1 pthread_cond_timedwait,os_cond_wait_timed,os_event_wait_time_low,srv_lock_timeout_thread,start_thread,clone
1 pthread_cond_timedwait,os_cond_wait_timed,os_event_wait_time_low,srv_error_monitor_thread,start_thread,clone
1 poll,handle_connections_sockets,mysqld_main,__libc_start_main,_start
and the related code is (quoted from srv_conc_force_exit_innodb):
1364 if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
1365 /* Look for a slot where a thread is waiting and no other
1366 thread has yet released the thread */
1367
1368 slot = UT_LIST_GET_FIRST(srv_conc_queue);
srv_thread_concurrency was not protected by any mutex. If it was set to zero, then threads in srv_conc_queue will not be waked up.
How to repeat:
one session run sysbench and another session change the value of innodb_thread_concurrency. Make sure srv_conc_queue is not empty before changing innodb_thread_concurrency to zero.
Suggested fix:
a rough patch based on MySQL5.5.32
--- a/storage/innobase/srv/srv0srv.c 2013-07-22 10:45:44.663798788 +0800
+++ b/storage/innobase/srv/srv0srv.c 2013-07-22 11:05:07.702493368 +0800
@@ -1227,6 +1227,11 @@
goto retry;
}
+
+ if (srv_thread_concurrency == 0) {
+ os_fast_mutex_unlock(&srv_conc_mutex);
+ return;
+ }
/* Too many threads inside: put the current thread to a queue */
@@ -1361,7 +1366,8 @@
trx->declared_to_be_inside_innodb = FALSE;
trx->n_tickets_to_enter_innodb = 0;
- if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
+ if (srv_conc_n_threads < (lint)srv_thread_concurrency ||
+ srv_thread_concurrency == 0) {
/* Look for a slot where a thread is waiting and no other
thread has yet released the thread */