diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2019-02-05 15:41:53 +0200 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2019-03-28 08:43:44 +0200 |
commit | 81d71ee6b21870772c336bff15b71904914f146a (patch) | |
tree | 72bb4aeb8a81ad04047a48102d3756a010b43eb5 | |
parent | 21b2fada7ab7f35c898c02d2f918461409cc9c8e (diff) | |
download | mariadb-git-81d71ee6b21870772c336bff15b71904914f146a.tar.gz |
MDEV-12009: Allow to force kill user threads/query which are flagged as high priority by Galera
As noted on kill_one_thread SUPER should be able to kill even
system threads i.e. threads/query flagged as high priority or
wsrep applier thread. Normal user, should not able to kill
threads/query flagged as high priority (BF) or wsrep applier
thread.
-rw-r--r-- | include/mysql/service_wsrep.h | 3 | ||||
-rw-r--r-- | mysql-test/suite/galera/r/galera_kill_applier.result | 4 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_kill_applier.cnf | 10 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_kill_applier.test | 54 | ||||
-rw-r--r-- | sql/sql_parse.cc | 14 | ||||
-rw-r--r-- | sql/sql_plugin_services.ic | 3 | ||||
-rw-r--r-- | sql/wsrep_dummy.cc | 3 | ||||
-rw-r--r-- | sql/wsrep_mysqld.cc | 1 | ||||
-rw-r--r-- | sql/wsrep_thd.cc | 9 | ||||
-rw-r--r-- | sql/wsrep_thd.h | 2 |
10 files changed, 95 insertions, 8 deletions
diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h index 267c8cb4e90..59df7a8b561 100644 --- a/include/mysql/service_wsrep.h +++ b/include/mysql/service_wsrep.h @@ -112,6 +112,7 @@ extern struct wsrep_service_st { int (*wsrep_trx_order_before_func)(MYSQL_THD, MYSQL_THD); void (*wsrep_unlock_rollback_func)(); void (*wsrep_set_data_home_dir_func)(const char *data_dir); + my_bool (*wsrep_thd_is_applier_func)(THD *thd); } *wsrep_service; #ifdef MYSQL_DYNAMIC_PLUGIN @@ -155,6 +156,7 @@ extern struct wsrep_service_st { #define wsrep_trx_order_before(T1,T2) wsrep_service->wsrep_trx_order_before_func(T1,T2) #define wsrep_unlock_rollback() wsrep_service->wsrep_unlock_rollback_func() #define wsrep_set_data_home_dir(A) wsrep_service->wsrep_set_data_home_dir_func(A) +#define wsrep_thd_is_applier(T) wsrep_service->wsrep_thd_is_applier_func(T) #define wsrep_debug get_wsrep_debug() #define wsrep_log_conflicts get_wsrep_log_conflicts() @@ -214,6 +216,7 @@ void wsrep_thd_set_conflict_state(THD *thd, enum wsrep_conflict_state state); bool wsrep_thd_ignore_table(THD *thd); void wsrep_unlock_rollback(); void wsrep_set_data_home_dir(const char *data_dir); +my_bool wsrep_thd_is_applier(THD *thd); #endif diff --git a/mysql-test/suite/galera/r/galera_kill_applier.result b/mysql-test/suite/galera/r/galera_kill_applier.result index fe4911639ed..89f8ead0b65 100644 --- a/mysql-test/suite/galera/r/galera_kill_applier.result +++ b/mysql-test/suite/galera/r/galera_kill_applier.result @@ -1,4 +1,8 @@ +CREATE USER foo@localhost; +GRANT SELECT on test.* TO foo@localhost; +# Open connection to the 1st node using 'test_user1' user. Got one of the listed errors Got one of the listed errors Got one of the listed errors Got one of the listed errors +DROP USER foo@localhost; diff --git a/mysql-test/suite/galera/t/galera_kill_applier.cnf b/mysql-test/suite/galera/t/galera_kill_applier.cnf new file mode 100644 index 00000000000..f2563e66f2e --- /dev/null +++ b/mysql-test/suite/galera/t/galera_kill_applier.cnf @@ -0,0 +1,10 @@ +!include ../galera_2nodes.cnf + +[mysqld.1] +wsrep_provider_options='base_port=@mysqld.1.#galera_port;pc.ignore_sb=true' +auto_increment_offset=1 + +[mysqld.2] +wsrep_provider_options='base_port=@mysqld.2.#galera_port;pc.ignore_sb=true' +auto_increment_offset=2 + diff --git a/mysql-test/suite/galera/t/galera_kill_applier.test b/mysql-test/suite/galera/t/galera_kill_applier.test index e14a8b9af23..5e4a587fe57 100644 --- a/mysql-test/suite/galera/t/galera_kill_applier.test +++ b/mysql-test/suite/galera/t/galera_kill_applier.test @@ -1,14 +1,25 @@ # # This test checks that applier threads are immune to KILL QUERY and KILL STATEMENT +# when USER is not SUPER # --source include/galera_cluster.inc ---source include/have_innodb.inc --connection node_1 +CREATE USER foo@localhost; +GRANT SELECT on test.* TO foo@localhost; + --let $applier_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE != 'wsrep aborter idle' OR STATE IS NULL LIMIT 1` +--let $aborter_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE = 'wsrep aborter idle' LIMIT 1` + +--echo # Open connection to the 1st node using 'test_user1' user. +--let $port_1= \$NODE_MYPORT_1 +--connect(foo_node_1,localhost,foo,,test,$port_1,) + +--connection foo_node_1 + --disable_query_log --error ER_KILL_DENIED_ERROR,ER_KILL_DENIED_ERROR --eval KILL $applier_thread @@ -16,11 +27,48 @@ --error ER_KILL_DENIED_ERROR,ER_KILL_DENIED_ERROR --eval KILL QUERY $applier_thread ---let $aborter_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE = 'wsrep aborter idle' LIMIT 1` - --error ER_KILL_DENIED_ERROR,ER_KILL_DENIED_ERROR --eval KILL $aborter_thread --error ER_KILL_DENIED_ERROR,ER_KILL_DENIED_ERROR --eval KILL QUERY $aborter_thread --enable_query_log + +# +# SUPER can kill applier threads +# +--connection node_2 + +--let $applier_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE != 'wsrep aborter idle' OR STATE IS NULL LIMIT 1` + +--disable_query_log +--eval KILL $applier_thread +--enable_query_log + +--let $aborter_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE = 'wsrep aborter idle' LIMIT 1` + +--disable_query_log +--eval KILL $aborter_thread +--enable_query_log + +--source include/restart_mysqld.inc + +--connection node_2 +--let $applier_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE != 'wsrep aborter idle' OR STATE IS NULL LIMIT 1` + +--disable_query_log +--eval KILL QUERY $applier_thread +--enable_query_log + +--let $aborter_thread = `SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE = 'wsrep aborter idle' LIMIT 1` + +--disable_query_log +--eval KILL QUERY $aborter_thread +--enable_query_log + +--source include/restart_mysqld.inc + +--connection node_1 +--disconnect foo_node_1 +DROP USER foo@localhost; + diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1f060305d4f..920f7ac0329 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8292,11 +8292,19 @@ kill_one_thread(THD *thd, longlong id, killed_state kill_signal, killed_type typ It's ok to also kill DELAYED threads with KILL_CONNECTION instead of KILL_SYSTEM_THREAD; The difference is that KILL_CONNECTION may be faster and do a harder kill than KILL_SYSTEM_THREAD; + + Note that if thread is wsrep Brute Force or applier thread we + allow killing it only when we're SUPER. */ - if (((thd->security_ctx->master_access & SUPER_ACL) || - thd->security_ctx->user_matches(tmp->security_ctx)) && - !wsrep_thd_is_BF(tmp, false)) + if ((thd->security_ctx->master_access & SUPER_ACL) || + (thd->security_ctx->user_matches(tmp->security_ctx) +#ifdef WITH_WSREP + && + !tmp->wsrep_applier && + !wsrep_thd_is_BF(tmp, false) +#endif + )) { tmp->awake(kill_signal); error=0; diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic index 427d8937c57..d70c76701fd 100644 --- a/sql/sql_plugin_services.ic +++ b/sql/sql_plugin_services.ic @@ -181,7 +181,8 @@ static struct wsrep_service_st wsrep_handler = { wsrep_trx_is_aborting, wsrep_trx_order_before, wsrep_unlock_rollback, - wsrep_set_data_home_dir + wsrep_set_data_home_dir, + wsrep_thd_is_applier, }; static struct thd_specifics_service_st thd_specifics_handler= diff --git a/sql/wsrep_dummy.cc b/sql/wsrep_dummy.cc index 795e2d19252..e2a4dcf3bad 100644 --- a/sql/wsrep_dummy.cc +++ b/sql/wsrep_dummy.cc @@ -20,6 +20,9 @@ my_bool wsrep_thd_is_BF(THD *, my_bool) { return 0; } +my_bool wsrep_thd_is_applier(THD *) +{ return 0; } + int wsrep_trx_order_before(THD *, THD *) { return 0; } diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index ee8509e3fa2..82415691b3f 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -2470,7 +2470,6 @@ extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode) thd->wsrep_exec_mode= mode; } - extern "C" void wsrep_thd_set_query_state( THD *thd, enum wsrep_query_state state) { diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 551e710cfeb..91f0e1e8d8a 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -596,6 +596,15 @@ my_bool wsrep_thd_is_BF(THD *thd, my_bool sync) return status; } +my_bool wsrep_thd_is_applier(THD *thd) +{ + my_bool ret = FALSE; + if (thd) { + ret = thd->wsrep_applier; + } + return ret; +} + extern "C" my_bool wsrep_thd_is_BF_or_commit(void *thd_ptr, my_bool sync) { diff --git a/sql/wsrep_thd.h b/sql/wsrep_thd.h index 5900668f3fb..f5fcb50280c 100644 --- a/sql/wsrep_thd.h +++ b/sql/wsrep_thd.h @@ -37,6 +37,7 @@ int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, */ extern void wsrep_thd_set_PA_safe(void *thd_ptr, my_bool safe); extern my_bool wsrep_thd_is_BF(THD *thd, my_bool sync); +extern my_bool wsrep_thd_is_applier(THD *thd); extern my_bool wsrep_thd_is_wsrep(void *thd_ptr); enum wsrep_conflict_state wsrep_thd_conflict_state(void *thd_ptr, my_bool sync); @@ -47,6 +48,7 @@ extern "C" int wsrep_thd_in_locking_session(void *thd_ptr); #else /* WITH_WSREP */ #define wsrep_thd_is_BF(T, S) (0) +#define wsrep_thd_is_applier(T) (0) #define wsrep_abort_thd(X,Y,Z) do { } while(0) #define wsrep_create_appliers(T) do { } while(0) |