diff options
57 files changed, 1780 insertions, 255 deletions
diff --git a/.gitignore b/.gitignore index 2ed53e5365d..2c7e5c890ae 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,7 @@ mysql-test/mtr mysql-test/mysql-test-run mysql-test/var/ mysys/thr_lock +mysys/thr_timer packaging/rpm-oel/mysql.spec packaging/rpm-uln/mysql.10.0.11.spec packaging/solaris/postinstall-solaris diff --git a/include/thr_timer.h b/include/thr_timer.h new file mode 100644 index 00000000000..892bbc1a01f --- /dev/null +++ b/include/thr_timer.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2012 Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 or later of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/* Prototypes when using thr_timer functions */ + +#ifndef _thr_timer_h +#define _thr_timer_h +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct st_timer { + struct timespec expire_time; + my_bool expired; + uint index_in_queue; + void (*func)(void*); + void *func_arg; +} thr_timer_t; + +/* Main functions for library */ +my_bool init_thr_timer(uint init_size_for_timer_queue); +void end_thr_timer(); + +/* Functions for handling one timer */ +void thr_timer_init(thr_timer_t *timer_data, void(*function)(void*), + void *arg); +my_bool thr_timer_settime(thr_timer_t *timer_data, ulonglong microseconds); +void thr_timer_end(thr_timer_t *timer_data); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* _thr_timer_h */ diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 25fe976b7ed..6c769e60780 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -58,6 +58,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA' @@ -85,7 +86,7 @@ delete from mysql.user where user='mysqltest_1'; flush privileges; delete from mysql.user where user='mysqltest_1'; flush privileges; -grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10; +grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10 max_statement_time 60; select * from mysql.user where user="mysqltest_1"; Host localhost User mysqltest_1 @@ -132,10 +133,11 @@ authentication_string password_expired N is_role N default_role +max_statement_time 60.000000 show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost -GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 -grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30; +GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_STATEMENT_TIME 60.000000 +grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30 max_statement_time 0; select * from mysql.user where user="mysqltest_1"; Host localhost User mysqltest_1 @@ -182,6 +184,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' WITH MAX_QUERIES_PER_HOUR 10 MAX_UPDATES_PER_HOUR 20 MAX_CONNECTIONS_PER_HOUR 30 diff --git a/mysql-test/r/max_statement_time.result b/mysql-test/r/max_statement_time.result new file mode 100644 index 00000000000..2681575daea --- /dev/null +++ b/mysql-test/r/max_statement_time.result @@ -0,0 +1,147 @@ + +# Test the MAX_STATEMENT_TIME option. + +SET @@MAX_STATEMENT_TIME=2; +select @@max_statement_time; +@@max_statement_time +2.000000 +SELECT SLEEP(1); +SLEEP(1) +0 +SELECT SLEEP(3); +SLEEP(3) +1 +SET @@MAX_STATEMENT_TIME=0; +SELECT SLEEP(1); +SLEEP(1) +0 +SHOW STATUS LIKE "max_statement_time_exceeded"; +Variable_name Value +Max_statement_time_exceeded 1 +CREATE TABLE t1 (a INT, b VARCHAR(300)) engine=myisam; +INSERT INTO t1 VALUES (1, 'string'); +SELECT 0; +0 +0 + +# Test the MAX_STATEMENT_TIME option with SF (should have no effect). + +CREATE PROCEDURE p1() +BEGIN +declare tmp int; +SET @@MAX_STATEMENT_TIME=0.0001; +SELECT COUNT(*) INTO tmp FROM t1 WHERE b LIKE '%z%'; +SET @@MAX_STATEMENT_TIME=0; +END| +CREATE PROCEDURE p2() +BEGIN +SET @@MAX_STATEMENT_TIME=5; +END| +SELECT @@MAX_STATEMENT_TIME; +@@MAX_STATEMENT_TIME +0.000000 +CALL p1(); +CALL p2(); +SELECT @@MAX_STATEMENT_TIME; +@@MAX_STATEMENT_TIME +5.000000 +SET @@MAX_STATEMENT_TIME=0; +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP TABLE t1; + +# MAX_STATEMENT_TIME account resource + +GRANT USAGE ON *.* TO user1@localhost WITH MAX_STATEMENT_TIME 1.005; +# con1 +SELECT @@max_statement_time; +@@max_statement_time +1.005000 +# restart and reconnect +set @global.userstat=1; +SELECT @@global.max_statement_time,@@session.max_statement_time; +@@global.max_statement_time @@session.max_statement_time +0.000000 1.005000 +select sleep(100); +sleep(100) +1 +SHOW STATUS LIKE "max_statement_time_exceeded"; +Variable_name Value +Max_statement_time_exceeded 1 +show grants for user1@localhost; +Grants for user1@localhost +GRANT USAGE ON *.* TO 'user1'@'localhost' WITH MAX_STATEMENT_TIME 1.005000 +set @global.userstat=0; +DROP USER user1@localhost; + +# MAX_STATEMENT_TIME status variables. + +flush status; +SET @@max_statement_time=0; +SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_exceeded +FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME = 'max_statement_time_exceeded'; +SET @@max_statement_time=0.5; +SELECT SLEEP(2); +SLEEP(2) +1 +SHOW STATUS LIKE '%timeout%'; +Variable_name Value +Ssl_default_timeout 0 +Ssl_session_cache_timeouts 0 +SET @@max_statement_time=0; +# Ensure that the counters for: +# - statements that exceeded their maximum execution time +# are incremented. +SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS +WHERE VARIABLE_NAME = 'max_statement_time_exceeded' + AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_exceeded; +STATUS +1 + +# Check that the appropriate error status is set. + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +START TRANSACTION; +SELECT * FROM t1 FOR UPDATE; +a +1 +SET @@SESSION.max_statement_time = 0.5; +UPDATE t1 SET a = 2; +ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +SHOW WARNINGS; +Level Code Message +Error 1967 Query execution was interrupted (max_statement_time exceeded) +ROLLBACK; +DROP TABLE t1; + +# Test interaction with lock waits. + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); +SET @@SESSION.max_statement_time= 0.5; +LOCK TABLES t1 WRITE; +SELECT @@SESSION.max_statement_time; +@@SESSION.max_statement_time +0.500000 +LOCK TABLES t1 READ; +ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +UNLOCK TABLES; +BEGIN; +SELECT * FROM t1; +a +1 +ALTER TABLE t1 ADD COLUMN b INT; +ERROR 70100: Query execution was interrupted (max_statement_time exceeded) +ROLLBACK; +SELECT GET_LOCK('lock', 1); +GET_LOCK('lock', 1) +1 +SELECT GET_LOCK('lock', 1); +GET_LOCK('lock', 1) +NULL +SELECT RELEASE_LOCK('lock'); +RELEASE_LOCK('lock') +1 +DROP TABLE t1; diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 5a2142c402c..80ba45be72a 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -422,6 +422,11 @@ The following options may be given as the first argument: value are used; the rest are ignored) --max-sp-recursion-depth[=#] Maximum stored procedure recursion depth + --max-statement-time=# + A SELECT query that have taken more than + max_statement_time seconds will be aborted. The argument + will be treated as a decimal value with microsecond + precision. A value of 0 (default) means no timeout --max-tmp-tables=# Maximum number of temporary tables a client can keep open at a time --max-user-connections=# @@ -1196,6 +1201,7 @@ max-relay-log-size 1073741824 max-seeks-for-key 18446744073709551615 max-sort-length 1024 max-sp-recursion-depth 0 +max-statement-time 0 max-tmp-tables 32 max-user-connections 0 max-write-lock-count 18446744073709551615 diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 7db51eadbe6..e30fa9a1966 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1202,13 +1202,13 @@ SET @aux= "SELECT COUNT(*) prepare my_stmt from @aux; execute my_stmt; COUNT(*) -45 +46 execute my_stmt; COUNT(*) -45 +46 execute my_stmt; COUNT(*) -45 +46 deallocate prepare my_stmt; drop procedure if exists p1| drop table if exists t1| diff --git a/mysql-test/r/status_user.result b/mysql-test/r/status_user.result index 829c8abb634..766a00f6f78 100644 --- a/mysql-test/r/status_user.result +++ b/mysql-test/r/status_user.result @@ -25,6 +25,7 @@ DENIED_CONNECTIONS bigint(21) NO 0 LOST_CONNECTIONS bigint(21) NO 0 ACCESS_DENIED bigint(21) NO 0 EMPTY_QUERIES bigint(21) NO 0 +MAX_STATEMENT_TIME_EXCEEDED bigint(21) NO 0 show columns from information_schema.user_statistics; Field Type Null Key Default Extra USER varchar(128) NO @@ -50,6 +51,7 @@ DENIED_CONNECTIONS bigint(21) NO 0 LOST_CONNECTIONS bigint(21) NO 0 ACCESS_DENIED bigint(21) NO 0 EMPTY_QUERIES bigint(21) NO 0 +MAX_STATEMENT_TIME_EXCEEDED bigint(21) NO 0 show columns from information_schema.index_statistics; Field Type Null Key Default Extra TABLE_SCHEMA varchar(192) NO diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index 0204354d9e3..f195b0a607e 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -131,6 +131,7 @@ user CREATE TABLE `user` ( `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `max_statement_time` decimal(12,6) NOT NULL DEFAULT '0.000000', PRIMARY KEY (`Host`,`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges' show create table func; diff --git a/mysql-test/r/system_mysql_db_fix40123.result b/mysql-test/r/system_mysql_db_fix40123.result index 0204354d9e3..f195b0a607e 100644 --- a/mysql-test/r/system_mysql_db_fix40123.result +++ b/mysql-test/r/system_mysql_db_fix40123.result @@ -131,6 +131,7 @@ user CREATE TABLE `user` ( `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `max_statement_time` decimal(12,6) NOT NULL DEFAULT '0.000000', PRIMARY KEY (`Host`,`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges' show create table func; diff --git a/mysql-test/r/system_mysql_db_fix50030.result b/mysql-test/r/system_mysql_db_fix50030.result index 0204354d9e3..f195b0a607e 100644 --- a/mysql-test/r/system_mysql_db_fix50030.result +++ b/mysql-test/r/system_mysql_db_fix50030.result @@ -131,6 +131,7 @@ user CREATE TABLE `user` ( `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `max_statement_time` decimal(12,6) NOT NULL DEFAULT '0.000000', PRIMARY KEY (`Host`,`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges' show create table func; diff --git a/mysql-test/r/system_mysql_db_fix50117.result b/mysql-test/r/system_mysql_db_fix50117.result index 0204354d9e3..f195b0a607e 100644 --- a/mysql-test/r/system_mysql_db_fix50117.result +++ b/mysql-test/r/system_mysql_db_fix50117.result @@ -131,6 +131,7 @@ user CREATE TABLE `user` ( `password_expired` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `is_role` enum('N','Y') CHARACTER SET utf8 NOT NULL DEFAULT 'N', `default_role` char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + `max_statement_time` decimal(12,6) NOT NULL DEFAULT '0.000000', PRIMARY KEY (`Host`,`User`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges' show create table func; diff --git a/mysql-test/suite/funcs_1/r/is_columns_is.result b/mysql-test/suite/funcs_1/r/is_columns_is.result index 8f2f81a4616..c73eaa874c7 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is.result @@ -36,6 +36,7 @@ def information_schema CLIENT_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NUL def information_schema CLIENT_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema CLIENT_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema CLIENT_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select +def information_schema CLIENT_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 24 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema CLIENT_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema CLIENT_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema CLIENT_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select @@ -408,6 +409,7 @@ def information_schema USER_STATISTICS CPU_TIME 6 0 NO double NULL NULL 21 NULL def information_schema USER_STATISTICS DENIED_CONNECTIONS 20 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema USER_STATISTICS EMPTY_QUERIES 23 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema USER_STATISTICS LOST_CONNECTIONS 21 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select +def information_schema USER_STATISTICS MAX_STATEMENT_TIME_EXCEEDED 24 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema USER_STATISTICS OTHER_COMMANDS 17 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema USER_STATISTICS ROLLBACK_TRANSACTIONS 19 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema USER_STATISTICS ROWS_DELETED 12 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select @@ -533,6 +535,7 @@ NULL information_schema CLIENT_STATISTICS DENIED_CONNECTIONS bigint NULL NULL NU NULL information_schema CLIENT_STATISTICS LOST_CONNECTIONS bigint NULL NULL NULL NULL bigint(21) NULL information_schema CLIENT_STATISTICS ACCESS_DENIED bigint NULL NULL NULL NULL bigint(21) NULL information_schema CLIENT_STATISTICS EMPTY_QUERIES bigint NULL NULL NULL NULL bigint(21) +NULL information_schema CLIENT_STATISTICS MAX_STATEMENT_TIME_EXCEEDED bigint NULL NULL NULL NULL bigint(21) 3.0000 information_schema COLLATIONS COLLATION_NAME varchar 32 96 utf8 utf8_general_ci varchar(32) 3.0000 information_schema COLLATIONS CHARACTER_SET_NAME varchar 32 96 utf8 utf8_general_ci varchar(32) NULL information_schema COLLATIONS ID bigint NULL NULL NULL NULL bigint(11) @@ -906,6 +909,7 @@ NULL information_schema USER_STATISTICS DENIED_CONNECTIONS bigint NULL NULL NULL NULL information_schema USER_STATISTICS LOST_CONNECTIONS bigint NULL NULL NULL NULL bigint(21) NULL information_schema USER_STATISTICS ACCESS_DENIED bigint NULL NULL NULL NULL bigint(21) NULL information_schema USER_STATISTICS EMPTY_QUERIES bigint NULL NULL NULL NULL bigint(21) +NULL information_schema USER_STATISTICS MAX_STATEMENT_TIME_EXCEEDED bigint NULL NULL NULL NULL bigint(21) 3.0000 information_schema VIEWS TABLE_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512) 3.0000 information_schema VIEWS TABLE_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema VIEWS TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index d05c120bfa8..09adebfab1c 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -227,6 +227,7 @@ def mysql user is_role 44 N NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum def mysql user Lock_tables_priv 21 N NO enum 1 3 NULL NULL NULL utf8 utf8_general_ci enum('N','Y') select,insert,update,references def mysql user max_connections 39 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned select,insert,update,references def mysql user max_questions 37 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned select,insert,update,references +def mysql user max_statement_time 46 0.000000 NO decimal NULL NULL 12 6 NULL NULL NULL decimal(12,6) select,insert,update,references def mysql user max_updates 38 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) unsigned select,insert,update,references def mysql user max_user_connections 40 0 NO int NULL NULL 10 0 NULL NULL NULL int(11) select,insert,update,references def mysql user Password 3 NO char 41 41 NULL NULL NULL latin1 latin1_bin char(41) select,insert,update,references @@ -568,3 +569,4 @@ NULL mysql user max_user_connections int NULL NULL NULL NULL int(11) 3.0000 mysql user password_expired enum 1 3 utf8 utf8_general_ci enum('N','Y') 3.0000 mysql user is_role enum 1 3 utf8 utf8_general_ci enum('N','Y') 3.0000 mysql user default_role char 80 240 utf8 utf8_bin char(80) +NULL mysql user max_statement_time decimal NULL NULL NULL NULL decimal(12,6) diff --git a/mysql-test/suite/funcs_1/r/is_user_privileges.result b/mysql-test/suite/funcs_1/r/is_user_privileges.result index 5296a37c98d..dfbe50ad862 100644 --- a/mysql-test/suite/funcs_1/r/is_user_privileges.result +++ b/mysql-test/suite/funcs_1/r/is_user_privileges.result @@ -132,6 +132,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser2 Password @@ -177,6 +178,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser3 Password @@ -222,6 +224,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 # # Add GRANT OPTION db_datadict.* to testuser1; GRANT UPDATE ON db_datadict.* TO 'testuser1'@'localhost' WITH GRANT OPTION; @@ -291,6 +294,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser2 Password @@ -336,6 +340,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser3 Password @@ -381,6 +386,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 # Establish connection testuser1 (user=testuser1) SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' @@ -436,6 +442,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser2 Password @@ -481,6 +488,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser3 Password @@ -526,6 +534,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 SHOW GRANTS; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' @@ -603,6 +612,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser2 Password @@ -648,6 +658,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser3 Password @@ -693,6 +704,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION; # # Here <SELECT YES> is shown correctly for testuser1; @@ -762,6 +774,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser2 Password @@ -807,6 +820,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser3 Password @@ -852,6 +866,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 # Switch to connection testuser1 SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' @@ -907,6 +922,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser2 Password @@ -952,6 +968,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser3 Password @@ -997,6 +1014,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 SHOW GRANTS; Grants for testuser1@localhost GRANT SELECT ON *.* TO 'testuser1'@'localhost' WITH GRANT OPTION @@ -1104,6 +1122,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser2 Password @@ -1149,6 +1168,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser3 Password @@ -1194,6 +1214,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 # Switch to connection testuser1 SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' @@ -1296,6 +1317,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser2 Password @@ -1341,6 +1363,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser3 Password @@ -1386,6 +1409,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 # Switch to connection testuser1 SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' @@ -1441,6 +1465,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser2 Password @@ -1486,6 +1511,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser3 Password @@ -1531,6 +1557,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 SHOW GRANTS; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' @@ -1593,6 +1620,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser2 Password @@ -1638,6 +1666,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser3 Password @@ -1683,6 +1712,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 SHOW GRANTS; Grants for testuser1@localhost GRANT USAGE ON *.* TO 'testuser1'@'localhost' @@ -1760,6 +1790,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser2 Password @@ -1805,6 +1836,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 Host localhost User testuser3 Password @@ -1850,6 +1882,7 @@ authentication_string password_expired N is_role N default_role +max_statement_time 0.000000 # Switch to connection testuser1 SELECT * FROM information_schema.user_privileges WHERE grantee LIKE '''testuser%''' diff --git a/mysql-test/suite/perfschema/r/digest_table_full.result b/mysql-test/suite/perfschema/r/digest_table_full.result index 9c0efb7b1ca..4c7de82abc2 100644 --- a/mysql-test/suite/perfschema/r/digest_table_full.result +++ b/mysql-test/suite/perfschema/r/digest_table_full.result @@ -109,11 +109,11 @@ DROP TRIGGER trg; #################################### # QUERYING PS STATEMENT DIGEST #################################### -SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, +SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest; -SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS -NULL NULL NULL 55 32 1 2 -statements_digest 0e98ee6a98e296530ec59c12dbc08dfe TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1 0 0 0 +SCHEMA_NAME DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS +NULL NULL 55 32 1 2 +statements_digest TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1 0 0 0 SHOW VARIABLES LIKE "performance_schema_digests_size"; Variable_name Value performance_schema_digests_size 2 diff --git a/mysql-test/suite/perfschema/r/rpl_gtid_func.result b/mysql-test/suite/perfschema/r/rpl_gtid_func.result index 98342bc4869..86c8347addd 100644 --- a/mysql-test/suite/perfschema/r/rpl_gtid_func.result +++ b/mysql-test/suite/perfschema/r/rpl_gtid_func.result @@ -33,11 +33,11 @@ TABLE information_schema % NO NO TABLE master foo YES YES TABLE mysql % NO NO TABLE performance_schema % NO NO -select digest, digest_text, count_star +select digest_text, count_star from performance_schema.events_statements_summary_by_digest where digest_text like "%in_%_digest%"; -digest digest_text count_star -e315485f9cbc06befb4e59970905a034 SELECT ? AS in_master_digest 1 +digest_text count_star +SELECT ? AS in_master_digest 1 insert into test.marker values (2); **** On Slave **** select * from test.marker; @@ -60,11 +60,11 @@ TABLE information_schema % NO NO TABLE mysql % NO NO TABLE performance_schema % NO NO TABLE slave foo YES YES -select digest, digest_text, count_star +select digest_text, count_star from performance_schema.events_statements_summary_by_digest where digest_text like "%in_%_digest%"; -digest digest_text count_star -bd2f53b41efcd037df41a3dd8bf3312a SELECT ? AS in_slave_digest 1 +digest_text count_star +SELECT ? AS in_slave_digest 1 **** On Master **** delete from performance_schema.setup_objects where object_schema='master'; diff --git a/mysql-test/suite/perfschema/r/start_server_no_digests.result b/mysql-test/suite/perfschema/r/start_server_no_digests.result index 4f6fa9bc5da..e4b389716a9 100644 --- a/mysql-test/suite/perfschema/r/start_server_no_digests.result +++ b/mysql-test/suite/perfschema/r/start_server_no_digests.result @@ -109,9 +109,9 @@ DROP TRIGGER trg; #################################### # QUERYING PS STATEMENT DIGEST #################################### -SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, +SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest; -SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS +SCHEMA_NAME DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS SHOW VARIABLES LIKE "performance_schema_digests_size"; Variable_name Value performance_schema_digests_size 0 diff --git a/mysql-test/suite/perfschema/r/statement_digest.result b/mysql-test/suite/perfschema/r/statement_digest.result index 41cba435cb6..a7983e5baaa 100644 --- a/mysql-test/suite/perfschema/r/statement_digest.result +++ b/mysql-test/suite/perfschema/r/statement_digest.result @@ -109,46 +109,46 @@ DROP TRIGGER trg; #################################### # QUERYING PS STATEMENT DIGEST #################################### -SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, +SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest; -SCHEMA_NAME DIGEST DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS -statements_digest 0e98ee6a98e296530ec59c12dbc08dfe TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1 0 0 0 -statements_digest 954f43425c3234acc8e194afd97e8a0a SELECT ? FROM t1 1 0 0 0 -statements_digest fc365a54bc19d746bd24c27aba46b990 SELECT ? FROM `t1` 1 0 0 0 -statements_digest 27ba28f6252e4ae0e9b14b36da536fbe SELECT ?, ... FROM t1 2 0 0 0 -statements_digest 81d03922612900032ec4b81934ab4841 SELECT ? FROM t2 1 0 0 0 -statements_digest adce8aec12b6b5046cd4bf55951014c7 SELECT ?, ... FROM t2 2 0 0 0 -statements_digest 59a1bd93c424b10802fe66bb6dcd94d2 INSERT INTO t1 VALUES (?) 1 1 0 0 -statements_digest 91b2da58b0eb49c35a38fbc49f5e491d INSERT INTO t2 VALUES (?) 1 1 0 0 -statements_digest 967114adbf91d8a4a99ec5e49e909ff4 INSERT INTO t3 VALUES (...) 4 4 0 0 -statements_digest 8f25e7a48487e0aa7377e816816bb658 INSERT INTO t4 VALUES (...) 1 1 0 0 -statements_digest 4e51253af793867fba66166de1f314f7 INSERT INTO t5 VALUES (...) 1 1 0 0 -statements_digest fa47b3109e117216cd10209690d28596 INSERT INTO t1 VALUES (?) /* , ... */ 2 7 0 0 -statements_digest 72409f84bc236e6fe9f2f7b4d727f2d3 INSERT INTO t3 VALUES (...) /* , ... */ 1 3 0 0 -statements_digest d40aaddb41ed794d65dd8273f0c75700 INSERT INTO t5 VALUES (...) /* , ... */ 1 3 0 0 -statements_digest 57a82b28388e52e99fc64339dd30edde INSERT INTO t1 VALUES ( NULL ) 1 1 0 0 -statements_digest 6a56b694106442474cb0e5fb7575c8b9 INSERT INTO t6 VALUES (...) 5 5 0 0 -statements_digest c9abf55e296c4317dbaf2d14ef907ad7 SELECT ? + ? 3 0 0 0 -statements_digest 156304a0851a3e3626b39fb3da841a82 SELECT ? 1 0 0 0 -statements_digest 3b085ab0d2063dfca1a39212e3ea1831 CREATE SCHEMA statements_digest_temp 2 2 0 0 -statements_digest 09f9fabef2feb9a54ba01455e5ae83b9 DROP SCHEMA statements_digest_temp 2 0 0 0 -statements_digest 7910a63ffd31cbcb742e15270c8958c8 SELECT ? FROM no_such_table 1 0 0 1 -statements_digest fa34540a438bc672478b1162505ee28c CREATE TABLE dup_table ( c CHARACTER (?) ) 2 0 0 1 -statements_digest 2c720f176bb7c8510ff8aca8921b9945 DROP TABLE dup_table 1 0 0 0 -statements_digest 0c7d9fd8c27ab067511da41ca3bcdff3 INSERT INTO t11 VALUES (?) 1 1 1 0 -statements_digest 81681ff345065ed72bcd1e9407ab85e4 SHOW WARNINGS 1 0 0 0 -statements_digest d766f5823ae5d8e4cf4602b8e7a3fb80 PREPARE stmt FROM ? 1 0 0 0 -statements_digest 3ab1e87eabd9688edf919754cce6348b EXECUTE stmt 2 0 0 0 -statements_digest 470094469d250b9f45cab45bf610efe8 DEALLOCATE PREPARE stmt 1 0 0 0 -statements_digest 1b4d25358e08b35ad54e49dfe5eaf3e4 CREATE PROCEDURE p1 ( ) BEGIN SELECT * FROM t12 ; END 1 0 0 0 -statements_digest 84554971243e91106214dcb8f4eaa89b CALL p1 ( ) 2 0 0 0 -statements_digest 77206e4bf30979c56752a7ed9150213a DROP PROCEDURE p1 1 0 0 0 -statements_digest 03b91dcdba6b0e29f7fb240ae4bcd97f CREATE FUNCTION `func` ( a INTEGER , b INTEGER ) RETURNS INTEGER (?) RETURN a + b 1 0 0 0 -statements_digest 72bc532f308f2dca62f5291df8c50e6f SELECT func (...) 2 0 0 0 -statements_digest 0b5a5297689c5036def6af8e8a8ce113 DROP FUNCTION func 1 0 0 0 -statements_digest d08331e42c67555ece50e46eef0f2b47 CREATE TRIGGER trg BEFORE INSERT ON t12 FOR EACH ROW SET @ ? := ? 1 0 0 0 -statements_digest 754a49a4de995c5a729e9ab52f135f59 INSERT INTO t12 VALUES (?) 2 2 0 0 -statements_digest 68df17752bca7c2c8ee2a6a19a0674e7 DROP TRIGGER trg 1 0 0 0 +SCHEMA_NAME DIGEST_TEXT COUNT_STAR SUM_ROWS_AFFECTED SUM_WARNINGS SUM_ERRORS +statements_digest TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1 0 0 0 +statements_digest SELECT ? FROM t1 1 0 0 0 +statements_digest SELECT ? FROM `t1` 1 0 0 0 +statements_digest SELECT ?, ... FROM t1 2 0 0 0 +statements_digest SELECT ? FROM t2 1 0 0 0 +statements_digest SELECT ?, ... FROM t2 2 0 0 0 +statements_digest INSERT INTO t1 VALUES (?) 1 1 0 0 +statements_digest INSERT INTO t2 VALUES (?) 1 1 0 0 +statements_digest INSERT INTO t3 VALUES (...) 4 4 0 0 +statements_digest INSERT INTO t4 VALUES (...) 1 1 0 0 +statements_digest INSERT INTO t5 VALUES (...) 1 1 0 0 +statements_digest INSERT INTO t1 VALUES (?) /* , ... */ 2 7 0 0 +statements_digest INSERT INTO t3 VALUES (...) /* , ... */ 1 3 0 0 +statements_digest INSERT INTO t5 VALUES (...) /* , ... */ 1 3 0 0 +statements_digest INSERT INTO t1 VALUES ( NULL ) 1 1 0 0 +statements_digest INSERT INTO t6 VALUES (...) 5 5 0 0 +statements_digest SELECT ? + ? 3 0 0 0 +statements_digest SELECT ? 1 0 0 0 +statements_digest CREATE SCHEMA statements_digest_temp 2 2 0 0 +statements_digest DROP SCHEMA statements_digest_temp 2 0 0 0 +statements_digest SELECT ? FROM no_such_table 1 0 0 1 +statements_digest CREATE TABLE dup_table ( c CHARACTER (?) ) 2 0 0 1 +statements_digest DROP TABLE dup_table 1 0 0 0 +statements_digest INSERT INTO t11 VALUES (?) 1 1 1 0 +statements_digest SHOW WARNINGS 1 0 0 0 +statements_digest PREPARE stmt FROM ? 1 0 0 0 +statements_digest EXECUTE stmt 2 0 0 0 +statements_digest DEALLOCATE PREPARE stmt 1 0 0 0 +statements_digest CREATE PROCEDURE p1 ( ) BEGIN SELECT * FROM t12 ; END 1 0 0 0 +statements_digest CALL p1 ( ) 2 0 0 0 +statements_digest DROP PROCEDURE p1 1 0 0 0 +statements_digest CREATE FUNCTION `func` ( a INTEGER , b INTEGER ) RETURNS INTEGER (?) RETURN a + b 1 0 0 0 +statements_digest SELECT func (...) 2 0 0 0 +statements_digest DROP FUNCTION func 1 0 0 0 +statements_digest CREATE TRIGGER trg BEFORE INSERT ON t12 FOR EACH ROW SET @ ? := ? 1 0 0 0 +statements_digest INSERT INTO t12 VALUES (?) 2 2 0 0 +statements_digest DROP TRIGGER trg 1 0 0 0 #################################### # CLEANUP #################################### diff --git a/mysql-test/suite/perfschema/r/statement_digest_consumers.result b/mysql-test/suite/perfschema/r/statement_digest_consumers.result index 21e62e13b19..8c5696bb139 100644 --- a/mysql-test/suite/perfschema/r/statement_digest_consumers.result +++ b/mysql-test/suite/perfschema/r/statement_digest_consumers.result @@ -123,47 +123,47 @@ DROP TRIGGER trg; #################################### # QUERYING PS STATEMENT DIGEST #################################### -SELECT schema_name, digest, digest_text, count_star FROM performance_schema.events_statements_summary_by_digest; -schema_name digest digest_text count_star -statements_digest 0e98ee6a98e296530ec59c12dbc08dfe TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1 -statements_digest 954f43425c3234acc8e194afd97e8a0a SELECT ? FROM t1 1 -statements_digest fc365a54bc19d746bd24c27aba46b990 SELECT ? FROM `t1` 1 -statements_digest 27ba28f6252e4ae0e9b14b36da536fbe SELECT ?, ... FROM t1 2 -statements_digest 81d03922612900032ec4b81934ab4841 SELECT ? FROM t2 1 -statements_digest adce8aec12b6b5046cd4bf55951014c7 SELECT ?, ... FROM t2 2 -statements_digest 59a1bd93c424b10802fe66bb6dcd94d2 INSERT INTO t1 VALUES (?) 1 -statements_digest 91b2da58b0eb49c35a38fbc49f5e491d INSERT INTO t2 VALUES (?) 1 -statements_digest 967114adbf91d8a4a99ec5e49e909ff4 INSERT INTO t3 VALUES (...) 4 -statements_digest 8f25e7a48487e0aa7377e816816bb658 INSERT INTO t4 VALUES (...) 1 -statements_digest 4e51253af793867fba66166de1f314f7 INSERT INTO t5 VALUES (...) 1 -statements_digest fa47b3109e117216cd10209690d28596 INSERT INTO t1 VALUES (?) /* , ... */ 2 -statements_digest 72409f84bc236e6fe9f2f7b4d727f2d3 INSERT INTO t3 VALUES (...) /* , ... */ 1 -statements_digest d40aaddb41ed794d65dd8273f0c75700 INSERT INTO t5 VALUES (...) /* , ... */ 1 -statements_digest 57a82b28388e52e99fc64339dd30edde INSERT INTO t1 VALUES ( NULL ) 1 -statements_digest 6a56b694106442474cb0e5fb7575c8b9 INSERT INTO t6 VALUES (...) 5 -statements_digest c9abf55e296c4317dbaf2d14ef907ad7 SELECT ? + ? 3 -statements_digest 156304a0851a3e3626b39fb3da841a82 SELECT ? 1 -statements_digest 3b085ab0d2063dfca1a39212e3ea1831 CREATE SCHEMA statements_digest_temp 2 -statements_digest 09f9fabef2feb9a54ba01455e5ae83b9 DROP SCHEMA statements_digest_temp 2 -statements_digest 7910a63ffd31cbcb742e15270c8958c8 SELECT ? FROM no_such_table 1 -statements_digest fa34540a438bc672478b1162505ee28c CREATE TABLE dup_table ( c CHARACTER (?) ) 2 -statements_digest 2c720f176bb7c8510ff8aca8921b9945 DROP TABLE dup_table 1 -statements_digest 0c7d9fd8c27ab067511da41ca3bcdff3 INSERT INTO t11 VALUES (?) 1 -statements_digest 81681ff345065ed72bcd1e9407ab85e4 SHOW WARNINGS 1 -statements_digest d766f5823ae5d8e4cf4602b8e7a3fb80 PREPARE stmt FROM ? 1 -statements_digest 3ab1e87eabd9688edf919754cce6348b EXECUTE stmt 2 -statements_digest 470094469d250b9f45cab45bf610efe8 DEALLOCATE PREPARE stmt 1 -statements_digest 1b4d25358e08b35ad54e49dfe5eaf3e4 CREATE PROCEDURE p1 ( ) BEGIN SELECT * FROM t12 ; END 1 -statements_digest 84554971243e91106214dcb8f4eaa89b CALL p1 ( ) 2 -statements_digest 77206e4bf30979c56752a7ed9150213a DROP PROCEDURE p1 1 -statements_digest 03b91dcdba6b0e29f7fb240ae4bcd97f CREATE FUNCTION `func` ( a INTEGER , b INTEGER ) RETURNS INTEGER (?) RETURN a + b 1 -statements_digest 72bc532f308f2dca62f5291df8c50e6f SELECT func (...) 2 -statements_digest 0b5a5297689c5036def6af8e8a8ce113 DROP FUNCTION func 1 -statements_digest d08331e42c67555ece50e46eef0f2b47 CREATE TRIGGER trg BEFORE INSERT ON t12 FOR EACH ROW SET @ ? := ? 1 -statements_digest 754a49a4de995c5a729e9ab52f135f59 INSERT INTO t12 VALUES (?) 2 -statements_digest 68df17752bca7c2c8ee2a6a19a0674e7 DROP TRIGGER trg 1 -SELECT digest, digest_text FROM performance_schema.events_statements_current; -digest digest_text +SELECT schema_name,digest_text, count_star FROM performance_schema.events_statements_summary_by_digest; +schema_name digest_text count_star +statements_digest TRUNCATE TABLE performance_schema . events_statements_summary_by_digest 1 +statements_digest SELECT ? FROM t1 1 +statements_digest SELECT ? FROM `t1` 1 +statements_digest SELECT ?, ... FROM t1 2 +statements_digest SELECT ? FROM t2 1 +statements_digest SELECT ?, ... FROM t2 2 +statements_digest INSERT INTO t1 VALUES (?) 1 +statements_digest INSERT INTO t2 VALUES (?) 1 +statements_digest INSERT INTO t3 VALUES (...) 4 +statements_digest INSERT INTO t4 VALUES (...) 1 +statements_digest INSERT INTO t5 VALUES (...) 1 +statements_digest INSERT INTO t1 VALUES (?) /* , ... */ 2 +statements_digest INSERT INTO t3 VALUES (...) /* , ... */ 1 +statements_digest INSERT INTO t5 VALUES (...) /* , ... */ 1 +statements_digest INSERT INTO t1 VALUES ( NULL ) 1 +statements_digest INSERT INTO t6 VALUES (...) 5 +statements_digest SELECT ? + ? 3 +statements_digest SELECT ? 1 +statements_digest CREATE SCHEMA statements_digest_temp 2 +statements_digest DROP SCHEMA statements_digest_temp 2 +statements_digest SELECT ? FROM no_such_table 1 +statements_digest CREATE TABLE dup_table ( c CHARACTER (?) ) 2 +statements_digest DROP TABLE dup_table 1 +statements_digest INSERT INTO t11 VALUES (?) 1 +statements_digest SHOW WARNINGS 1 +statements_digest PREPARE stmt FROM ? 1 +statements_digest EXECUTE stmt 2 +statements_digest DEALLOCATE PREPARE stmt 1 +statements_digest CREATE PROCEDURE p1 ( ) BEGIN SELECT * FROM t12 ; END 1 +statements_digest CALL p1 ( ) 2 +statements_digest DROP PROCEDURE p1 1 +statements_digest CREATE FUNCTION `func` ( a INTEGER , b INTEGER ) RETURNS INTEGER (?) RETURN a + b 1 +statements_digest SELECT func (...) 2 +statements_digest DROP FUNCTION func 1 +statements_digest CREATE TRIGGER trg BEFORE INSERT ON t12 FOR EACH ROW SET @ ? := ? 1 +statements_digest INSERT INTO t12 VALUES (?) 2 +statements_digest DROP TRIGGER trg 1 +SELECT digest_text FROM performance_schema.events_statements_current; +digest_text #################################### # CLEANUP #################################### diff --git a/mysql-test/suite/perfschema/r/statement_digest_long_query.result b/mysql-test/suite/perfschema/r/statement_digest_long_query.result index bb355304537..8bc7a877bda 100644 --- a/mysql-test/suite/perfschema/r/statement_digest_long_query.result +++ b/mysql-test/suite/perfschema/r/statement_digest_long_query.result @@ -6,7 +6,7 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 #################################### # QUERYING PS STATEMENT DIGEST #################################### -SELECT schema_name, digest, digest_text, count_star FROM events_statements_summary_by_digest; -schema_name digest digest_text count_star -performance_schema 9d35ff74210c6b30efa4559d627ed0f7 TRUNCATE TABLE events_statements_summary_by_digest 1 -performance_schema d78a04c1c42765b8552e0483c50ae9ff SELECT ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ... 1 +SELECT schema_name, digest_text, count_star FROM events_statements_summary_by_digest; +schema_name digest_text count_star +performance_schema TRUNCATE TABLE events_statements_summary_by_digest 1 +performance_schema SELECT ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ... 1 diff --git a/mysql-test/suite/perfschema/t/digest_table_full.test b/mysql-test/suite/perfschema/t/digest_table_full.test index cb9d7ea4ea8..dbbce662256 100644 --- a/mysql-test/suite/perfschema/t/digest_table_full.test +++ b/mysql-test/suite/perfschema/t/digest_table_full.test @@ -19,7 +19,7 @@ TRUNCATE TABLE performance_schema.events_statements_summary_by_digest; --echo #################################### --echo # QUERYING PS STATEMENT DIGEST --echo #################################### -SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, +SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest; diff --git a/mysql-test/suite/perfschema/t/rpl_gtid_func.test b/mysql-test/suite/perfschema/t/rpl_gtid_func.test index 27837572bff..f337f95bf84 100644 --- a/mysql-test/suite/perfschema/t/rpl_gtid_func.test +++ b/mysql-test/suite/perfschema/t/rpl_gtid_func.test @@ -45,7 +45,7 @@ insert into performance_schema.setup_objects select * from performance_schema.setup_objects order by object_type, object_schema, object_name; -select digest, digest_text, count_star +select digest_text, count_star from performance_schema.events_statements_summary_by_digest where digest_text like "%in_%_digest%"; @@ -67,7 +67,7 @@ insert into performance_schema.setup_objects select * from performance_schema.setup_objects order by object_type, object_schema, object_name; -select digest, digest_text, count_star +select digest_text, count_star from performance_schema.events_statements_summary_by_digest where digest_text like "%in_%_digest%"; diff --git a/mysql-test/suite/perfschema/t/start_server_no_digests.test b/mysql-test/suite/perfschema/t/start_server_no_digests.test index cb9d7ea4ea8..dbbce662256 100644 --- a/mysql-test/suite/perfschema/t/start_server_no_digests.test +++ b/mysql-test/suite/perfschema/t/start_server_no_digests.test @@ -19,7 +19,7 @@ TRUNCATE TABLE performance_schema.events_statements_summary_by_digest; --echo #################################### --echo # QUERYING PS STATEMENT DIGEST --echo #################################### -SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, +SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest; diff --git a/mysql-test/suite/perfschema/t/statement_digest.test b/mysql-test/suite/perfschema/t/statement_digest.test index ed1f99e4318..59486ad61d8 100644 --- a/mysql-test/suite/perfschema/t/statement_digest.test +++ b/mysql-test/suite/perfschema/t/statement_digest.test @@ -16,7 +16,7 @@ TRUNCATE TABLE performance_schema.events_statements_summary_by_digest; --echo #################################### --echo # QUERYING PS STATEMENT DIGEST --echo #################################### -SELECT SCHEMA_NAME, DIGEST, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, +SELECT SCHEMA_NAME, DIGEST_TEXT, COUNT_STAR, SUM_ROWS_AFFECTED, SUM_WARNINGS, SUM_ERRORS FROM performance_schema.events_statements_summary_by_digest; # Cleanup for Digest diff --git a/mysql-test/suite/perfschema/t/statement_digest_consumers.test b/mysql-test/suite/perfschema/t/statement_digest_consumers.test index e7510e32049..16fa300b975 100644 --- a/mysql-test/suite/perfschema/t/statement_digest_consumers.test +++ b/mysql-test/suite/perfschema/t/statement_digest_consumers.test @@ -28,8 +28,8 @@ TRUNCATE TABLE performance_schema.events_statements_summary_by_digest; --echo #################################### --echo # QUERYING PS STATEMENT DIGEST --echo #################################### -SELECT schema_name, digest, digest_text, count_star FROM performance_schema.events_statements_summary_by_digest; -SELECT digest, digest_text FROM performance_schema.events_statements_current; +SELECT schema_name,digest_text, count_star FROM performance_schema.events_statements_summary_by_digest; +SELECT digest_text FROM performance_schema.events_statements_current; # Cleanup for Digest --source ../include/digest_cleanup.inc diff --git a/mysql-test/suite/perfschema/t/statement_digest_long_query.test b/mysql-test/suite/perfschema/t/statement_digest_long_query.test index 3969383a6fb..be80917c9af 100644 --- a/mysql-test/suite/perfschema/t/statement_digest_long_query.test +++ b/mysql-test/suite/perfschema/t/statement_digest_long_query.test @@ -20,4 +20,4 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 --echo #################################### --echo # QUERYING PS STATEMENT DIGEST --echo #################################### -SELECT schema_name, digest, digest_text, count_star FROM events_statements_summary_by_digest; +SELECT schema_name, digest_text, count_star FROM events_statements_summary_by_digest; diff --git a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result deleted file mode 100644 index df4bc6ce5f6..00000000000 --- a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.result +++ /dev/null @@ -1,25 +0,0 @@ -use mysql; -alter table user drop column is_role; -alter table user drop column default_role; -flush privileges; -create role test_role; -ERROR HY000: Column count of mysql.user is wrong. Expected 44, found 43. Created with MariaDB MYSQL_VERSION_ID, now running MYSQL_VERSION_ID. Please use mysql_upgrade to fix this error. -drop role test_role; -ERROR HY000: Operation DROP ROLE failed for 'test_role' -alter table user add column is_role enum('N', 'Y') default 'N' not null -COLLATE utf8_general_ci -after password_expired; -create role test_role; -create user test_user@localhost; -grant test_role to test_user@localhost; -set default role test_role for root@localhost; -ERROR HY000: Column count of mysql.user is wrong. Expected 45, found 44. Created with MariaDB MYSQL_VERSION_ID, now running MYSQL_VERSION_ID. Please use mysql_upgrade to fix this error. -drop role test_role; -drop user test_user@localhost; -alter table user add column default_role char(80) binary default '' not null -COLLATE utf8_general_ci -after is_role; -update user set is_role='N'; -flush privileges; -create role test_role; -drop role test_role; diff --git a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test b/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test deleted file mode 100644 index 5122a2fed9a..00000000000 --- a/mysql-test/suite/roles/create_and_drop_role_invalid_user_table.test +++ /dev/null @@ -1,38 +0,0 @@ -source include/not_embedded.inc; - -connect (mysql, localhost, root,,); -use mysql; - -alter table user drop column is_role; -alter table user drop column default_role; - -flush privileges; - ---replace_regex /10\d\d\d\d/MYSQL_VERSION_ID/ ---error ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE -create role test_role; ---error ER_CANNOT_USER -drop role test_role; -alter table user add column is_role enum('N', 'Y') default 'N' not null - COLLATE utf8_general_ci -after password_expired; - -# Test default role column -create role test_role; -create user test_user@localhost; -grant test_role to test_user@localhost; ---replace_regex /10\d\d\d\d/MYSQL_VERSION_ID/ ---error ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE -set default role test_role for root@localhost; -drop role test_role; -drop user test_user@localhost; - -alter table user add column default_role char(80) binary default '' not null - COLLATE utf8_general_ci -after is_role; - -update user set is_role='N'; - -flush privileges; -create role test_role; -drop role test_role; diff --git a/mysql-test/suite/roles/set_role-recursive.result b/mysql-test/suite/roles/set_role-recursive.result index 008de2c3265..9e62558fc14 100644 --- a/mysql-test/suite/roles/set_role-recursive.result +++ b/mysql-test/suite/roles/set_role-recursive.result @@ -16,11 +16,11 @@ Host User Role Admin_option test_role1 test_role2 N grant select on *.* to test_role2; select * from mysql.user where user like 'test_role1'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role - test_role1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time + test_role1 N N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000 select * from mysql.user where user like 'test_role2'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role - test_role2 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time + test_role2 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000 select * from mysql.roles_mapping; ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping' show grants; diff --git a/mysql-test/suite/roles/set_role-simple.result b/mysql-test/suite/roles/set_role-simple.result index f870bf8eb30..3ce6d5c054b 100644 --- a/mysql-test/suite/roles/set_role-simple.result +++ b/mysql-test/suite/roles/set_role-simple.result @@ -11,8 +11,8 @@ localhost root test_role1 Y localhost test_user test_role1 N grant select on *.* to test_role1; select * from mysql.user where user='test_role1'; -Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role - test_role1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y +Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Create_user_priv Event_priv Trigger_priv Create_tablespace_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections max_user_connections plugin authentication_string password_expired is_role default_role max_statement_time + test_role1 Y N N N N N N N N N N N N N N N N N N N N N N N N N N N N 0 0 0 0 N Y 0.000000 select * from mysql.roles_mapping; ERROR 42000: SELECT command denied to user 'test_user'@'localhost' for table 'roles_mapping' show grants; diff --git a/mysql-test/suite/sys_vars/r/max_statement_time_basic.result b/mysql-test/suite/sys_vars/r/max_statement_time_basic.result new file mode 100644 index 00000000000..8b384ac6765 --- /dev/null +++ b/mysql-test/suite/sys_vars/r/max_statement_time_basic.result @@ -0,0 +1,172 @@ +SET @start_global_value = @@global.max_statement_time; +SELECT @start_global_value; +@start_global_value +0 +SET @start_session_value = @@session.max_statement_time; +SELECT @start_session_value; +@start_session_value +0 +'#--------------------FN_DYNVARS_068_01-------------------------#' +SET @@global.max_statement_time = 100; +SET @@global.max_statement_time = DEFAULT; +SELECT @@global.max_statement_time; +@@global.max_statement_time +0.000000 +SET @@session.max_statement_time = 200; +SET @@session.max_statement_time = DEFAULT; +SELECT @@session.max_statement_time; +@@session.max_statement_time +0.000000 +'#--------------------FN_DYNVARS_068_02-------------------------#' +SET @@global.max_statement_time = DEFAULT; +SELECT @@global.max_statement_time = 0; +@@global.max_statement_time = 0 +1 +SET @@session.max_statement_time = DEFAULT; +SELECT @@session.max_statement_time = 0; +@@session.max_statement_time = 0 +1 +'#--------------------FN_DYNVARS_068_03-------------------------#' +SET @@global.max_statement_time = 0; +SELECT @@global.max_statement_time; +@@global.max_statement_time +0.000000 +SET @@global.max_statement_time = 0.123456; +SELECT @@global.max_statement_time; +@@global.max_statement_time +0.123456 +SET @@global.max_statement_time = 60020; +SELECT @@global.max_statement_time; +@@global.max_statement_time +60020.000000 +SET @@global.max_statement_time = 31536000; +SELECT @@global.max_statement_time; +@@global.max_statement_time +31536000.000000 +SET @@global.max_statement_time = 65536; +SELECT @@global.max_statement_time; +@@global.max_statement_time +65536.000000 +'#--------------------FN_DYNVARS_068_04-------------------------#' +SET @@session.max_statement_time = 0; +SELECT @@session.max_statement_time; +@@session.max_statement_time +0.000000 +SET @@session.max_statement_time = 1; +SELECT @@session.max_statement_time; +@@session.max_statement_time +1.000000 +SET @@session.max_statement_time = 50050; +SELECT @@session.max_statement_time; +@@session.max_statement_time +50050.000000 +SET @@session.max_statement_time = 31536000; +SELECT @@session.max_statement_time; +@@session.max_statement_time +31536000.000000 +SET @@session.max_statement_time = 65550; +SELECT @@session.max_statement_time; +@@session.max_statement_time +65550.000000 +'#------------------FN_DYNVARS_068_05-----------------------#' +SET @@global.max_statement_time = 100000000000; +Warnings: +Warning 1292 Truncated incorrect max_statement_time value: '100000000000' +SELECT @@global.max_statement_time; +@@global.max_statement_time +31536000.000000 +SET @@global.max_statement_time = -1; +Warnings: +Warning 1292 Truncated incorrect max_statement_time value: '-1' +SELECT @@global.max_statement_time; +@@global.max_statement_time +0.000000 +SET @@global.max_statement_time = 65530.34; +SELECT @@global.max_statement_time; +@@global.max_statement_time +65530.340000 +SET @@global.max_statement_time = test; +ERROR 42000: Incorrect argument type to variable 'max_statement_time' +SELECT @@global.max_statement_time; +@@global.max_statement_time +65530.340000 +SET @@session.max_statement_time = 100000000000; +Warnings: +Warning 1292 Truncated incorrect max_statement_time value: '100000000000' +SELECT @@session.max_statement_time; +@@session.max_statement_time +31536000.000000 +SET @@session.max_statement_time = -2; +Warnings: +Warning 1292 Truncated incorrect max_statement_time value: '-2' +SELECT @@session.max_statement_time; +@@session.max_statement_time +0.000000 +SET @@session.max_statement_time = 65530.34; +SELECT @@session.max_statement_time; +@@session.max_statement_time +65530.340000 +SET @@session.max_statement_time = test; +ERROR 42000: Incorrect argument type to variable 'max_statement_time' +SELECT @@session.max_statement_time; +@@session.max_statement_time +65530.340000 +'#------------------FN_DYNVARS_068_06-----------------------#' +SELECT @@global.max_statement_time = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='max_statement_time'; +@@global.max_statement_time = VARIABLE_VALUE +1 +'#------------------FN_DYNVARS_068_07-----------------------#' +SELECT @@session.max_statement_time = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.SESSION_VARIABLES +WHERE VARIABLE_NAME='max_statement_time'; +@@session.max_statement_time = VARIABLE_VALUE +1 +'#------------------FN_DYNVARS_068_08-----------------------#' +SET @@global.max_statement_time = TRUE; +SELECT @@global.max_statement_time; +@@global.max_statement_time +1.000000 +SET @@global.max_statement_time = FALSE; +SELECT @@global.max_statement_time; +@@global.max_statement_time +0.000000 +'#---------------------FN_DYNVARS_001_09----------------------#' +SET @@global.max_statement_time = 10; +SELECT @@max_statement_time = @@global.max_statement_time; +@@max_statement_time = @@global.max_statement_time +0 +'#---------------------FN_DYNVARS_001_10----------------------#' +SET @@max_statement_time = 100; +SELECT @@max_statement_time = @@local.max_statement_time; +@@max_statement_time = @@local.max_statement_time +1 +SELECT @@local.max_statement_time = @@session.max_statement_time; +@@local.max_statement_time = @@session.max_statement_time +1 +'#---------------------FN_DYNVARS_001_11----------------------#' +SET max_statement_time = 1; +SELECT @@max_statement_time; +@@max_statement_time +1.000000 +SELECT local.max_statement_time; +ERROR 42S02: Unknown table 'local' in field list +SELECT session.max_statement_time; +ERROR 42S02: Unknown table 'session' in field list +SELECT max_statement_time = @@session.max_statement_time; +ERROR 42S22: Unknown column 'max_statement_time' in 'field list' +# +# Check that one can use max_statement_time as a field +# +drop table if exists t1; +create table t1 (a int, max_statement_time int); +drop table t1; +SET @@global.max_statement_time = @start_global_value; +SELECT @@global.max_statement_time; +@@global.max_statement_time +0.000000 +SET @@session.max_statement_time = @start_session_value; +SELECT @@session.max_statement_time; +@@session.max_statement_time +0.000000 diff --git a/mysql-test/suite/sys_vars/t/max_statement_time_basic.test b/mysql-test/suite/sys_vars/t/max_statement_time_basic.test new file mode 100644 index 00000000000..186589dcee2 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/max_statement_time_basic.test @@ -0,0 +1,217 @@ +####################### mysql-test\t\max_statement_time_basic.test ############### +# # +# Variable Name: max_statement_time # +# Scope: GLOBAL | SESSION # +# Access Type: Dynamic # +# Data Type: numeric # +# Default Value:10 # +# Min Value: 1 # +# # +# # +# Creation Date: 2012-12-30 # +# Author: Monty # +# # +# Description: Test Cases of Dynamic System Variable max_statement_time # +# that checks the behavior of this variable in the following ways# +# * Default Value # +# * Valid & Invalid values # +# * Scope & Access method # +# * Data Integrity # +# # +# Reference: https://kb.askmonty.org/en/how-to-limittimeout-queries/ # +# server-system-variables.html # +# # +############################################################################### + +--source include/load_sysvars.inc + +############################################################ +# START OF max_statement_time TESTS # +############################################################ + + +############################################################# +# Save initial value # +############################################################# + +SET @start_global_value = @@global.max_statement_time; +SELECT @start_global_value; +SET @start_session_value = @@session.max_statement_time; +SELECT @start_session_value; + + +--echo '#--------------------FN_DYNVARS_068_01-------------------------#' +############################################################### +# Display the DEFAULT value of max_statement_time # +############################################################### + +SET @@global.max_statement_time = 100; +SET @@global.max_statement_time = DEFAULT; +SELECT @@global.max_statement_time; + +SET @@session.max_statement_time = 200; +SET @@session.max_statement_time = DEFAULT; +SELECT @@session.max_statement_time; + + +--echo '#--------------------FN_DYNVARS_068_02-------------------------#' +############################################################### +# Check the DEFAULT value of max_statement_time # +############################################################### + +SET @@global.max_statement_time = DEFAULT; +SELECT @@global.max_statement_time = 0; + +SET @@session.max_statement_time = DEFAULT; +SELECT @@session.max_statement_time = 0; + + +--echo '#--------------------FN_DYNVARS_068_03-------------------------#' +######################################################################### +# Change the value of max_statement_time to a valid value for GLOBAL Scope # +######################################################################### + +SET @@global.max_statement_time = 0; +SELECT @@global.max_statement_time; +SET @@global.max_statement_time = 0.123456; +SELECT @@global.max_statement_time; +SET @@global.max_statement_time = 60020; +SELECT @@global.max_statement_time; +SET @@global.max_statement_time = 31536000; +SELECT @@global.max_statement_time; +SET @@global.max_statement_time = 65536; +SELECT @@global.max_statement_time; + + +--echo '#--------------------FN_DYNVARS_068_04-------------------------#' +########################################################################## +# Change the value of max_statement_time to a valid value for SESSION Scope # +########################################################################## + +SET @@session.max_statement_time = 0; +SELECT @@session.max_statement_time; +SET @@session.max_statement_time = 1; +SELECT @@session.max_statement_time; +SET @@session.max_statement_time = 50050; +SELECT @@session.max_statement_time; +SET @@session.max_statement_time = 31536000; +SELECT @@session.max_statement_time; +SET @@session.max_statement_time = 65550; +SELECT @@session.max_statement_time; + + +--echo '#------------------FN_DYNVARS_068_05-----------------------#' +######################################################## +# Change the value of max_statement_time to an invalid value # +######################################################## + +SET @@global.max_statement_time = 100000000000; +SELECT @@global.max_statement_time; +SET @@global.max_statement_time = -1; +SELECT @@global.max_statement_time; +SET @@global.max_statement_time = 65530.34; +SELECT @@global.max_statement_time; +--Error ER_WRONG_TYPE_FOR_VAR +SET @@global.max_statement_time = test; +SELECT @@global.max_statement_time; + +SET @@session.max_statement_time = 100000000000; +SELECT @@session.max_statement_time; +SET @@session.max_statement_time = -2; +SELECT @@session.max_statement_time; +SET @@session.max_statement_time = 65530.34; +SELECT @@session.max_statement_time; + +--Error ER_WRONG_TYPE_FOR_VAR +SET @@session.max_statement_time = test; +SELECT @@session.max_statement_time; + + +--echo '#------------------FN_DYNVARS_068_06-----------------------#' +#################################################################### +# Check if the value in GLOBAL Table matches value in variable # +#################################################################### + + +SELECT @@global.max_statement_time = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES +WHERE VARIABLE_NAME='max_statement_time'; + +--echo '#------------------FN_DYNVARS_068_07-----------------------#' +#################################################################### +# Check if the value in SESSION Table matches value in variable # +#################################################################### + +SELECT @@session.max_statement_time = VARIABLE_VALUE +FROM INFORMATION_SCHEMA.SESSION_VARIABLES +WHERE VARIABLE_NAME='max_statement_time'; + + +--echo '#------------------FN_DYNVARS_068_08-----------------------#' +#################################################################### +# Check if TRUE and FALSE values can be used on variable # +#################################################################### + +SET @@global.max_statement_time = TRUE; +SELECT @@global.max_statement_time; +SET @@global.max_statement_time = FALSE; +SELECT @@global.max_statement_time; + + +--echo '#---------------------FN_DYNVARS_001_09----------------------#' +################################################################################# +# Check if accessing variable with and without GLOBAL point to same variable # +################################################################################# + +SET @@global.max_statement_time = 10; +SELECT @@max_statement_time = @@global.max_statement_time; + + +--echo '#---------------------FN_DYNVARS_001_10----------------------#' +######################################################################################################## +# Check if accessing variable with SESSION,LOCAL and without SCOPE points to same session variable # +######################################################################################################## + +SET @@max_statement_time = 100; +SELECT @@max_statement_time = @@local.max_statement_time; +SELECT @@local.max_statement_time = @@session.max_statement_time; + + +--echo '#---------------------FN_DYNVARS_001_11----------------------#' +########################################################################## +# Check if max_statement_time can be accessed with and without @@ sign # +########################################################################## + +SET max_statement_time = 1; +SELECT @@max_statement_time; +--Error ER_UNKNOWN_TABLE +SELECT local.max_statement_time; +--Error ER_UNKNOWN_TABLE +SELECT session.max_statement_time; +--Error ER_BAD_FIELD_ERROR +SELECT max_statement_time = @@session.max_statement_time; + +--echo # +--echo # Check that one can use max_statement_time as a field +--echo # + +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a int, max_statement_time int); +drop table t1; + +#################################### +# Restore initial value # +#################################### + +SET @@global.max_statement_time = @start_global_value; +SELECT @@global.max_statement_time; +SET @@session.max_statement_time = @start_session_value; +SELECT @@session.max_statement_time; + + +#################################################### +# END OF max_statement_time TESTS # +#################################################### + diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index ed7271521c8..20632038273 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -47,10 +47,10 @@ flush privileges; # delete from mysql.user where user='mysqltest_1'; flush privileges; -grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10; +grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10 max_statement_time 60; query_vertical select * from mysql.user where user="mysqltest_1"; show grants for mysqltest_1@localhost; -grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30; +grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30 max_statement_time 0; query_vertical select * from mysql.user where user="mysqltest_1"; show grants for mysqltest_1@localhost; # This is just to double check that one won't ignore results of selects diff --git a/mysql-test/t/max_statement_time.test b/mysql-test/t/max_statement_time.test new file mode 100644 index 00000000000..0356d3caa49 --- /dev/null +++ b/mysql-test/t/max_statement_time.test @@ -0,0 +1,189 @@ +# +# Test behavior of MAX_STATEMENT_TIME. +# + +--source include/not_embedded.inc +--source include/have_innodb.inc + +--echo +--echo # Test the MAX_STATEMENT_TIME option. +--echo + +SET @@MAX_STATEMENT_TIME=2; +select @@max_statement_time; +SELECT SLEEP(1); +SELECT SLEEP(3); +SET @@MAX_STATEMENT_TIME=0; +SELECT SLEEP(1); +SHOW STATUS LIKE "max_statement_time_exceeded"; + +CREATE TABLE t1 (a INT, b VARCHAR(300)) engine=myisam; + +INSERT INTO t1 VALUES (1, 'string'); + +--disable_result_log +--disable_query_log + +SET @@MAX_STATEMENT_TIME=2; + +SET @@MAX_STATEMENT_TIME=0.1; +WHILE (! $mysql_errno) +{ + SET @@MAX_STATEMENT_TIME=0; + INSERT INTO t1 SELECT * FROM t1; + SET @@MAX_STATEMENT_TIME=0.1; + --error 0,ER_STATEMENT_TIMEOUT + SELECT COUNT(*) FROM t1 WHERE b LIKE '%z%'; +} +SET @@MAX_STATEMENT_TIME=0; + +--enable_query_log +--enable_result_log + +eval SELECT $mysql_errno; + +--echo +--echo # Test the MAX_STATEMENT_TIME option with SF (should have no effect). +--echo + +DELIMITER |; + +CREATE PROCEDURE p1() +BEGIN + declare tmp int; + SET @@MAX_STATEMENT_TIME=0.0001; + SELECT COUNT(*) INTO tmp FROM t1 WHERE b LIKE '%z%'; + SET @@MAX_STATEMENT_TIME=0; +END| + +CREATE PROCEDURE p2() +BEGIN + SET @@MAX_STATEMENT_TIME=5; +END| + +DELIMITER ;| + +SELECT @@MAX_STATEMENT_TIME; +CALL p1(); +CALL p2(); +SELECT @@MAX_STATEMENT_TIME; +SET @@MAX_STATEMENT_TIME=0; + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP TABLE t1; + +--echo +--echo # MAX_STATEMENT_TIME account resource +--echo + +GRANT USAGE ON *.* TO user1@localhost WITH MAX_STATEMENT_TIME 1.005; + +--echo # con1 +connect(con1,localhost,user1,,test,,); +SELECT @@max_statement_time; +disconnect con1; + +--echo # restart and reconnect +connection default; +source include/restart_mysqld.inc; + +set @global.userstat=1; +connect(con1,localhost,user1,,test,,); +SELECT @@global.max_statement_time,@@session.max_statement_time; +select sleep(100); +SHOW STATUS LIKE "max_statement_time_exceeded"; +disconnect con1; + +connection default; +show grants for user1@localhost; +--disable_parsing +select max_user_timeouts from information_schema.user_statistics where user="user1"; +--enable_parsing + +set @global.userstat=0; +DROP USER user1@localhost; + +--echo +--echo # MAX_STATEMENT_TIME status variables. +--echo + +flush status; + +SET @@max_statement_time=0; +SELECT CONVERT(VARIABLE_VALUE, UNSIGNED) INTO @time_exceeded + FROM INFORMATION_SCHEMA.GLOBAL_STATUS + WHERE VARIABLE_NAME = 'max_statement_time_exceeded'; + +SET @@max_statement_time=0.5; +SELECT SLEEP(2); +SHOW STATUS LIKE '%timeout%'; +SET @@max_statement_time=0; + +--echo # Ensure that the counters for: +--echo # - statements that exceeded their maximum execution time +--echo # are incremented. + +SELECT 1 AS STATUS FROM INFORMATION_SCHEMA.GLOBAL_STATUS + WHERE VARIABLE_NAME = 'max_statement_time_exceeded' + AND CONVERT(VARIABLE_VALUE, UNSIGNED) > @time_exceeded; + +--echo +--echo # Check that the appropriate error status is set. +--echo + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +START TRANSACTION; +SELECT * FROM t1 FOR UPDATE; + +connect (con1,localhost,root,,test,,); +SET @@SESSION.max_statement_time = 0.5; +--error ER_STATEMENT_TIMEOUT +UPDATE t1 SET a = 2; +SHOW WARNINGS; +disconnect con1; + +connection default; +ROLLBACK; +DROP TABLE t1; + +--echo +--echo # Test interaction with lock waits. +--echo + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1); + +connect (con1,localhost,root,,test,,); +SET @@SESSION.max_statement_time= 0.5; + +connection default; +LOCK TABLES t1 WRITE; + +connection con1; +SELECT @@SESSION.max_statement_time; +--error ER_STATEMENT_TIMEOUT +LOCK TABLES t1 READ; + +connection default; +UNLOCK TABLES; +BEGIN; +SELECT * FROM t1; + +connection con1; +--error ER_STATEMENT_TIMEOUT +ALTER TABLE t1 ADD COLUMN b INT; + +connection default; +ROLLBACK; +SELECT GET_LOCK('lock', 1); + +connection con1; +SELECT GET_LOCK('lock', 1); + +disconnect con1; +connection default; +SELECT RELEASE_LOCK('lock'); +DROP TABLE t1; diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index f0d25dae6b9..7f076b10e78 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -33,7 +33,9 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c my_default.c my_basename.c my_write.c ptr_cmp.c queues.c stacktrace.c string.c thr_alarm.c thr_lock.c thr_mutex.c - thr_rwlock.c tree.c typelib.c base64.c my_memmem.c my_getpagesize.c + thr_rwlock.c thr_timer.c + tree.c typelib.c base64.c my_memmem.c + my_getpagesize.c lf_alloc-pin.c lf_dynarray.c lf_hash.c safemalloc.c my_new.cc my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c @@ -89,6 +91,10 @@ ADD_EXECUTABLE(thr_lock thr_lock.c) TARGET_LINK_LIBRARIES(thr_lock mysys) SET_TARGET_PROPERTIES(thr_lock PROPERTIES COMPILE_FLAGS "-DMAIN") +ADD_EXECUTABLE(thr_timer thr_timer.c) +TARGET_LINK_LIBRARIES(thr_timer mysys) +SET_TARGET_PROPERTIES(thr_timer PROPERTIES COMPILE_FLAGS "-DMAIN") + INSTALL_DEBUG_SYMBOLS(mysys) IF(MSVC) INSTALL_DEBUG_TARGET(mysys DESTINATION ${INSTALL_LIBDIR}/debug) diff --git a/mysys/my_init.c b/mysys/my_init.c index 2c06425f6fb..32289dbed7a 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -454,7 +454,8 @@ PSI_mutex_key key_LOCK_localtime_r; #endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */ PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock, - key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, key_LOCK_alarm, + key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, + key_LOCK_alarm, key_LOCK_timer, key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap, key_THR_LOCK_lock, key_THR_LOCK_malloc, key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net, @@ -474,6 +475,7 @@ static PSI_mutex_info all_mysys_mutexes[]= { &key_IO_CACHE_SHARE_mutex, "IO_CACHE::SHARE_mutex", 0}, { &key_KEY_CACHE_cache_lock, "KEY_CACHE::cache_lock", 0}, { &key_LOCK_alarm, "LOCK_alarm", PSI_FLAG_GLOBAL}, + { &key_LOCK_timer, "LOCK_timer", PSI_FLAG_GLOBAL}, { &key_my_thread_var_mutex, "my_thread_var::mutex", 0}, { &key_THR_LOCK_charset, "THR_LOCK_charset", PSI_FLAG_GLOBAL}, { &key_THR_LOCK_heap, "THR_LOCK_heap", PSI_FLAG_GLOBAL}, @@ -489,13 +491,14 @@ static PSI_mutex_info all_mysys_mutexes[]= { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL } }; -PSI_cond_key key_COND_alarm, key_IO_CACHE_SHARE_cond, +PSI_cond_key key_COND_alarm, key_COND_timer, key_IO_CACHE_SHARE_cond, key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend, key_THR_COND_threads, key_WT_RESOURCE_cond; static PSI_cond_info all_mysys_conds[]= { { &key_COND_alarm, "COND_alarm", PSI_FLAG_GLOBAL}, + { &key_COND_timer, "COND_timer", PSI_FLAG_GLOBAL}, { &key_IO_CACHE_SHARE_cond, "IO_CACHE_SHARE::cond", 0}, { &key_IO_CACHE_SHARE_cond_writer, "IO_CACHE_SHARE::cond_writer", 0}, { &key_my_thread_var_suspend, "my_thread_var::suspend", 0}, @@ -512,12 +515,17 @@ static PSI_rwlock_info all_mysys_rwlocks[]= #ifdef USE_ALARM_THREAD PSI_thread_key key_thread_alarm; +#endif +PSI_thread_key key_thread_timer; static PSI_thread_info all_mysys_threads[]= { - { &key_thread_alarm, "alarm", PSI_FLAG_GLOBAL} +#ifdef USE_ALARM_THREAD + { &key_thread_alarm, "alarm", PSI_FLAG_GLOBAL}, +#endif + { &key_thread_timer, "statement_timer", PSI_FLAG_GLOBAL} }; -#endif /* USE_ALARM_THREAD */ + #ifdef HUGETLB_USE_PROC_MEMINFO PSI_file_key key_file_proc_meminfo; @@ -552,10 +560,8 @@ void my_init_mysys_psi_keys() count= sizeof(all_mysys_rwlocks)/sizeof(all_mysys_rwlocks[0]); mysql_rwlock_register(category, all_mysys_rwlocks, count); -#ifdef USE_ALARM_THREAD count= sizeof(all_mysys_threads)/sizeof(all_mysys_threads[0]); mysql_thread_register(category, all_mysys_threads, count); -#endif /* USE_ALARM_THREAD */ count= sizeof(all_mysys_files)/sizeof(all_mysys_files[0]); mysql_file_register(category, all_mysys_files, count); diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index 80c6a981db2..9b94a5a18ce 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -42,16 +42,16 @@ extern PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock, key_THR_LOCK_lock, key_THR_LOCK_malloc, key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net, key_THR_LOCK_open, key_THR_LOCK_threads, key_LOCK_uuid_generator, - key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap; + key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap, key_LOCK_timer; -extern PSI_cond_key key_COND_alarm, key_IO_CACHE_SHARE_cond, +extern PSI_cond_key key_COND_alarm, key_COND_timer, key_IO_CACHE_SHARE_cond, key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend, key_THR_COND_threads; #ifdef USE_ALARM_THREAD extern PSI_thread_key key_thread_alarm; #endif /* USE_ALARM_THREAD */ - +extern PSI_thread_key key_thread_timer; extern PSI_rwlock_key key_SAFEHASH_mutex; #endif /* HAVE_PSI_INTERFACE */ diff --git a/mysys/thr_timer.c b/mysys/thr_timer.c new file mode 100644 index 00000000000..6414ee6f246 --- /dev/null +++ b/mysys/thr_timer.c @@ -0,0 +1,589 @@ +/* + Copyright (c) 2012 Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 or later of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/* + Implementation if OS independent timers. + This is done based on pthread primitives, especially pthread_cond_timedwait() +*/ + +#include "mysys_priv.h" +#include "thr_timer.h" +#include <m_string.h> +#include <queues.h> +#ifdef HAVE_TIMER_CREATE +#include <sys/syscall.h> +#endif + +enum thread_state +{ + NOT_RUNNING= -1, RUNNING= 0, ABORTING=1 +}; + +static enum thread_state timer_thread_state= NOT_RUNNING; + +volatile my_bool timer_thread_running= 0; +struct timespec next_timer_expire_time; + +static my_bool thr_timer_inited= 0; +static mysql_mutex_t LOCK_timer; +static mysql_cond_t COND_timer; +static QUEUE timer_queue; +pthread_t timer_thread; + +#define set_max_time(abs_time) \ + { (abs_time)->MY_tv_sec= INT_MAX32; (abs_time)->MY_tv_nsec= 0; } + + +static void *timer_handler(void *arg __attribute__((unused))); + +/* + Compare two timespecs +*/ + +static int compare_timespec(void *not_used __attribute__((unused)), + uchar *a_ptr, uchar *b_ptr) +{ + return cmp_timespec((*(struct timespec*) a_ptr), + (*(struct timespec*) b_ptr)); +} + + +/** + Initialize timer variables and create timer thread + + @param alloc_timers Init allocation of timers. Will be autoextended + if needed + @return 0 ok + @return 1 error; Can't create thread +*/ + +static thr_timer_t max_timer_data; + +my_bool init_thr_timer(uint alloc_timers) +{ + pthread_attr_t thr_attr; + my_bool res; + DBUG_ENTER("init_thr_timer"); + + init_queue(&timer_queue, alloc_timers+2, offsetof(thr_timer_t,expire_time), + 0, compare_timespec, NullS, + offsetof(thr_timer_t, index_in_queue)+1, 1); + mysql_mutex_init(key_LOCK_timer, &LOCK_timer, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_timer, &COND_timer, NULL); + + /* Set dummy element with max time into the queue to simplify usage */ + bzero(&max_timer_data, sizeof(max_timer_data)); + set_max_time(&max_timer_data.expire_time); + queue_insert(&timer_queue, (uchar*) &max_timer_data); + next_timer_expire_time= max_timer_data.expire_time; + + /* Create a thread to handle timers */ + pthread_attr_init(&thr_attr); + pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); + pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); + pthread_attr_setstacksize(&thr_attr,8196); + res= mysql_thread_create(key_thread_timer, + &timer_thread, &thr_attr, timer_handler, NULL) != 0; + pthread_attr_destroy(&thr_attr); + + thr_timer_inited= 1; + DBUG_RETURN(res); +} + + +void end_thr_timer(void) +{ + struct timespec abstime; + DBUG_ENTER("end_thr_timer"); + + if (!thr_timer_inited) + DBUG_VOID_RETURN; + + mysql_mutex_lock(&LOCK_timer); + timer_thread_state= ABORTING; /* Signal abort */ + mysql_cond_signal(&COND_timer); + + /* Wait until timer thread dies */ + set_timespec(abstime, 10*1000); /* Wait up to 10 seconds */ + while (timer_thread_state == ABORTING) + { + int error= mysql_cond_timedwait(&COND_timer, &LOCK_timer, &abstime); + if (error == ETIME || error == ETIMEDOUT) + break; /* Don't wait forever */ + } + mysql_mutex_unlock(&LOCK_timer); + if (timer_thread_state == NOT_RUNNING) + { + mysql_mutex_destroy(&LOCK_timer); + mysql_cond_destroy(&COND_timer); + delete_queue(&timer_queue); + thr_timer_inited= 0; + } + DBUG_VOID_RETURN; +} + + +/* + Initialize a timer object + + @param timer_data Timer structure + @param function Function to be called when getting timeout + @param argument Argument for function +*/ + +void thr_timer_init(thr_timer_t *timer_data, void(*function)(void*), + void *arg) +{ + DBUG_ENTER("thr_timer_init"); + bzero(timer_data, sizeof(*timer_data)); + timer_data->func= function; + timer_data->func_arg= arg; + timer_data->expired= 1; /* Not active */ + DBUG_VOID_RETURN; +} + + +/* + Request timer after X milliseconds + + SYNOPSIS + thr_timer() + timer_data Pointer to timer structure + micro_seconds; Number of microseconds until timer + + RETURN VALUES + 0 ok + 1 If no more timers are allowed (aborted by process) + + Stores in first argument a pointer to a non-zero int which is set to 0 + when the timer has been given +*/ + +my_bool thr_timer_settime(thr_timer_t *timer_data, ulonglong micro_seconds) +{ + int reschedule; + DBUG_ENTER("thr_timer_settime"); + DBUG_PRINT("enter",("thread: %s micro_seconds: %llu",my_thread_name(), + micro_seconds)); + + DBUG_ASSERT(timer_data->expired == 1); + + set_timespec_nsec(timer_data->expire_time, micro_seconds*1000); + timer_data->expired= 0; + + mysql_mutex_lock(&LOCK_timer); /* Lock from threads & timers */ + if (queue_insert_safe(&timer_queue,(uchar*) timer_data)) + { + DBUG_PRINT("info", ("timer queue full")); + fprintf(stderr,"Warning: thr_timer queue is full\n"); + timer_data->expired= 1; + mysql_mutex_unlock(&LOCK_timer); + DBUG_RETURN(1); + } + + /* Reschedule timer if the current one has more time left than new one */ + reschedule= cmp_timespec(next_timer_expire_time, timer_data->expire_time); + mysql_mutex_unlock(&LOCK_timer); + if (reschedule > 0) + { +#if defined(MAIN) + printf("reschedule\n"); fflush(stdout); +#endif + DBUG_PRINT("info", ("reschedule")); + mysql_cond_signal(&COND_timer); + } + + DBUG_RETURN(0); +} + + +/* + Remove timer from list of timers + + notes: Timer will be marked as expired +*/ + +void thr_timer_end(thr_timer_t *timer_data) +{ + DBUG_ENTER("thr_timer_end"); + + mysql_mutex_lock(&LOCK_timer); + if (!timer_data->expired) + { + DBUG_ASSERT(timer_data->index_in_queue != 0); + DBUG_ASSERT(queue_element(&timer_queue, timer_data->index_in_queue) == + (uchar*) timer_data); + queue_remove(&timer_queue, timer_data->index_in_queue); + /* Mark as expired for asserts to work */ + timer_data->expired= 1; + } + mysql_mutex_unlock(&LOCK_timer); + DBUG_VOID_RETURN; +} + + +/* + Come here when some timer in queue is due. +*/ + +static sig_handler process_timers(struct timespec *now) +{ + thr_timer_t *timer_data; + DBUG_ENTER("process_timers"); + DBUG_PRINT("info",("active timers: %d", timer_queue.elements - 1)); + +#if defined(MAIN) + printf("process_timer\n"); fflush(stdout); +#endif + + /* We can safely remove the first one as it has already expired */ + for (;;) + { + void (*function)(void*); + void *func_arg; + + timer_data= (thr_timer_t*) queue_top(&timer_queue); + function= timer_data->func; + func_arg= timer_data->func_arg; + timer_data->expired= 1; /* Mark expired */ + /* + We remove timer before calling timer function to allow thread to + delete it's timer data any time. + */ + queue_remove_top(&timer_queue); /* Remove timer */ + (*function)(func_arg); /* Inform thread of timeout */ + + /* Check if next one has also expired */ + timer_data= (thr_timer_t*) queue_top(&timer_queue); + if (cmp_timespec(timer_data->expire_time, (*now)) > 0) + break; /* All data processed */ + } + DBUG_VOID_RETURN; +} + + +/* + set up a timer thread to handle timeouts + This will be killed when timer_thread_state is set to ABORTING. + At end timer_aborted will be set to NOT_RUNNING +*/ + +static void *timer_handler(void *arg __attribute__((unused))) +{ + my_thread_init(); + + timer_thread_state= RUNNING; + + mysql_mutex_lock(&LOCK_timer); + while (likely(timer_thread_state == RUNNING)) + { + int error; + struct timespec *top_time; + struct timespec now, abstime; + + set_timespec(now, 0); + + top_time= &(((thr_timer_t*) queue_top(&timer_queue))->expire_time); + + if (cmp_timespec((*top_time), now) <= 0) + { + process_timers(&now); + top_time= &(((thr_timer_t*) queue_top(&timer_queue))->expire_time); + } + + abstime= *top_time; + next_timer_expire_time= *top_time; + if ((error= mysql_cond_timedwait(&COND_timer, &LOCK_timer, &abstime)) && + error != ETIME && error != ETIMEDOUT) + { +#ifdef MAIN + printf("Got error: %d from ptread_cond_timedwait (errno: %d)\n", + error,errno); +#endif + } + } + timer_thread_state= NOT_RUNNING; /* Mark thread ended */ + mysql_cond_signal(&COND_timer); /* signal end_thr_timer() */ + mysql_mutex_unlock(&LOCK_timer); + my_thread_end(); + pthread_exit(0); + return 0; /* Impossible */ +} + + +/**************************************************************************** + Testing of thr_timer (when compiled with -DMAIN) +***************************************************************************/ + +#ifdef MAIN + +static mysql_cond_t COND_thread_count; +static mysql_mutex_t LOCK_thread_count; +static uint thread_count, benchmark_runs, test_to_run= 1; + +static void send_signal(void *arg) +{ + struct st_my_thread_var *current_my_thread_var= arg; +#if defined(MAIN) + printf("sending signal\n"); fflush(stdout); +#endif + mysql_mutex_lock(¤t_my_thread_var->mutex); + mysql_cond_signal(¤t_my_thread_var->suspend); + mysql_mutex_unlock(¤t_my_thread_var->mutex); +} + + +static void run_thread_test(int param) +{ + int i,wait_time,retry; + my_hrtime_t start_time; + thr_timer_t timer_data; + struct st_my_thread_var *current_my_thread_var; + DBUG_ENTER("run_thread_test"); + + current_my_thread_var= my_thread_var; + thr_timer_init(&timer_data, send_signal, current_my_thread_var); + + for (i=1 ; i <= 10 ; i++) + { + wait_time=param ? 11-i : i; + start_time= my_hrtime(); + + mysql_mutex_lock(¤t_my_thread_var->mutex); + if (thr_timer_settime(&timer_data, wait_time * 1000000)) + { + printf("Thread: %s timers aborted\n",my_thread_name()); + break; + } + if (wait_time == 3) + { + printf("Thread: %s Simulation of no timer needed\n",my_thread_name()); + fflush(stdout); + } + else + { + for (retry=0 ; !timer_data.expired && retry < 10 ; retry++) + { + printf("Thread: %s Waiting %d sec\n",my_thread_name(),wait_time); + mysql_cond_wait(¤t_my_thread_var->suspend, + ¤t_my_thread_var->mutex); + + } + if (!timer_data.expired) + { + printf("Thread: %s didn't get an timer. Aborting!\n", + my_thread_name()); + break; + } + } + mysql_mutex_unlock(¤t_my_thread_var->mutex); + printf("Thread: %s Slept for %g (%d) sec\n",my_thread_name(), + (int) (my_hrtime().val-start_time.val)/1000000.0, wait_time); + fflush(stdout); + thr_timer_end(&timer_data); + fflush(stdout); + } + DBUG_VOID_RETURN; +} + + +static void run_thread_benchmark(int param) +{ + int i; + struct st_my_thread_var *current_my_thread_var; + thr_timer_t timer_data; + DBUG_ENTER("run_thread_benchmark"); + + current_my_thread_var= my_thread_var; + thr_timer_init(&timer_data, send_signal, current_my_thread_var); + + for (i=1 ; i <= param ; i++) + { + if (thr_timer_settime(&timer_data, 1000000)) + { + printf("Thread: %s timers aborted\n",my_thread_name()); + break; + } + thr_timer_end(&timer_data); + } + DBUG_VOID_RETURN; +} + + +#ifdef HAVE_TIMER_CREATE + +/* Test for benchmarking posix timers against thr_timer */ + +#ifndef sigev_notify_thread_id +#define sigev_notify_thread_id _sigev_un._tid +#endif + +static void run_timer_benchmark(int param) +{ + int i; + timer_t timerid; + struct sigevent sigev; + pid_t thread_id= (pid_t) syscall(SYS_gettid); + DBUG_ENTER("run_timer_benchmark"); + + /* Setup a signal that will never be signaled */ + sigev.sigev_value.sival_ptr= 0; + sigev.sigev_signo= SIGRTMIN; /* First free signal */ + sigev.sigev_notify= SIGEV_SIGNAL | SIGEV_THREAD_ID; + sigev.sigev_notify_thread_id= thread_id; + + if (timer_create(CLOCK_MONOTONIC, &sigev, &timerid)) + { + printf("Could not create timer\n"); + exit(1); + } + + for (i=1 ; i <= param ; i++) + { + struct itimerspec abstime; + abstime.it_interval.tv_sec= 0; + abstime.it_interval.tv_nsec= 0; + abstime.it_value.tv_sec= 1; + abstime.it_value.tv_nsec= 0; + + if (timer_settime(timerid, 0, &abstime, NULL)) + { + printf("Thread: %s timers aborted\n",my_thread_name()); + break; + } + abstime.it_interval.tv_sec= 0; + abstime.it_interval.tv_nsec= 0; + abstime.it_value.tv_sec= 0; + abstime.it_value.tv_nsec= 0; + timer_settime(timerid, 0, &abstime, NULL); + } + timer_delete(timerid); + DBUG_VOID_RETURN; +} +#endif /* HAVE_TIMER_CREATE */ + + +static void *start_thread(void *arg) +{ + my_thread_init(); + printf("Thread %d (%s) started\n",*((int*) arg),my_thread_name()); + fflush(stdout); + + switch (test_to_run) { + case 1: + run_thread_test(*((int*) arg)); + break; + case 2: + run_thread_benchmark(benchmark_runs); + break; + case 3: +#ifdef HAVE_TIMER_CREATE + run_timer_benchmark(benchmark_runs); +#endif + break; + } + free((uchar*) arg); + mysql_mutex_lock(&LOCK_thread_count); + thread_count--; + mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */ + mysql_mutex_unlock(&LOCK_thread_count); + my_thread_end(); + return 0; +} + + +/* Start a lot of threads that will run with timers */ + +static void run_test() +{ + pthread_t tid; + pthread_attr_t thr_attr; + int i,*param,error; + DBUG_ENTER("run_test"); + + if (init_thr_timer(5)) + { + printf("Can't initialize timers\n"); + exit(1); + } + + mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST); + mysql_cond_init(0, &COND_thread_count, NULL); + + thr_setconcurrency(3); + pthread_attr_init(&thr_attr); + pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); + printf("Main thread: %s\n",my_thread_name()); + for (i=0 ; i < 2 ; i++) + { + param=(int*) malloc(sizeof(int)); + *param= i; + mysql_mutex_lock(&LOCK_thread_count); + if ((error= mysql_thread_create(0, + &tid, &thr_attr, start_thread, + (void*) param))) + { + printf("Can't create thread %d, error: %d\n",i,error); + exit(1); + } + thread_count++; + mysql_mutex_unlock(&LOCK_thread_count); + } + + pthread_attr_destroy(&thr_attr); + mysql_mutex_lock(&LOCK_thread_count); + while (thread_count) + { + mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); + } + mysql_mutex_unlock(&LOCK_thread_count); + DBUG_ASSERT(timer_queue.elements == 1); + end_thr_timer(); + printf("Test succeeded\n"); + DBUG_VOID_RETURN; +} + + +int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) +{ + MY_INIT(argv[0]); + + if (argc > 1 && argv[1][0] == '-') + { + switch (argv[1][1]) { + case '#': + test_to_run= 1; + DBUG_PUSH(argv[1]+2); + break; + case 'b': + test_to_run= 2; + benchmark_runs= atoi(argv[1]+2); + break; + case 't': + test_to_run= 3; + benchmark_runs= atoi(argv[1]+2); + break; + } + } + if (!benchmark_runs) + benchmark_runs= 1000000; + + run_test(); + my_end(1); + return 0; +} + +#endif /* MAIN */ diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index a148e191204..faad08ab6d9 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -33,7 +33,7 @@ set @had_db_table= @@warning_count != 0; CREATE TABLE IF NOT EXISTS host ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges'; -CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) DEFAULT 0 NOT NULL, plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, authentication_string TEXT NOT NULL, password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, default_role char(80) binary DEFAULT '' NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; +CREATE TABLE IF NOT EXISTS user ( Host char(60) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, max_user_connections int(11) DEFAULT 0 NOT NULL, plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, authentication_string TEXT NOT NULL, password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, default_role char(80) binary DEFAULT '' NOT NULL, max_statement_time decimal(12,6) DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges'; -- Remember for later if user table already existed set @had_user_table= @@warning_count != 0; @@ -80,7 +80,7 @@ CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsign CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; -CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(141) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment text collate utf8_bin NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures'; +CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob NOT NULL, body longblob NOT NULL, definer char(141) collate utf8_bin DEFAULT '' NOT NULL, created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'IGNORE_BAD_TABLE_OPTIONS', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE', 'NO_ENGINE_SUBSTITUTION', 'PAD_CHAR_TO_FULL_LENGTH') DEFAULT '' NOT NULL, comment text collate utf8_bin NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures'; CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(80) binary DEFAULT '' NOT NULL, Routine_name char(64) COLLATE utf8_general_ci DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(141) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; diff --git a/scripts/mysql_system_tables_data.sql b/scripts/mysql_system_tables_data.sql index 46c96ef4bb1..075aafd5e3b 100644 --- a/scripts/mysql_system_tables_data.sql +++ b/scripts/mysql_system_tables_data.sql @@ -39,10 +39,10 @@ DROP TABLE tmp_db; -- Fill "user" table with default users allowing root access -- from local machine if "user" table didn't exist before CREATE TEMPORARY TABLE tmp_user LIKE user; -INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N', 'N',''); -REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','' FROM dual WHERE @current_hostname != 'localhost'; -REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N', ''); -REPLACE INTO tmp_user VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N', ''); +INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N', 'N','', 0); +REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0 FROM dual WHERE @current_hostname != 'localhost'; +REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N','',0); +REPLACE INTO tmp_user VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','N','N', '', 0); INSERT INTO tmp_user (host,user) VALUES ('localhost',''); INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE @current_hostname != 'localhost'; INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0; diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 3ec2d94673a..96e4103b5bd 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -632,6 +632,7 @@ ALTER TABLE user ADD plugin char(64) DEFAULT '', ADD authentication_string TEXT ALTER TABLE user ADD password_expired ENUM('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; ALTER TABLE user ADD is_role enum('N', 'Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL; ALTER TABLE user ADD default_role char(80) binary DEFAULT '' NOT NULL; +ALTER TABLE user ADD max_statement_time decimal(12,6) DEFAULT 0 NOT NULL; ALTER TABLE user MODIFY plugin char(64) CHARACTER SET latin1 DEFAULT '' NOT NULL, MODIFY authentication_string TEXT NOT NULL; -- Somewhere above, we ran ALTER TABLE user .... CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin. -- we want password_expired column to have collation utf8_general_ci. diff --git a/sql/lex.h b/sql/lex.h index 10a52160cf0..affb8032193 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -363,6 +363,7 @@ static SYMBOL symbols[] = { { "MAX_QUERIES_PER_HOUR", SYM(MAX_QUERIES_PER_HOUR)}, { "MAX_ROWS", SYM(MAX_ROWS)}, { "MAX_SIZE", SYM(MAX_SIZE_SYM)}, + { "MAX_STATEMENT_TIME", SYM(MAX_STATEMENT_TIME_SYM)}, { "MAX_UPDATES_PER_HOUR", SYM(MAX_UPDATES_PER_HOUR)}, { "MAX_USER_CONNECTIONS", SYM(MAX_USER_CONNECTIONS_SYM)}, { "MAXVALUE", SYM(MAX_VALUE_SYM)}, diff --git a/sql/log_event.cc b/sql/log_event.cc index ee35acadd9b..e5183b208b2 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -473,6 +473,7 @@ inline bool unexpected_error_code(int unexpected_error) case ER_NET_READ_ERROR: case ER_NET_ERROR_ON_WRITE: case ER_QUERY_INTERRUPTED: + case ER_STATEMENT_TIMEOUT: case ER_CONNECTION_KILLED: case ER_SERVER_SHUTDOWN: case ER_NEW_ABORTING_CONNECTION: diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 899140f7d71..ec5f66cac45 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2106,6 +2106,9 @@ void clean_up(bool print_message) sp_cache_end(); free_status_vars(); end_thr_alarm(1); /* Free allocated memory */ +#ifndef EMBEDDED_LIBRARY + end_thr_timer(); +#endif my_free_open_file_info(); if (defaults_argv) free_defaults(defaults_argv); @@ -4746,6 +4749,14 @@ static int init_server_components() my_rnd_init(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2); setup_fpu(); init_thr_lock(); +#ifndef EMBEDDED_LIBRARY + if (init_thr_timer(thread_scheduler->max_threads + extra_max_connections)) + { + fprintf(stderr, "Can't initialize timers\n"); + unireg_abort(1); + } +#endif + my_uuid_init((ulong) (my_rnd(&sql_rand))*12345,12345); #ifdef HAVE_REPLICATION init_slave_list(); @@ -5361,9 +5372,6 @@ int mysqld_main(int argc, char **argv) } #endif - if (WSREP_ON) - wsrep_filter_new_cluster (&argc, argv); - orig_argc= argc; orig_argv= argv; my_getopt_use_args_separator= TRUE; @@ -7341,6 +7349,13 @@ struct my_option my_long_options[]= {"table_cache", 0, "Deprecated; use --table-open-cache instead.", &tc_size, &tc_size, 0, GET_ULONG, REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0}, +#ifdef WITH_WSREP + {"wsrep-new-cluster", 0, "Bootstrap a cluster. It works by overriding the " + "current value of wsrep_cluster_address. It is recommended not to add this " + "option to the config file as this will trigger bootstrap on every server " + "start.", &wsrep_new_cluster, &wsrep_new_cluster, 0, GET_BOOL, NO_ARG, + 0, 0, 0, 0, 0, 0}, +#endif /* The following options exist in 5.6 but not in 10.0 */ MYSQL_TO_BE_IMPLEMENTED_OPTION("default-tmp-storage-engine"), @@ -8073,6 +8088,7 @@ SHOW_VAR status_vars[]= { {"Handler_write", (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS}, {"Key", (char*) &show_default_keycache, SHOW_FUNC}, {"Last_query_cost", (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS}, + {"max_statement_time_exceeded", (char*) offsetof(STATUS_VAR, max_statement_time_exceeded), SHOW_LONG_STATUS}, {"Max_used_connections", (char*) &max_used_connections, SHOW_LONG}, {"Memory_used", (char*) offsetof(STATUS_VAR, memory_used), SHOW_LONGLONG_STATUS}, {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_NOFLUSH}, @@ -9141,7 +9157,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr) debug_assert_if_crashed_table= 1; global_system_variables.long_query_time= (ulonglong) - (global_system_variables.long_query_time_double * 1e6); + (global_system_variables.long_query_time_double * 1e6 + 0.1); + global_system_variables.max_statement_time= (ulonglong) + (global_system_variables.max_statement_time_double * 1e6 + 0.1); if (opt_short_log_format) opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT; diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 32cdbe138b2..7042669a363 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7110,3 +7110,5 @@ ER_IT_IS_A_VIEW 42S02 eng "'%-.192s' is a view" ER_SLAVE_SKIP_NOT_IN_GTID eng "When using GTID, @@sql_slave_skip_counter can not be used. Instead, setting @@gtid_slave_pos explicitly can be used to skip to after a given GTID position." +ER_STATEMENT_TIMEOUT 70100 + eng "Query execution was interrupted (max_statement_time exceeded)" diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index 3fadbcd088f..61e2830e82e 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -172,6 +172,10 @@ extern "C" sig_handler handle_fatal_signal(int sig) case KILL_QUERY_HARD: kreason= "KILL_QUERY"; break; + case KILL_TIMEOUT: + case KILL_TIMEOUT_HARD: + kreason= "KILL_TIMEOUT"; + break; case KILL_SYSTEM_THREAD: case KILL_SYSTEM_THREAD_HARD: kreason= "KILL_SYSTEM_THREAD"; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 5e30b148ad7..8e976f0f579 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -211,8 +211,10 @@ static char *safe_str(char *str) static const char *safe_str(const char *str) { return str ? str : ""; } +#ifndef NO_EMBEDDED_ACCESS_CHECKS static size_t safe_strlen(const char *str) { return str ? strlen(str) : 0; } +#endif /* Classes */ @@ -709,6 +711,8 @@ bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, char *username, #define ROLE_ASSIGN_COLUMN_IDX 43 #define DEFAULT_ROLE_COLUMN_IDX 44 +#define MAX_STATEMENT_TIME_COLUMN_IDX 45 + /* various flags valid for ACL_USER */ #define IS_ROLE (1L << 0) /* Flag to mark that a ROLE is on the recursive DEPTH_FIRST_SEARCH stack */ @@ -1272,6 +1276,8 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) user.sort= get_sort(2, user.host.hostname, user.user.str); user.hostname_length= safe_strlen(user.host.hostname); + user.user_resource.user_conn= 0; + user.user_resource.max_statement_time= 0.0; /* Starting from 4.0.2 we have more fields */ if (table->s->fields >= 31) @@ -1331,6 +1337,14 @@ static bool acl_load(THD *thd, TABLE_LIST *tables) fix_user_plugin_ptr(&user); } } + + if (table->s->fields > MAX_STATEMENT_TIME_COLUMN_IDX) + { + /* Starting from 10.1.1 we can have max_statement_time */ + ptr= get_field(thd->mem_root, + table->field[MAX_STATEMENT_TIME_COLUMN_IDX]); + user.user_resource.max_statement_time= ptr ? atof(ptr) : 0.0; + } } else { @@ -2041,6 +2055,8 @@ static void acl_update_user(const char *user, const char *host, acl_user->user_resource.conn_per_hour= mqh->conn_per_hour; if (mqh->specified_limits & USER_RESOURCES::USER_CONNECTIONS) acl_user->user_resource.user_conn= mqh->user_conn; + if (mqh->specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME) + acl_user->user_resource.max_statement_time= mqh->max_statement_time; if (ssl_type != SSL_TYPE_NOT_SPECIFIED) { acl_user->ssl_type= ssl_type; @@ -3393,8 +3409,6 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo, if (table->s->fields >= 36 && (mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS)) table->field[next_field+3]->store((longlong) mqh.user_conn, FALSE); - mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour; - next_field+= 4; if (table->s->fields >= 41) { @@ -3415,7 +3429,16 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo, table->field[next_field]->reset(); table->field[next_field + 1]->reset(); } + + if (table->s->fields > MAX_STATEMENT_TIME_COLUMN_IDX) + { + if (mqh.specified_limits & USER_RESOURCES::MAX_STATEMENT_TIME) + table->field[MAX_STATEMENT_TIME_COLUMN_IDX]-> + store(mqh.max_statement_time); + } } + mqh_used= (mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour || + mqh.user_conn || mqh.max_statement_time != 0.0); /* table format checked earlier */ if (handle_as_role) @@ -7508,6 +7531,21 @@ static void add_user_option(String *grant, long value, const char *name, } } + +static void add_user_option(String *grant, double value, const char *name) +{ + if (value != 0.0 ) + { + char buff[FLOATING_POINT_BUFFER]; + size_t len; + grant->append(' '); + grant->append(name, strlen(name)); + grant->append(' '); + len= my_fcvt(value, 6, buff, NULL); + grant->append(buff, len); + } +} + static const char *command_array[]= { "SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "RELOAD", @@ -7890,7 +7928,8 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry, (acl_user->user_resource.questions || acl_user->user_resource.updates || acl_user->user_resource.conn_per_hour || - acl_user->user_resource.user_conn)) + acl_user->user_resource.user_conn || + acl_user->user_resource.max_statement_time != 0.0)) { global.append(STRING_WITH_LEN(" WITH")); if (want_access & GRANT_ACL) @@ -7903,6 +7942,8 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry, "MAX_CONNECTIONS_PER_HOUR", false); add_user_option(&global, acl_user->user_resource.user_conn, "MAX_USER_CONNECTIONS", true); + add_user_option(&global, acl_user->user_resource.max_statement_time, + "MAX_STATEMENT_TIME"); } } @@ -12232,12 +12273,22 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) if ((acl_user->user_resource.questions || acl_user->user_resource.updates || acl_user->user_resource.conn_per_hour || - acl_user->user_resource.user_conn || max_user_connections_checking) && + acl_user->user_resource.user_conn || + acl_user->user_resource.max_statement_time != 0.0 || + max_user_connections_checking) && get_or_create_user_conn(thd, (opt_old_style_user_limits ? sctx->user : sctx->priv_user), (opt_old_style_user_limits ? sctx->host_or_ip : sctx->priv_host), &acl_user->user_resource)) DBUG_RETURN(1); // The error is set by get_or_create_user_conn() + + if (acl_user->user_resource.max_statement_time != 0.0) + { + thd->variables.max_statement_time_double= + acl_user->user_resource.max_statement_time; + thd->variables.max_statement_time= + (thd->variables.max_statement_time_double * 1e6 + 0.1); + } } else sctx->skip_grants(); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index dde0a9a2f7a..9b899464c4b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -861,6 +861,23 @@ bool Drop_table_error_handler::handle_condition(THD *thd, } +/** + Send timeout to thread. + + Note that this is always safe as the thread will always remove it's + timeouts at end of query (and thus before THD is destroyed) +*/ + +extern "C" void thd_kill_timeout(THD* thd) +{ + thd->status_var.max_statement_time_exceeded++; + mysql_mutex_lock(&thd->LOCK_thd_data); + /* Kill queries that can't cause data corruptions */ + thd->awake(KILL_TIMEOUT); + mysql_mutex_unlock(&thd->LOCK_thd_data); +} + + THD::THD(bool is_wsrep_applier) :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION, /* statement id */ 0), @@ -1058,6 +1075,8 @@ THD::THD(bool is_wsrep_applier) protocol_text.init(this); protocol_binary.init(this); + thr_timer_init(&query_timer, (void (*)(void*)) thd_kill_timeout, this); + tablespace_op=FALSE; /* @@ -1373,6 +1392,7 @@ extern "C" THD *_current_thd_noinline(void) return my_pthread_getspecific_ptr(THD*,THR_THD); } #endif + /* Init common variables that has to be reset on start and on change_user */ @@ -1779,6 +1799,7 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, This is normally called from another thread's THD object. @note Do always call this while holding LOCK_thd_data. + NOT_KILLED is used to awake a thread for a slave */ void THD::awake(killed_state state_to_set) @@ -1790,6 +1811,13 @@ void THD::awake(killed_state state_to_set) print_aborted_warning(3, "KILLED"); + /* + Don't degrade killed state, for example from a KILL_CONNECTION to + STATEMENT TIMEOUT + */ + if (killed >= KILL_CONNECTION) + state_to_set= killed; + /* Set the 'killed' flag of 'this', which is the target THD object. */ killed= state_to_set; @@ -1821,6 +1849,7 @@ void THD::awake(killed_state state_to_set) mysql_mutex_lock(&mysys_var->mutex); if (!system_thread) // Don't abort locks mysys_var->abort=1; + /* This broadcast could be up in the air if the victim thread exits the cond in the time between read and broadcast, but that is @@ -1989,6 +2018,9 @@ int killed_errno(killed_state killed) case KILL_QUERY: case KILL_QUERY_HARD: DBUG_RETURN(ER_QUERY_INTERRUPTED); + case KILL_TIMEOUT: + case KILL_TIMEOUT_HARD: + DBUG_RETURN(ER_STATEMENT_TIMEOUT); case KILL_SERVER: case KILL_SERVER_HARD: DBUG_RETURN(ER_SERVER_SHUTDOWN); diff --git a/sql/sql_class.h b/sql/sql_class.h index cab2968a62b..4ba2901d0cc 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -37,6 +37,7 @@ #include "violite.h" /* vio_is_connected */ #include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA, THR_LOCK_INFO */ +#include "thr_timer.h" #include <mysql/psi/mysql_stage.h> #include <mysql/psi/mysql_statement.h> #include <mysql/psi/mysql_idle.h> @@ -449,17 +450,19 @@ enum killed_state */ ABORT_QUERY= 6, ABORT_QUERY_HARD= 7, + KILL_TIMEOUT= 8, + KILL_TIMEOUT_HARD= 9, /* All of the following killed states will kill the connection KILL_CONNECTION must be the first of these and it must start with an even number (becasue of HARD bit)! */ - KILL_CONNECTION= 8, - KILL_CONNECTION_HARD= 9, - KILL_SYSTEM_THREAD= 10, - KILL_SYSTEM_THREAD_HARD= 11, - KILL_SERVER= 12, - KILL_SERVER_HARD= 13 + KILL_CONNECTION= 10, + KILL_CONNECTION_HARD= 11, + KILL_SYSTEM_THREAD= 12, + KILL_SYSTEM_THREAD_HARD= 13, + KILL_SERVER= 14, + KILL_SERVER_HARD= 15 }; extern int killed_errno(killed_state killed); @@ -508,6 +511,7 @@ typedef struct system_variables ulonglong max_heap_table_size; ulonglong tmp_table_size; ulonglong long_query_time; + ulonglong max_statement_time; ulonglong optimizer_switch; sql_mode_t sql_mode; ///< which non-standard SQL behaviour should be enabled sql_mode_t old_behavior; ///< which old SQL behaviour should be enabled @@ -644,8 +648,7 @@ typedef struct system_variables my_bool wsrep_causal_reads; uint wsrep_sync_wait; ulong wsrep_retry_autocommit; - - double long_query_time_double; + double long_query_time_double, max_statement_time_double; my_bool pseudo_slave_mode; @@ -734,6 +737,7 @@ typedef struct system_status_var ulong empty_queries; ulong access_denied_errors; ulong lost_connections; + ulong max_statement_time_exceeded; /* Number of statements sent from the client */ @@ -3779,6 +3783,34 @@ public: void* wsrep_apply_format; char wsrep_info[128]; /* string for dynamic proc info */ #endif /* WITH_WSREP */ + + /* Handling of timeouts for commands */ + thr_timer_t query_timer; +public: + void set_query_timer() + { +#ifndef EMBEDDED_LIBRARY + /* + Don't start a query timer if + - If timeouts are not set + - if we are in a stored procedure or sub statement + - If this is a slave thread + - If we already have set a timeout (happens when running prepared + statements that calls mysql_execute_command()) + */ + if (!variables.max_statement_time || spcont || in_sub_stmt || + slave_thread || query_timer.expired == 0) + return; + thr_timer_settime(&query_timer, variables.max_statement_time); +#endif + } + void reset_query_timer() + { +#ifndef EMBEDDED_LIBRARY + if (!query_timer.expired) + thr_timer_end(&query_timer); +#endif + } }; diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 0065edcc14d..89a90f41697 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -101,7 +101,6 @@ int get_or_create_user_conn(THD *thd, const char *user, end: mysql_mutex_unlock(&LOCK_user_conn); return return_val; - } @@ -437,6 +436,7 @@ void init_user_stats(USER_STATS *user_stats, ulonglong rollback_trans, ulonglong denied_connections, ulonglong lost_connections, + ulonglong max_statement_time_exceeded, ulonglong access_denied_errors, ulonglong empty_queries) { @@ -467,6 +467,7 @@ void init_user_stats(USER_STATS *user_stats, user_stats->rollback_trans= rollback_trans; user_stats->denied_connections= denied_connections; user_stats->lost_connections= lost_connections; + user_stats->max_statement_time_exceeded= max_statement_time_exceeded; user_stats->access_denied_errors= access_denied_errors; user_stats->empty_queries= empty_queries; DBUG_VOID_RETURN; @@ -496,6 +497,7 @@ void add_user_stats(USER_STATS *user_stats, ulonglong rollback_trans, ulonglong denied_connections, ulonglong lost_connections, + ulonglong max_statement_time_exceeded, ulonglong access_denied_errors, ulonglong empty_queries) { @@ -519,6 +521,7 @@ void add_user_stats(USER_STATS *user_stats, user_stats->rollback_trans+= rollback_trans; user_stats->denied_connections+= denied_connections; user_stats->lost_connections+= lost_connections; + user_stats->max_statement_time_exceeded+= max_statement_time_exceeded; user_stats->access_denied_errors+= access_denied_errors; user_stats->empty_queries+= empty_queries; } @@ -644,6 +647,7 @@ static bool increment_count_by_name(const char *name, size_t name_length, 0, 0, // commit and rollback trans thd->status_var.access_denied_errors, 0, // lost connections + 0, // max query timeouts 0, // access denied errors 0); // empty queries @@ -756,6 +760,7 @@ static void update_global_user_stats_with_user(THD *thd, /* The following can only contain 0 or 1 and then connection ends */ user_stats->denied_connections+= thd->status_var.access_denied_errors; user_stats->lost_connections+= thd->status_var.lost_connections; + user_stats->max_statement_time_exceeded+= thd->status_var.max_statement_time_exceeded; } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 6aa76ebf9c7..e8e02197a1b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2697,6 +2697,9 @@ mysql_execute_command(THD *thd) goto error; } + /* Start timeouts */ + thd->set_query_timer(); + switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: @@ -5492,6 +5495,7 @@ error: finish: + thd->reset_query_timer(); DBUG_ASSERT(!thd->in_active_multi_stmt_transaction() || thd->in_multi_stmt_transaction_mode()); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index ec7d4979a4e..a5c305f9448 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3198,6 +3198,7 @@ static int aggregate_user_stats(HASH *all_user_stats, HASH *agg_user_stats) user->other_commands, user->commit_trans, user->rollback_trans, user->denied_connections, user->lost_connections, + user->max_statement_time_exceeded, user->access_denied_errors, user->empty_queries); if (my_hash_insert(agg_user_stats, (uchar*) agg_user)) @@ -3223,6 +3224,7 @@ static int aggregate_user_stats(HASH *all_user_stats, HASH *agg_user_stats) user->other_commands, user->commit_trans, user->rollback_trans, user->denied_connections, user->lost_connections, + user->max_statement_time_exceeded, user->access_denied_errors, user->empty_queries); } } @@ -3278,6 +3280,7 @@ int send_user_stats(THD* thd, HASH *all_user_stats, TABLE *table) table->field[j++]->store((longlong)user_stats->lost_connections, TRUE); table->field[j++]->store((longlong)user_stats->access_denied_errors, TRUE); table->field[j++]->store((longlong)user_stats->empty_queries, TRUE); + table->field[j++]->store((longlong)user_stats->max_statement_time_exceeded, TRUE); if (schema_table_store_record(thd, table)) { DBUG_PRINT("error", ("store record error")); @@ -7410,6 +7413,7 @@ ST_FIELD_INFO user_stats_fields_info[]= {"LOST_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Lost_connections",SKIP_OPEN_TABLE}, {"ACCESS_DENIED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Access_denied",SKIP_OPEN_TABLE}, {"EMPTY_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Empty_queries",SKIP_OPEN_TABLE}, + {"MAX_STATEMENT_TIME_EXCEEDED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Max_statement_time_exceeded",SKIP_OPEN_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} }; @@ -7438,6 +7442,7 @@ ST_FIELD_INFO client_stats_fields_info[]= {"LOST_CONNECTIONS", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Lost_connections",SKIP_OPEN_TABLE}, {"ACCESS_DENIED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Access_denied",SKIP_OPEN_TABLE}, {"EMPTY_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Empty_queries",SKIP_OPEN_TABLE}, + {"MAX_STATEMENT_TIME_EXCEEDED", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, "Max_statement_time_exceeded",SKIP_OPEN_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, 0} }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 78a0eff935a..df9c59e5deb 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1304,6 +1304,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token MAX_SIZE_SYM %token MAX_SYM /* SQL-2003-N */ %token MAX_UPDATES_PER_HOUR +%token MAX_STATEMENT_TIME_SYM %token MAX_USER_CONNECTIONS_SYM %token MAX_VALUE_SYM /* SQL-2003-N */ %token MEDIUMBLOB @@ -14266,6 +14267,7 @@ keyword_sp: | MAX_CONNECTIONS_PER_HOUR {} | MAX_QUERIES_PER_HOUR {} | MAX_SIZE_SYM {} + | MAX_STATEMENT_TIME_SYM {} | MAX_UPDATES_PER_HOUR {} | MAX_USER_CONNECTIONS_SYM {} | MEDIUM_SYM {} @@ -15620,6 +15622,12 @@ grant_option: lex->mqh.user_conn= $2; lex->mqh.specified_limits|= USER_RESOURCES::USER_CONNECTIONS; } + | MAX_STATEMENT_TIME_SYM NUM_literal + { + LEX *lex=Lex; + lex->mqh.max_statement_time= $2->val_real(); + lex->mqh.specified_limits|= USER_RESOURCES::MAX_STATEMENT_TIME; + } ; begin: diff --git a/sql/structs.h b/sql/structs.h index da8d4beb754..d02301e4350 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -232,12 +232,15 @@ typedef struct user_resources { connections allowed */ int user_conn; + /* Max query timeout */ + double max_statement_time; + /* Values of this enum and specified_limits member are used by the parser to store which user limits were specified in GRANT statement. */ enum {QUERIES_PER_HOUR= 1, UPDATES_PER_HOUR= 2, CONNECTIONS_PER_HOUR= 4, - USER_CONNECTIONS= 8}; + USER_CONNECTIONS= 8, MAX_STATEMENT_TIME= 16}; uint specified_limits; } USER_RESOURCES; @@ -293,7 +296,7 @@ typedef struct st_user_stats ha_rows rows_updated, rows_deleted, rows_inserted; ulonglong select_commands, update_commands, other_commands; ulonglong commit_trans, rollback_trans; - ulonglong denied_connections, lost_connections; + ulonglong denied_connections, lost_connections, max_statement_time_exceeded; ulonglong access_denied_errors; ulonglong empty_queries; } USER_STATS; @@ -331,6 +334,7 @@ init_user_stats(USER_STATS *user_stats, ulonglong rollback_trans, ulonglong denied_connections, ulonglong lost_connections, + ulonglong max_statement_time_exceeded, ulonglong access_denied_errors, ulonglong empty_queries); @@ -357,6 +361,7 @@ add_user_stats(USER_STATS *user_stats, ulonglong rollback_trans, ulonglong denied_connections, ulonglong lost_connections, + ulonglong max_statement_time_exceeded, ulonglong access_denied_errors, ulonglong empty_queries); diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 0fab83be90d..b9304403ee5 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1176,6 +1176,29 @@ static Sys_var_double Sys_long_query_time( NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(update_cached_long_query_time)); + +static bool update_cached_max_statement_time(sys_var *self, THD *thd, + enum_var_type type) +{ + if (type == OPT_SESSION) + thd->variables.max_statement_time= + double2ulonglong(thd->variables.max_statement_time_double * 1e6); + else + global_system_variables.max_statement_time= + double2ulonglong(global_system_variables.max_statement_time_double * 1e6); + return false; +} + +static Sys_var_double Sys_max_statement_time( + "max_statement_time", + "A SELECT query that have taken more than max_statement_time seconds " + "will be aborted. The argument will be treated as a decimal value " + "with microsecond precision. A value of 0 (default) means no timeout", + SESSION_VAR(max_statement_time_double), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, LONG_TIMEOUT), DEFAULT(0), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(update_cached_max_statement_time)); + static bool fix_low_prio_updates(sys_var *self, THD *thd, enum_var_type type) { if (type == OPT_SESSION) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 2897bb3fb69..938ec243f61 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -82,6 +82,7 @@ my_bool wsrep_restart_slave_activated = 0; // node has dropped, and slave // restart will be needed my_bool wsrep_slave_UK_checks = 0; // slave thread does UK checks my_bool wsrep_slave_FK_checks = 0; // slave thread does FK checks +bool wsrep_new_cluster = false; // Bootstrap the cluster ? /* * End configuration options */ @@ -886,37 +887,6 @@ void wsrep_stop_replication(THD *thd) return; } -/* This one is set to true when --wsrep-new-cluster is found in the command - * line arguments */ -static my_bool wsrep_new_cluster= FALSE; -#define WSREP_NEW_CLUSTER "--wsrep-new-cluster" -/* Finds and hides --wsrep-new-cluster from the arguments list - * by moving it to the end of the list and decrementing argument count */ -void wsrep_filter_new_cluster (int* argc, char* argv[]) -{ - int i; - for (i= *argc - 1; i > 0; i--) - { - /* make a copy of the argument to convert possible underscores to hyphens. - * the copy need not to be longer than WSREP_NEW_CLUSTER option */ - char arg[sizeof(WSREP_NEW_CLUSTER) + 1]= { 0, }; - strncpy(arg, argv[i], sizeof(arg) - 1); - char* underscore(arg); - while (NULL != (underscore= strchr(underscore, '_'))) *underscore= '-'; - - if (!strcmp(arg, WSREP_NEW_CLUSTER)) - { - wsrep_new_cluster= TRUE; - *argc -= 1; - /* preserve the order of remaining arguments AND - * preserve the original argument pointers - just in case */ - char* wnc= argv[i]; - memmove(&argv[i], &argv[i + 1], (*argc - i)*sizeof(argv[i])); - argv[*argc]= wnc; /* this will be invisible to the rest of the program */ - } - } -} - bool wsrep_start_replication() { wsrep_status_t rcode; @@ -939,11 +909,16 @@ bool wsrep_start_replication() return true; } - bool const bootstrap(TRUE == wsrep_new_cluster); - wsrep_new_cluster= FALSE; + bool const bootstrap= wsrep_new_cluster; WSREP_INFO("Start replication"); + if (wsrep_new_cluster) + { + WSREP_INFO("'wsrep-new-cluster' option used, bootstrapping the cluster"); + wsrep_new_cluster= false; + } + if ((rcode = wsrep->connect(wsrep, wsrep_cluster_name, wsrep_cluster_address, diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h index bc78d2beecf..67f26548043 100644 --- a/sql/wsrep_mysqld.h +++ b/sql/wsrep_mysqld.h @@ -87,6 +87,7 @@ extern my_bool wsrep_restart_slave_activated; extern my_bool wsrep_slave_FK_checks; extern my_bool wsrep_slave_UK_checks; extern ulong wsrep_running_threads; +extern bool wsrep_new_cluster; enum enum_wsrep_OSU_method { WSREP_OSU_TOI, WSREP_OSU_RSU }; enum enum_wsrep_sync_wait { @@ -112,11 +113,6 @@ extern const char* wsrep_provider_version; extern const char* wsrep_provider_vendor; int wsrep_show_status(THD *thd, SHOW_VAR *var, char *buff); - -/* Filters out --wsrep-new-cluster oprtion from argv[] - * should be called in the very beginning of main() */ -void wsrep_filter_new_cluster (int* argc, char* argv[]); - int wsrep_init(); void wsrep_deinit(bool free_options); void wsrep_recover(); @@ -328,7 +324,6 @@ int wsrep_create_trigger_query(THD *thd, uchar** buf, size_t* buf_len); #define wsrep_stop_replication(X) do { } while(0) #define wsrep_inited (0) #define wsrep_deinit(X) do { } while(0) -#define wsrep_filter_new_cluster(X,Y) do { } while(0) #define wsrep_recover() do { } while(0) #define wsrep_slave_threads (1) |