revision-id: 100fd3e4c66a6e066e1ba5e2b1dafccbee301c2e (mariadb-10.1.37-80-g100fd3e4c66) parent(s): 27f1de5cb3ededcea5a54d43047b5c38c2965075 author: Jan Lindström committer: Jan Lindström timestamp: 2019-01-31 09:45:32 +0200 message: 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. --- .../galera/r/galera_ist_mysqldump,debug.rdiff | 19 ++------ .../suite/galera/r/galera_kill_applier.result | 4 ++ mysql-test/suite/galera/t/galera_kill_applier.test | 56 ++++++++++++++++++++-- sql/sql_parse.cc | 14 ++++-- 4 files changed, 72 insertions(+), 21 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_ist_mysqldump,debug.rdiff b/mysql-test/suite/galera/r/galera_ist_mysqldump,debug.rdiff index 141b1ebd25f..c168a8abdd1 100644 --- a/mysql-test/suite/galera/r/galera_ist_mysqldump,debug.rdiff +++ b/mysql-test/suite/galera/r/galera_ist_mysqldump,debug.rdiff @@ -1,12 +1,11 @@ ---- r/galera_ist_mysqldump.result 2018-11-22 14:25:28.551554055 +0200 -+++ r/galera_ist_mysqldump.reject 2018-11-22 15:46:33.119441931 +0200 -@@ -200,6 +200,114 @@ +--- r/galera_ist_mysqldump.result 2018-11-19 14:10:26.307031336 +0200 ++++ r/galera_ist_mysqldump.reject 2019-01-30 11:57:13.199102357 +0200 +@@ -180,6 +180,103 @@ DROP TABLE t1; COMMIT; SET AUTOCOMMIT=ON; +Performing State Transfer on a server that has been killed and restarted +while a DDL was in progress on it -+connection node_1; +CREATE TABLE t1 (f1 CHAR(255)) ENGINE=InnoDB; +SET AUTOCOMMIT=OFF; +START TRANSACTION; @@ -15,7 +14,6 @@ +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); +INSERT INTO t1 VALUES ('node1_committed_before'); -+connection node_2; +START TRANSACTION; +INSERT INTO t1 VALUES ('node2_committed_before'); +INSERT INTO t1 VALUES ('node2_committed_before'); @@ -24,12 +22,9 @@ +INSERT INTO t1 VALUES ('node2_committed_before'); +COMMIT; +SET GLOBAL debug_dbug = 'd,sync.alter_opened_table'; -+connection node_1; +ALTER TABLE t1 ADD COLUMN f2 INTEGER; -+connection node_2; +SET wsrep_sync_wait = 0; +Killing server ... -+connection node_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_committed_during'); @@ -44,7 +39,6 @@ +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); -+connect node_1a_galera_st_kill_slave_ddl, 127.0.0.1, root, , test, $NODE_MYPORT_1; +SET AUTOCOMMIT=OFF; +START TRANSACTION; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); @@ -52,9 +46,7 @@ +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); -+connection node_2; +Performing --wsrep-recover ... -+connection node_2; +Starting server ... +Using --wsrep-start-position when starting mysqld ... +SET AUTOCOMMIT=OFF; @@ -65,7 +57,6 @@ +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +INSERT INTO t1 (f1) VALUES ('node2_committed_after'); +COMMIT; -+connection node_1; +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_committed_after'); @@ -80,7 +71,6 @@ +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +INSERT INTO t1 (f1) VALUES ('node1_committed_after'); +COMMIT; -+connection node_1a_galera_st_kill_slave_ddl; +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); +INSERT INTO t1 (f1) VALUES ('node1_to_be_rollbacked_after'); @@ -98,7 +88,6 @@ +1 +COMMIT; +SET AUTOCOMMIT=ON; -+connection node_1; +SELECT COUNT(*) = 2 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 't1'; +COUNT(*) = 2 +1 @@ -112,6 +101,6 @@ +COMMIT; +SET AUTOCOMMIT=ON; +SET GLOBAL debug_dbug = $debug_orig; - connection node_1; CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); DROP USER sst; + CALL mtr.add_suppression("Slave SQL: Error 'The MySQL server is running with the --skip-grant-tables option so it cannot execute this statement' on query"); 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.test b/mysql-test/suite/galera/t/galera_kill_applier.test index e14a8b9af23..48a411d2cf2 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,50 @@ --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 + +--disable_query_log +--eval KILL $applier_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 $aborter_thread +--enable_query_log + +--source include/restart_mysqld.inc + +--connection node_2 + +--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 3f6ce8356ce..83278559a9c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -8297,11 +8297,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;