in "struct show_var_st status_vars[]= {" ...
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
-@@ -335,6 +335,7 @@
+@@ -336,6 +336,7 @@
sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_FUNC]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_TRIGGER]= CF_STATUS_COMMAND;
-@@ -2359,12 +2360,16 @@
+@@ -2368,12 +2369,17 @@
mysql_mutex_unlock(&LOCK_active_mi);
break;
}
if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
goto error;
- mysql_mutex_lock(&LOCK_active_mi);
-+ if(SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command)
++ bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command;
++ if(do_lock)
+ {
+ mysql_mutex_lock(&LOCK_active_mi);
+ }
if (active_mi != NULL)
{
res = show_master_info(thd, active_mi);
-@@ -2375,7 +2380,10 @@
+@@ -2384,7 +2390,19 @@
WARN_NO_MASTER_INFO, ER(WARN_NO_MASTER_INFO));
my_ok(thd);
}
- mysql_mutex_unlock(&LOCK_active_mi);
-+ if(SQLCOM_SHOW_SLAVE_NOLOCK_STAT != lex->sql_command)
++ if(do_lock)
+ {
+ mysql_mutex_unlock(&LOCK_active_mi);
+ }
++ DBUG_EXECUTE_IF("after_show_slave_status",
++ {
++ const char act[]=
++ "now "
++ "signal signal.after_show_slave_status";
++ DBUG_ASSERT(opt_debug_sync_timeout > 0);
++ DBUG_ASSERT(!debug_sync_set_action(current_thd,
++ STRING_WITH_LEN(act)));
++ };);
break;
}
case SQLCOM_SHOW_MASTER_STAT:
%token STDDEV_SAMP_SYM /* SQL-2003-N */
%token STD_SYM
%token STOP_SYM
-@@ -11086,6 +11087,10 @@
+@@ -11105,6 +11106,11 @@
{
Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
}
++ /* SHOW SLAVE STATUS NOLOCK */
+ | SLAVE STATUS_SYM NOLOCK_SYM
+ {
+ Lex->sql_command = SQLCOM_SHOW_SLAVE_NOLOCK_STAT; //SQLCOM_SHOW_SLAVE_NOLOCK_STAT;
{
#ifdef HAVE_RESPONSE_TIME_DISTRIBUTION
--- /dev/null
++++ b/mysql-test/t/percona_show_slave_status_nolock.test
+@@ -0,0 +1,90 @@
++--source include/master-slave.inc
++--source include/have_debug_sync.inc
++--source include/have_binlog_format_statement.inc
++
++call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes");
++
++--let $rpl_connection_name=slave_lock
++--let $rpl_server_number=2
++--source include/rpl_connect.inc
++
++--let $rpl_connection_name=slave_nolock
++--let $rpl_server_number=2
++--source include/rpl_connect.inc
++
++--let $show_statement= SHOW PROCESSLIST
++--let $field= Info
++
++connection master;
++--echo [master]
++--disable_warnings
++DROP TABLE IF EXISTS t;
++--enable_warnings
++CREATE TABLE t(id INT);
++sync_slave_with_master;
++
++connection slave;
++--echo [slave]
++SET DEBUG_SYNC='RESET';
++SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status";
++
++connection master;
++--echo [master]
++INSERT INTO t VALUES(0);
++
++connection slave;
++--echo [slave]
++--let $condition= 'INSERT INTO t VALUES(0)'
++--source include/wait_show_condition.inc
++
++--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine
++--source include/percona_show_slave_status_nolock.inc
++
++connection master;
++--echo [master]
++INSERT INTO t VALUES(1);
++
++connection slave;
++--echo [slave]
++--let $condition= 'INSERT INTO t VALUES(1)'
++--source include/wait_show_condition.inc
++
++--let $rpl_connection_name=slave_stop
++--let $rpl_server_number=2
++--source include/rpl_connect.inc
++
++connection slave_stop;
++--echo [slave_stop]
++send STOP SLAVE;
++
++connection slave;
++--echo [slave]
++--let $condition= 'STOP SLAVE'
++--source include/wait_show_condition.inc
++
++--echo check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine
++--source include/percona_show_slave_status_nolock.inc
++
++
++connection slave_stop;
++--echo [slave_stop]
++reap;
++--source include/wait_for_slave_to_stop.inc
++START SLAVE;
++--source include/wait_for_slave_to_start.inc
++
++connection master;
++--echo [master]
++SET DEBUG_SYNC='RESET';
++
++connection slave;
++--echo [slave]
++SET GLOBAL DEBUG='';
++SET DEBUG_SYNC='RESET';
++
++connection master;
++--echo [master]
++DROP TABLE t;
++sync_slave_with_master;
++
++--source include/rpl_end.inc
+--- /dev/null
+++ b/mysql-test/r/percona_show_slave_status_nolock.result
-@@ -0,0 +1,21 @@
+@@ -0,0 +1,69 @@
+include/master-slave.inc
+[connection master]
++call mtr.add_suppression("Slave SQL: Request to stop slave SQL Thread received while applying a group that has non-transactional changes");
++include/rpl_connect.inc [creating slave_lock]
++include/rpl_connect.inc [creating slave_nolock]
++[master]
+DROP TABLE IF EXISTS t;
+CREATE TABLE t(id INT);
-+INSERT INTO t SELECT SLEEP(10);
++[slave]
++SET DEBUG_SYNC='RESET';
++SET GLOBAL DEBUG="+d,after_mysql_insert,after_show_slave_status";
++[master]
++INSERT INTO t VALUES(0);
++[slave]
++check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - both should work fine
++
++[slave_lock]
++SHOW SLAVE STATUS;
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++SIGNAL after SHOW SLAVE STATUS is 'signal.after_show_slave_status'
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
++[slave_nolock]
++SHOW SLAVE STATUS NOLOCK;
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++# should be 'signal.after_show_slave_status'
++SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status'
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.continue';
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
++
++[master]
++INSERT INTO t VALUES(1);
++[slave]
++include/rpl_connect.inc [creating slave_stop]
++[slave_stop]
+STOP SLAVE;
-+Warnings:
-+Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave.
-+master count(*)
-+master 1
-+slave count(*)
-+slave 0
++[slave]
++check 'SHOW SLAVE STATUS' and 'SHOW SLAVE STATUS NOLOCK' - just NOLOCK version should works fine
++
++[slave_lock]
++SHOW SLAVE STATUS;
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++SIGNAL after SHOW SLAVE STATUS is 'signal.empty'
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
++[slave_nolock]
+SHOW SLAVE STATUS NOLOCK;
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++# should be 'signal.after_show_slave_status'
++SIGNAL after SHOW SLAVE STATUS NOLOCK is 'signal.after_show_slave_status'
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.continue';
++[slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
++
++[slave_stop]
+include/wait_for_slave_to_stop.inc
+START SLAVE;
+include/wait_for_slave_to_start.inc
-+slave count(*)
-+slave 1
++[master]
++SET DEBUG_SYNC='RESET';
++[slave]
++SET GLOBAL DEBUG='';
++SET DEBUG_SYNC='RESET';
++[master]
+DROP TABLE t;
-+STOP SLAVE;
-+include/wait_for_slave_to_stop.inc
++include/rpl_end.inc
--- /dev/null
-+++ b/mysql-test/t/percona_show_slave_status_nolock.test
-@@ -0,0 +1,53 @@
-+--source include/master-slave.inc
-+--source include/have_binlog_format_statement.inc
-+--disable_query_log
-+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it uses a system function that may return a different value on the slave. Statement:");
-+call mtr.add_suppression("Slave SQL.*Request to stop slave SQL Thread received while applying a group that has non-transactional changes; waiting for completion of the group");
-+--enable_query_log
-+connection master;
-+ --disable_warnings
-+ DROP TABLE IF EXISTS t;
-+ --enable_warnings
-+ CREATE TABLE t(id INT);
-+ sync_slave_with_master;
++++ b/mysql-test/include/percona_show_slave_status_nolock.inc
+@@ -0,0 +1,56 @@
++--echo
++--disable_result_log
++connection slave_lock;
++--echo [slave_lock]
++send SHOW SLAVE STATUS;
+
-+connection master;
-+ send INSERT INTO t SELECT SLEEP(10);
++connection slave;
++--let $condition= 'SHOW SLAVE STATUS'
++--source include/wait_show_condition.inc
++
++--disable_warnings
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++--enable_warnings
++
++--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'`
++--echo SIGNAL after SHOW SLAVE STATUS is $current
+
+connection slave;
-+ sleep 15;
-+ send STOP SLAVE;
++--echo [slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
+
-+connection master;
-+ reap;
++connection slave_nolock;
++--echo [slave_nolock]
++send SHOW SLAVE STATUS NOLOCK;
+
-+ --disable_query_log
-+ select "master",count(*) from t;
-+ --enable_query_log
++connection slave;
++--let $condition= 'SHOW SLAVE STATUS NOLOCK'
++--source include/wait_show_condition.inc
+
-+connection slave1;
-+ --disable_query_log
-+ select "slave",count(*) from t;
-+ --enable_query_log
++--disable_warnings
++SET DEBUG_SYNC='now WAIT_FOR signal.after_show_slave_status TIMEOUT 1';
++--enable_warnings
+
-+ --disable_result_log
-+ SHOW SLAVE STATUS NOLOCK;
-+ --enable_result_log
++--echo # should be 'signal.after_show_slave_status'
++--let current=`SELECT SUBSTR(Variable_value FROM 22) FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE Variable_name = 'DEBUG_SYNC'`
++--echo SIGNAL after SHOW SLAVE STATUS NOLOCK is $current
+
+connection slave;
-+ reap;
++--echo [slave]
++SET DEBUG_SYNC='now SIGNAL signal.continue';
+
-+ --source include/wait_for_slave_to_stop.inc
-+ START SLAVE;
-+ --source include/wait_for_slave_to_start.inc
++connection slave_lock;
++--disable_result_log
++reap;
++--enable_result_log
+
-+ --disable_query_log
-+ select "slave",count(*) from t;
-+ --enable_query_log
++connection slave_nolock;
++--disable_result_log
++reap;
++--enable_result_log
+
-+connection master;
-+ DROP TABLE t;
-+sync_slave_with_master;
-+STOP SLAVE;
-+--source include/wait_for_slave_to_stop.inc
-+
-\ No newline at end of file
++connection slave;
++--echo [slave]
++SET DEBUG_SYNC='now SIGNAL signal.empty';
++--enable_result_log
++--echo
+--- a/sql/slave.cc
++++ b/sql/slave.cc
+@@ -1816,6 +1816,7 @@
+
+ if (mi->host[0])
+ {
++ bool do_lock=SQLCOM_SHOW_SLAVE_NOLOCK_STAT != thd->lex->sql_command;
+ DBUG_PRINT("info",("host is set: '%s'", mi->host));
+ String *packet= &thd->packet;
+ protocol->prepare_for_resend();
+@@ -1824,9 +1825,15 @@
+ slave_running can be accessed without run_lock but not other
+ non-volotile members like mi->io_thd, which is guarded by the mutex.
+ */
+- mysql_mutex_lock(&mi->run_lock);
++ if (do_lock)
++ {
++ mysql_mutex_lock(&mi->run_lock);
++ }
+ protocol->store(mi->io_thd ? mi->io_thd->proc_info : "", &my_charset_bin);
+- mysql_mutex_unlock(&mi->run_lock);
++ if (do_lock)
++ {
++ mysql_mutex_unlock(&mi->run_lock);
++ }
+
+ mysql_mutex_lock(&mi->data_lock);
+ mysql_mutex_lock(&mi->rli.data_lock);