Skip to content

Commit

Permalink
MDEV-22458: Server with WSREP hangs after INSERT, wrong usage of mute…
Browse files Browse the repository at this point in the history
…x 'LOCK_thd_data' and 'share->intern_lock' / 'lock->mutex'

Add `find_thread_by_id_with_thd_data_lock` which will be used only when killing thread.
This version needs to take `thd->LOCK_thd_data` lock.
  • Loading branch information
mkaruza authored and Jan Lindström committed Jul 24, 2020
1 parent 6b8b7b1 commit 4b4372a
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 2 deletions.
10 changes: 10 additions & 0 deletions mysql-test/suite/galera/r/MDEV-22458.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
connection node_2;
connection node_1;
CREATE TABLE t1 (a INT);
connect con1,localhost,root,,test;
INSERT INTO t1 VALUES (1),(2),(3),(4);
SHOW EXPLAIN FOR $con1;
ERROR HY000: Target is not running an EXPLAINable command
connection con1;
INSERT INTO t1 VALUES (5),(6),(7),(8);
DROP TABLE t1;
21 changes: 21 additions & 0 deletions mysql-test/suite/galera/t/MDEV-22458.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# MDEV-22458
#
# When running SHOW command, thread lock `LOCK_thd_data` should not be taken.
# Lock will be taken only when we are killing thread
#

--source include/galera_cluster.inc
CREATE TABLE t1 (a INT);

--connect (con1,localhost,root,,test)
--let $con1 = `SELECT CONNECTION_ID()`

INSERT INTO t1 VALUES (1),(2),(3),(4);

--error ER_TARGET_NOT_EXPLAINABLE
EVALP SHOW EXPLAIN FOR $con1;

--connection con1
INSERT INTO t1 VALUES (5),(6),(7),(8);

DROP TABLE t1;
28 changes: 26 additions & 2 deletions sql/sql_parse.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9019,7 +9019,6 @@ my_bool find_thread_callback(THD *thd, find_thread_callback_arg *arg)
if (thd->get_command() != COM_DAEMON &&
arg->id == (arg->query_id ? thd->query_id : (longlong) thd->thread_id))
{
if (WSREP(thd)) mysql_mutex_lock(&thd->LOCK_thd_data);
mysql_mutex_lock(&thd->LOCK_thd_kill); // Lock from delete
arg->thd= thd;
return 1;
Expand All @@ -9035,6 +9034,26 @@ THD *find_thread_by_id(longlong id, bool query_id)
return arg.thd;
}

#ifdef WITH_WSREP
my_bool find_thread_with_thd_data_lock_callback(THD *thd, find_thread_callback_arg *arg)
{
if (thd->get_command() != COM_DAEMON &&
arg->id == (arg->query_id ? thd->query_id : (longlong) thd->thread_id))
{
if (WSREP(thd)) mysql_mutex_lock(&thd->LOCK_thd_data);
mysql_mutex_lock(&thd->LOCK_thd_kill); // Lock from delete
arg->thd= thd;
return 1;
}
return 0;
}
THD *find_thread_by_id_with_thd_data_lock(longlong id, bool query_id)
{
find_thread_callback_arg arg(id, query_id);
server_threads.iterate(find_thread_with_thd_data_lock_callback, &arg);
return arg.thd;
}
#endif

/**
kill one thread.
Expand All @@ -9052,7 +9071,11 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
uint error= (type == KILL_TYPE_QUERY ? ER_NO_SUCH_QUERY : ER_NO_SUCH_THREAD);
DBUG_ENTER("kill_one_thread");
DBUG_PRINT("enter", ("id: %lld signal: %u", id, (uint) kill_signal));
#ifdef WITH_WSREP
if (id && (tmp= find_thread_by_id_with_thd_data_lock(id, type == KILL_TYPE_QUERY)))
#else
if (id && (tmp= find_thread_by_id(id, type == KILL_TYPE_QUERY)))
#endif
{
/*
If we're SUPER, we can KILL anything, including system-threads.
Expand Down Expand Up @@ -9106,8 +9129,9 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ
else
error= (type == KILL_TYPE_QUERY ? ER_KILL_QUERY_DENIED_ERROR :
ER_KILL_DENIED_ERROR);

#ifdef WITH_WSREP
if (WSREP(tmp)) mysql_mutex_unlock(&tmp->LOCK_thd_data);
#endif
mysql_mutex_unlock(&tmp->LOCK_thd_kill);
}
DBUG_PRINT("exit", ("%d", error));
Expand Down

0 comments on commit 4b4372a

Please sign in to comment.