diff --git a/client/mysql.cc b/client/mysql.cc index 93ebf4a3e39..df38f31f949 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -312,7 +312,7 @@ static int com_quit(String *str, char *), com_go(String *str, char *), com_notee(String *str, char *), com_charset(String *str, char *), com_prompt(String *str, char *), com_delimiter(String *str, char *), com_warnings(String *str, char *), com_nowarnings(String *str, char *), - com_resetconnection(String *str, char *); + com_resetconnection(String *str, char *), com_attr(String *str, char *); #ifdef USE_POPEN static int com_nopager(String *str, char *), com_pager(String *str, char *), @@ -387,6 +387,7 @@ static COMMANDS commands[] = { {"prompt", 'R', com_prompt, 1, "Change your mysql prompt."}, {"quit", 'q', com_quit, 0, "Quit mysql."}, {"rehash", '#', com_rehash, 0, "Rebuild completion hash."}, + {"setattr", 'z', com_attr, 1, "Set query attribute."}, {"source", '.', com_source, 1, "Execute an SQL script file. Takes a file name as an argument."}, {"status", 's', com_status, 0, "Get status information from the server."}, @@ -4052,6 +4053,26 @@ static int com_shell(String *buffer MY_ATTRIBUTE((unused)), } #endif +static int com_attr(String *buffer MY_ATTRIBUTE((unused)), char *line) { + static const char *delim = " \t"; + char *ptr = nullptr; + char *buf = strdup(line); + const char *cmd __attribute__((unused)) = strtok_r(buf, delim, &ptr); + const char *key = strtok_r(nullptr, delim, &ptr); + const char *val = strtok_r(nullptr, delim, &ptr); + + if (!key || !val) { + put_info("Usage: setattr key value", INFO_ERROR); + free(buf); + return -1; + } + + mysql_options4(&mysql, MYSQL_OPT_QUERY_ATTR_ADD, key, val); + + free(buf); + return 0; +} + static int com_print(String *buffer, char *line MY_ATTRIBUTE((unused))) { tee_puts("--------------", stdout); (void)tee_fputs(buffer->c_ptr(), stdout); diff --git a/include/mysql/com_data.h b/include/mysql/com_data.h index 75983e15ca6..7aa6aa4459c 100644 --- a/include/mysql/com_data.h +++ b/include/mysql/com_data.h @@ -106,6 +106,7 @@ struct COM_FIELD_LIST_DATA { }; union COM_DATA { + COM_QUERY_DATA com_query; COM_INIT_DB_DATA com_init_db; COM_REFRESH_DATA com_refresh; COM_KILL_DATA com_kill; @@ -116,8 +117,9 @@ union COM_DATA { COM_STMT_PREPARE_DATA com_stmt_prepare; COM_STMT_CLOSE_DATA com_stmt_close; COM_STMT_RESET_DATA com_stmt_reset; - COM_QUERY_DATA com_query; COM_FIELD_LIST_DATA com_field_list; + /*we initialize with default values only one member of union*/ + COM_DATA() : com_query() {} }; #endif /* PLUGIN_PROTOCOL_INCLUDED */ diff --git a/include/mysql/services.h.pp b/include/mysql/services.h.pp index cbfd22fa405..e02200b3dab 100644 --- a/include/mysql/services.h.pp +++ b/include/mysql/services.h.pp @@ -60,6 +60,7 @@ struct COM_FIELD_LIST_DATA { unsigned int query_length; }; union COM_DATA { + COM_QUERY_DATA com_query; COM_INIT_DB_DATA com_init_db; COM_REFRESH_DATA com_refresh; COM_KILL_DATA com_kill; @@ -70,8 +71,8 @@ union COM_DATA { COM_STMT_PREPARE_DATA com_stmt_prepare; COM_STMT_CLOSE_DATA com_stmt_close; COM_STMT_RESET_DATA com_stmt_reset; - COM_QUERY_DATA com_query; COM_FIELD_LIST_DATA com_field_list; + COM_DATA() : com_query() {} }; #include "mysql/service_srv_session.h" struct Srv_session; diff --git a/mysql-test/r/dd_is_compatibility_cs.result b/mysql-test/r/dd_is_compatibility_cs.result index afb7ed4385f..67e9735f5d8 100644 --- a/mysql-test/r/dd_is_compatibility_cs.result +++ b/mysql-test/r/dd_is_compatibility_cs.result @@ -170,6 +170,7 @@ PARTITIONS PLUGINS PROCESSLIST PROFILING +QUERY_PERF_COUNTER REFERENTIAL_CONSTRAINTS RESOURCE_GROUPS ROUTINES diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 93cf4112bf2..f94f0c589cb 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -77,6 +77,7 @@ PARTITIONS PLUGINS PROCESSLIST PROFILING +QUERY_PERF_COUNTER REFERENTIAL_CONSTRAINTS RESOURCE_GROUPS ROUTINES @@ -854,7 +855,7 @@ table_schema IN ('mysql', 'information_schema', 'test', 'mysqltest') AND table_name not like 'ndb%' AND table_name COLLATE utf8_general_ci not like 'innodb_%' GROUP BY TABLE_SCHEMA; TABLE_SCHEMA count(*) -information_schema 32 +information_schema 33 mysql 31 create table t1 (i int, j int); create trigger trg1 before insert on t1 for each row @@ -1312,6 +1313,7 @@ PARTITIONS information_schema.PARTITIONS 1 PLUGINS information_schema.PLUGINS 1 PROCESSLIST information_schema.PROCESSLIST 1 PROFILING information_schema.PROFILING 1 +QUERY_PERF_COUNTER information_schema.QUERY_PERF_COUNTER 1 REFERENTIAL_CONSTRAINTS information_schema.REFERENTIAL_CONSTRAINTS 1 RESOURCE_GROUPS information_schema.RESOURCE_GROUPS 1 ROUTINES information_schema.ROUTINES 1 @@ -2456,6 +2458,7 @@ PARTITIONS TABLE_SCHEMA PLUGINS PLUGIN_NAME PROCESSLIST ID PROFILING QUERY_ID +QUERY_PERF_COUNTER QUERY_TYPE REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA RESOURCE_GROUPS RESOURCE_GROUP_NAME ROUTINES ROUTINE_SCHEMA @@ -2507,6 +2510,7 @@ PARTITIONS TABLE_SCHEMA PLUGINS PLUGIN_NAME PROCESSLIST ID PROFILING QUERY_ID +QUERY_PERF_COUNTER QUERY_TYPE REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA RESOURCE_GROUPS RESOURCE_GROUP_NAME ROUTINES ROUTINE_SCHEMA diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result index 297dd8e7ea8..38315d62dda 100644 --- a/mysql-test/r/information_schema_db.result +++ b/mysql-test/r/information_schema_db.result @@ -23,6 +23,7 @@ PARTITIONS PLUGINS PROCESSLIST PROFILING +QUERY_PERF_COUNTER REFERENTIAL_CONSTRAINTS RESOURCE_GROUPS ROUTINES diff --git a/mysql-test/r/mysqlshow_cs.result b/mysql-test/r/mysqlshow_cs.result index 83869414a95..0e8ee42ea20 100644 --- a/mysql-test/r/mysqlshow_cs.result +++ b/mysql-test/r/mysqlshow_cs.result @@ -126,6 +126,7 @@ Database: information_schema | PLUGINS | | PROCESSLIST | | PROFILING | +| QUERY_PERF_COUNTER | | REFERENTIAL_CONSTRAINTS | | RESOURCE_GROUPS | | ROUTINES | @@ -193,6 +194,7 @@ Database: INFORMATION_SCHEMA | PLUGINS | | PROCESSLIST | | PROFILING | +| QUERY_PERF_COUNTER | | REFERENTIAL_CONSTRAINTS | | RESOURCE_GROUPS | | ROUTINES | diff --git a/mysql-test/r/query_perf_counter.result b/mysql-test/r/query_perf_counter.result new file mode 100644 index 00000000000..de69ee539b7 --- /dev/null +++ b/mysql-test/r/query_perf_counter.result @@ -0,0 +1,8 @@ +create database db1; +use db1; +select * from information_schema.query_perf_counter where query_type = "ASSOC_RANGE222"; +QUERY_TYPE CPU NUM_QUERIES +select * from information_schema.query_perf_counter where query_type = "ASSOC_RANGE22"; +QUERY_TYPE CPU NUM_QUERIES +ASSOC_RANGE22 cpu_time 1 +drop database db1; 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 c929f8543cc..b0462440c7e 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is.result @@ -198,6 +198,9 @@ def information_schema PROCESSLIST COMMAND 5 NO varchar 5 16 NULL NULL NULL utf def information_schema PROCESSLIST TIME 6 NO int NULL NULL NULL NULL NULL NULL NULL int(7) select NULL def information_schema PROCESSLIST STATE 7 YES varchar 21 64 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NULL def information_schema PROCESSLIST INFO 8 YES varchar 21845 65535 NULL NULL NULL utf8 utf8_general_ci varchar(65535) select NULL +def information_schema QUERY_PERF_COUNTER QUERY_TYPE 1 NO varchar 84 254 NULL NULL NULL utf8 utf8_general_ci varchar(254) select NULL +def information_schema QUERY_PERF_COUNTER CPU 2 NO bigint NULL NULL NULL NULL NULL NULL NULL bigint(21) select NULL +def information_schema QUERY_PERF_COUNTER NUM_QUERIES 3 NO bigint NULL NULL NULL NULL NULL NULL NULL bigint(21) select NULL def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_CATALOG 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) select NULL def information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME 3 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select NULL @@ -398,6 +401,7 @@ COL_CML DATA_TYPE CHARACTER_SET_NAME COLLATION_NAME 3.0000 varchar utf8 utf8_general_ci 3.0029 varchar utf8 utf8_general_ci 3.0118 varchar utf8 utf8_general_ci +3.0238 varchar utf8 utf8_general_ci 3.0476 varchar utf8 utf8_general_ci 3.0769 varchar utf8 utf8_general_ci 3.2000 varchar utf8 utf8_general_ci @@ -633,6 +637,9 @@ NULL information_schema PROCESSLIST ID bigint NULL NULL NULL NULL bigint(21) uns NULL information_schema PROCESSLIST TIME int NULL NULL NULL NULL int(7) 3.0476 information_schema PROCESSLIST STATE varchar 21 64 utf8 utf8_general_ci varchar(64) 3.0000 information_schema PROCESSLIST INFO varchar 21845 65535 utf8 utf8_general_ci varchar(65535) +3.0238 information_schema QUERY_PERF_COUNTER QUERY_TYPE varchar 84 254 utf8 utf8_general_ci varchar(254) +NULL information_schema QUERY_PERF_COUNTER CPU bigint NULL NULL NULL NULL bigint(21) +NULL information_schema QUERY_PERF_COUNTER NUM_QUERIES bigint NULL NULL NULL NULL bigint(21) 3.0000 information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_CATALOG varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA varchar 64 192 utf8 utf8_bin varchar(64) 3.0000 information_schema REFERENTIAL_CONSTRAINTS CONSTRAINT_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) diff --git a/mysql-test/suite/funcs_1/r/is_tables_is.result b/mysql-test/suite/funcs_1/r/is_tables_is.result index 87105b811da..960369d424f 100644 --- a/mysql-test/suite/funcs_1/r/is_tables_is.result +++ b/mysql-test/suite/funcs_1/r/is_tables_is.result @@ -385,6 +385,29 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME QUERY_PERF_COUNTER +TABLE_TYPE SYSTEM VIEW +ENGINE NULL +VERSION 10 +ROW_FORMAT NULL +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT #AI# +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION NULL +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME REFERENTIAL_CONSTRAINTS TABLE_TYPE SYSTEM VIEW ENGINE NULL @@ -1117,6 +1140,29 @@ user_comment Separator ----------------------------------------------------- TABLE_CATALOG def TABLE_SCHEMA information_schema +TABLE_NAME QUERY_PERF_COUNTER +TABLE_TYPE SYSTEM VIEW +ENGINE NULL +VERSION 10 +ROW_FORMAT NULL +TABLE_ROWS #TBLR# +AVG_ROW_LENGTH #ARL# +DATA_LENGTH #DL# +MAX_DATA_LENGTH #MDL# +INDEX_LENGTH #IL# +DATA_FREE #DF# +AUTO_INCREMENT #AI# +CREATE_TIME #CRT# +UPDATE_TIME #UT# +CHECK_TIME #CT# +TABLE_COLLATION NULL +CHECKSUM NULL +CREATE_OPTIONS #CO# +TABLE_COMMENT #TC# +user_comment +Separator ----------------------------------------------------- +TABLE_CATALOG def +TABLE_SCHEMA information_schema TABLE_NAME REFERENTIAL_CONSTRAINTS TABLE_TYPE SYSTEM VIEW ENGINE NULL diff --git a/mysql-test/suite/perfschema/r/nesting.result b/mysql-test/suite/perfschema/r/nesting.result index a145b3a05df..2bd1c615849 100644 --- a/mysql-test/suite/perfschema/r/nesting.result +++ b/mysql-test/suite/perfschema/r/nesting.result @@ -114,132 +114,142 @@ and (end_event_id <= @marker_end) ) all_events order by relative_event_id asc; relative_event_id relative_end_event_id event_name comment nesting_event_type relative_nesting_event_id -0 17 statement/sql/select select "MARKER_BEGIN" as marker NULL NULL -1 5 stage/sql/starting (stage) STATEMENT 0 +0 19 statement/sql/select select "MARKER_BEGIN" as marker NULL NULL +1 6 stage/sql/starting (stage) STATEMENT 0 2 2 wait/io/socket/sql/client_connection recv STAGE 1 3 3 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 1 -4 4 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 1 -5 5 wait/io/file/sql/query_log write STAGE 1 -6 6 stage/sql/checking permissions (stage) STATEMENT 0 -7 7 stage/sql/Opening tables (stage) STATEMENT 0 -8 8 stage/sql/init (stage) STATEMENT 0 -9 9 stage/sql/optimizing (stage) STATEMENT 0 -10 10 stage/sql/executing (stage) STATEMENT 0 -11 11 stage/sql/end (stage) STATEMENT 0 -12 12 stage/sql/query end (stage) STATEMENT 0 -13 13 stage/sql/closing tables (stage) STATEMENT 0 -14 15 stage/sql/freeing items (stage) STATEMENT 0 -15 15 wait/io/socket/sql/client_connection send STAGE 14 -16 17 stage/sql/cleaning up (stage) STATEMENT 0 -17 17 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 16 -18 18 idle idle NULL NULL -19 36 statement/sql/select select "This is simple statement one" as payload NULL NULL -20 24 stage/sql/starting (stage) STATEMENT 19 -21 21 wait/io/socket/sql/client_connection recv STAGE 20 -22 22 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 20 -23 23 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 20 -24 24 wait/io/file/sql/query_log write STAGE 20 -25 25 stage/sql/checking permissions (stage) STATEMENT 19 -26 26 stage/sql/Opening tables (stage) STATEMENT 19 -27 27 stage/sql/init (stage) STATEMENT 19 -28 28 stage/sql/optimizing (stage) STATEMENT 19 -29 29 stage/sql/executing (stage) STATEMENT 19 -30 30 stage/sql/end (stage) STATEMENT 19 -31 31 stage/sql/query end (stage) STATEMENT 19 -32 32 stage/sql/closing tables (stage) STATEMENT 19 -33 34 stage/sql/freeing items (stage) STATEMENT 19 -34 34 wait/io/socket/sql/client_connection send STAGE 33 -35 36 stage/sql/cleaning up (stage) STATEMENT 19 -36 36 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 35 -37 37 idle idle NULL NULL -38 55 statement/sql/select select "This is simple statement two" as payload NULL NULL -39 43 stage/sql/starting (stage) STATEMENT 38 -40 40 wait/io/socket/sql/client_connection recv STAGE 39 -41 41 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 39 -42 42 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 39 -43 43 wait/io/file/sql/query_log write STAGE 39 -44 44 stage/sql/checking permissions (stage) STATEMENT 38 -45 45 stage/sql/Opening tables (stage) STATEMENT 38 -46 46 stage/sql/init (stage) STATEMENT 38 -47 47 stage/sql/optimizing (stage) STATEMENT 38 -48 48 stage/sql/executing (stage) STATEMENT 38 -49 49 stage/sql/end (stage) STATEMENT 38 -50 50 stage/sql/query end (stage) STATEMENT 38 -51 51 stage/sql/closing tables (stage) STATEMENT 38 -52 53 stage/sql/freeing items (stage) STATEMENT 38 -53 53 wait/io/socket/sql/client_connection send STAGE 52 -54 55 stage/sql/cleaning up (stage) STATEMENT 38 -55 55 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 54 -56 56 idle idle NULL NULL -57 73 statement/sql/select select "This is the first part of a multi query" as payload; +4 4 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 1 +5 5 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 1 +6 6 wait/io/file/sql/query_log write STAGE 1 +7 7 stage/sql/checking permissions (stage) STATEMENT 0 +8 8 stage/sql/Opening tables (stage) STATEMENT 0 +9 9 stage/sql/init (stage) STATEMENT 0 +10 10 stage/sql/optimizing (stage) STATEMENT 0 +11 11 stage/sql/executing (stage) STATEMENT 0 +12 12 stage/sql/end (stage) STATEMENT 0 +13 13 stage/sql/query end (stage) STATEMENT 0 +14 14 stage/sql/closing tables (stage) STATEMENT 0 +15 16 stage/sql/freeing items (stage) STATEMENT 0 +16 16 wait/io/socket/sql/client_connection send STAGE 15 +17 19 stage/sql/cleaning up (stage) STATEMENT 0 +18 18 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 17 +19 19 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 17 +20 20 idle idle NULL NULL +21 40 statement/sql/select select "This is simple statement one" as payload NULL NULL +22 27 stage/sql/starting (stage) STATEMENT 21 +23 23 wait/io/socket/sql/client_connection recv STAGE 22 +24 24 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 22 +25 25 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 22 +26 26 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 22 +27 27 wait/io/file/sql/query_log write STAGE 22 +28 28 stage/sql/checking permissions (stage) STATEMENT 21 +29 29 stage/sql/Opening tables (stage) STATEMENT 21 +30 30 stage/sql/init (stage) STATEMENT 21 +31 31 stage/sql/optimizing (stage) STATEMENT 21 +32 32 stage/sql/executing (stage) STATEMENT 21 +33 33 stage/sql/end (stage) STATEMENT 21 +34 34 stage/sql/query end (stage) STATEMENT 21 +35 35 stage/sql/closing tables (stage) STATEMENT 21 +36 37 stage/sql/freeing items (stage) STATEMENT 21 +37 37 wait/io/socket/sql/client_connection send STAGE 36 +38 40 stage/sql/cleaning up (stage) STATEMENT 21 +39 39 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 38 +40 40 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 38 +41 41 idle idle NULL NULL +42 61 statement/sql/select select "This is simple statement two" as payload NULL NULL +43 48 stage/sql/starting (stage) STATEMENT 42 +44 44 wait/io/socket/sql/client_connection recv STAGE 43 +45 45 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 43 +46 46 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 43 +47 47 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 43 +48 48 wait/io/file/sql/query_log write STAGE 43 +49 49 stage/sql/checking permissions (stage) STATEMENT 42 +50 50 stage/sql/Opening tables (stage) STATEMENT 42 +51 51 stage/sql/init (stage) STATEMENT 42 +52 52 stage/sql/optimizing (stage) STATEMENT 42 +53 53 stage/sql/executing (stage) STATEMENT 42 +54 54 stage/sql/end (stage) STATEMENT 42 +55 55 stage/sql/query end (stage) STATEMENT 42 +56 56 stage/sql/closing tables (stage) STATEMENT 42 +57 58 stage/sql/freeing items (stage) STATEMENT 42 +58 58 wait/io/socket/sql/client_connection send STAGE 57 +59 61 stage/sql/cleaning up (stage) STATEMENT 42 +60 60 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 59 +61 61 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 59 +62 62 idle idle NULL NULL +63 80 statement/sql/select select "This is the first part of a multi query" as payload; select "And this is the second part of a multi query" as payload; select "With a third part to make things complete" as payload NULL NULL -58 63 stage/sql/starting (stage) STATEMENT 57 -59 59 wait/io/socket/sql/client_connection recv STAGE 58 -60 60 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 58 -61 61 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 58 -62 62 wait/io/file/sql/query_log write STAGE 58 -63 63 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 58 -64 64 stage/sql/checking permissions (stage) STATEMENT 57 -65 65 stage/sql/Opening tables (stage) STATEMENT 57 -66 66 stage/sql/init (stage) STATEMENT 57 -67 67 stage/sql/optimizing (stage) STATEMENT 57 -68 68 stage/sql/executing (stage) STATEMENT 57 -69 69 stage/sql/end (stage) STATEMENT 57 -70 70 stage/sql/query end (stage) STATEMENT 57 -71 71 stage/sql/closing tables (stage) STATEMENT 57 -72 73 stage/sql/freeing items (stage) STATEMENT 57 -73 73 wait/io/socket/sql/client_connection send STAGE 72 -74 89 statement/sql/select select "And this is the second part of a multi query" as payload; +64 70 stage/sql/starting (stage) STATEMENT 63 +65 65 wait/io/socket/sql/client_connection recv STAGE 64 +66 66 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 64 +67 67 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 64 +68 68 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 64 +69 69 wait/io/file/sql/query_log write STAGE 64 +70 70 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 64 +71 71 stage/sql/checking permissions (stage) STATEMENT 63 +72 72 stage/sql/Opening tables (stage) STATEMENT 63 +73 73 stage/sql/init (stage) STATEMENT 63 +74 74 stage/sql/optimizing (stage) STATEMENT 63 +75 75 stage/sql/executing (stage) STATEMENT 63 +76 76 stage/sql/end (stage) STATEMENT 63 +77 77 stage/sql/query end (stage) STATEMENT 63 +78 78 stage/sql/closing tables (stage) STATEMENT 63 +79 80 stage/sql/freeing items (stage) STATEMENT 63 +80 80 wait/io/socket/sql/client_connection send STAGE 79 +81 96 statement/sql/select select "And this is the second part of a multi query" as payload; select "With a third part to make things complete" as payload NULL NULL -75 79 stage/sql/starting (stage) STATEMENT 74 -76 76 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 75 -77 77 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 75 -78 78 wait/io/file/sql/query_log write STAGE 75 -79 79 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 75 -80 80 stage/sql/checking permissions (stage) STATEMENT 74 -81 81 stage/sql/Opening tables (stage) STATEMENT 74 -82 82 stage/sql/init (stage) STATEMENT 74 -83 83 stage/sql/optimizing (stage) STATEMENT 74 -84 84 stage/sql/executing (stage) STATEMENT 74 -85 85 stage/sql/end (stage) STATEMENT 74 -86 86 stage/sql/query end (stage) STATEMENT 74 -87 87 stage/sql/closing tables (stage) STATEMENT 74 -88 89 stage/sql/freeing items (stage) STATEMENT 74 -89 89 wait/io/socket/sql/client_connection send STAGE 88 -90 106 statement/sql/select select "With a third part to make things complete" as payload NULL NULL -91 94 stage/sql/starting (stage) STATEMENT 90 -92 92 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 91 -93 93 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 91 -94 94 wait/io/file/sql/query_log write STAGE 91 -95 95 stage/sql/checking permissions (stage) STATEMENT 90 -96 96 stage/sql/Opening tables (stage) STATEMENT 90 -97 97 stage/sql/init (stage) STATEMENT 90 -98 98 stage/sql/optimizing (stage) STATEMENT 90 -99 99 stage/sql/executing (stage) STATEMENT 90 -100 100 stage/sql/end (stage) STATEMENT 90 -101 101 stage/sql/query end (stage) STATEMENT 90 -102 102 stage/sql/closing tables (stage) STATEMENT 90 -103 104 stage/sql/freeing items (stage) STATEMENT 90 -104 104 wait/io/socket/sql/client_connection send STAGE 103 -105 106 stage/sql/cleaning up (stage) STATEMENT 90 -106 106 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 105 -107 107 idle idle NULL NULL -108 125 statement/sql/select select "MARKER_END" as marker NULL NULL -109 113 stage/sql/starting (stage) STATEMENT 108 -110 110 wait/io/socket/sql/client_connection recv STAGE 109 -111 111 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 109 -112 112 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 109 -113 113 wait/io/file/sql/query_log write STAGE 109 -114 114 stage/sql/checking permissions (stage) STATEMENT 108 -115 115 stage/sql/Opening tables (stage) STATEMENT 108 -116 116 stage/sql/init (stage) STATEMENT 108 -117 117 stage/sql/optimizing (stage) STATEMENT 108 -118 118 stage/sql/executing (stage) STATEMENT 108 -119 119 stage/sql/end (stage) STATEMENT 108 -120 120 stage/sql/query end (stage) STATEMENT 108 -121 121 stage/sql/closing tables (stage) STATEMENT 108 -122 123 stage/sql/freeing items (stage) STATEMENT 108 -123 123 wait/io/socket/sql/client_connection send STAGE 122 -124 125 stage/sql/cleaning up (stage) STATEMENT 108 -125 125 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 124 +82 86 stage/sql/starting (stage) STATEMENT 81 +83 83 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 82 +84 84 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 82 +85 85 wait/io/file/sql/query_log write STAGE 82 +86 86 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 82 +87 87 stage/sql/checking permissions (stage) STATEMENT 81 +88 88 stage/sql/Opening tables (stage) STATEMENT 81 +89 89 stage/sql/init (stage) STATEMENT 81 +90 90 stage/sql/optimizing (stage) STATEMENT 81 +91 91 stage/sql/executing (stage) STATEMENT 81 +92 92 stage/sql/end (stage) STATEMENT 81 +93 93 stage/sql/query end (stage) STATEMENT 81 +94 94 stage/sql/closing tables (stage) STATEMENT 81 +95 96 stage/sql/freeing items (stage) STATEMENT 81 +96 96 wait/io/socket/sql/client_connection send STAGE 95 +97 114 statement/sql/select select "With a third part to make things complete" as payload NULL NULL +98 101 stage/sql/starting (stage) STATEMENT 97 +99 99 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 98 +100 100 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 98 +101 101 wait/io/file/sql/query_log write STAGE 98 +102 102 stage/sql/checking permissions (stage) STATEMENT 97 +103 103 stage/sql/Opening tables (stage) STATEMENT 97 +104 104 stage/sql/init (stage) STATEMENT 97 +105 105 stage/sql/optimizing (stage) STATEMENT 97 +106 106 stage/sql/executing (stage) STATEMENT 97 +107 107 stage/sql/end (stage) STATEMENT 97 +108 108 stage/sql/query end (stage) STATEMENT 97 +109 109 stage/sql/closing tables (stage) STATEMENT 97 +110 111 stage/sql/freeing items (stage) STATEMENT 97 +111 111 wait/io/socket/sql/client_connection send STAGE 110 +112 114 stage/sql/cleaning up (stage) STATEMENT 97 +113 113 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 112 +114 114 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 112 +115 115 idle idle NULL NULL +116 135 statement/sql/select select "MARKER_END" as marker NULL NULL +117 122 stage/sql/starting (stage) STATEMENT 116 +118 118 wait/io/socket/sql/client_connection recv STAGE 117 +119 119 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 117 +120 120 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 117 +121 121 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 117 +122 122 wait/io/file/sql/query_log write STAGE 117 +123 123 stage/sql/checking permissions (stage) STATEMENT 116 +124 124 stage/sql/Opening tables (stage) STATEMENT 116 +125 125 stage/sql/init (stage) STATEMENT 116 +126 126 stage/sql/optimizing (stage) STATEMENT 116 +127 127 stage/sql/executing (stage) STATEMENT 116 +128 128 stage/sql/end (stage) STATEMENT 116 +129 129 stage/sql/query end (stage) STATEMENT 116 +130 130 stage/sql/closing tables (stage) STATEMENT 116 +131 132 stage/sql/freeing items (stage) STATEMENT 116 +132 132 wait/io/socket/sql/client_connection send STAGE 131 +133 135 stage/sql/cleaning up (stage) STATEMENT 116 +134 134 wait/synch/mutex/sql/THD::LOCK_thd_query lock STAGE 133 +135 135 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 133 diff --git a/mysql-test/t/query_perf_counter.test b/mysql-test/t/query_perf_counter.test new file mode 100644 index 00000000000..444328acfbc --- /dev/null +++ b/mysql-test/t/query_perf_counter.test @@ -0,0 +1,10 @@ +create database db1; +use db1; +connect (con,localhost,root,,db1); +query_attrs_add query_info {"num_queries":1,"query_type":"ASSOC_RANGE22"}; +select * from information_schema.query_perf_counter where query_type = "ASSOC_RANGE222"; +--replace_column 2 cpu_time +select * from information_schema.query_perf_counter where query_type = "ASSOC_RANGE22"; +query_attrs_delete query_info; +connection default; +drop database db1; diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 76014c9ea8c..6f12389768a 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -377,6 +377,7 @@ SET(SQL_SHARED_SOURCES protocol_classic.cc psi_memory_key.cc query_result.cc + query_tag_perf_counter.cc records.cc regexp/errors.cc regexp/regexp_engine.cc diff --git a/plugin/test_service_sql_api/test_sql_stmt.cc b/plugin/test_service_sql_api/test_sql_stmt.cc index b08551b147d..db635f9be0d 100644 --- a/plugin/test_service_sql_api/test_sql_stmt.cc +++ b/plugin/test_service_sql_api/test_sql_stmt.cc @@ -712,6 +712,7 @@ static char *fieldflags2str(uint f) { } static void set_query_in_com_data(union COM_DATA *cmd, const char *query) { + memset(cmd, 0, sizeof(*cmd)); cmd->com_query.query = (char *)query; cmd->com_query.length = strlen(query); } @@ -1127,6 +1128,7 @@ static void test_4(MYSQL_SESSION session, void *p) { d_data++; } + memset(&cmd, 0, sizeof(cmd)); set_query_in_com_data(&cmd, "SELECT * FROM t2"); run_cmd(session, COM_QUERY, &cmd, &ctx, false, p); diff --git a/sql/handler.h b/sql/handler.h index 93f4242d2d4..829d483f327 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -822,6 +822,7 @@ enum enum_schema_tables { SCH_OPTIMIZER_TRACE, SCH_PLUGINS, SCH_PROCESSLIST, + SCH_QUERY_PERF_COUNTER, SCH_PROFILES, SCH_SCHEMA_PRIVILEGES, SCH_TABLESPACES, diff --git a/sql/protocol_classic.cc b/sql/protocol_classic.cc index 08094a77efd..d0341247f8f 100644 --- a/sql/protocol_classic.cc +++ b/sql/protocol_classic.cc @@ -2734,6 +2734,8 @@ bool Protocol_classic::parse_packet(union COM_DATA *data, break; } case COM_QUERY: { + data->com_query.query_attrs_length = 0; + data->com_query.query_attrs = nullptr; data->com_query.query = reinterpret_cast(input_raw_packet); data->com_query.length = input_packet_length; break; diff --git a/sql/query_tag_perf_counter.cc b/sql/query_tag_perf_counter.cc new file mode 100644 index 00000000000..d8e85724b9b --- /dev/null +++ b/sql/query_tag_perf_counter.cc @@ -0,0 +1,96 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "field.h" +#include "query_tag_perf_counter.h" +#include "sql_class.h" +#include "sql_show.h" +#include "table.h" + +namespace qutils { + +namespace pt = boost::property_tree; + +using cpu_and_num_queries = std::tuple; +static int64_t timespec_diff(const timespec &start, const timespec &stop); + +static std::mutex stats_mutex; +static std::unordered_map stats; + +query_tag_perf_counter::query_tag_perf_counter(THD *_thd) + : started(false), thd(_thd) { + if (!thd->query_type.empty() && thd->num_queries > 0) { + this->started = + clock_gettime(CLOCK_THREAD_CPUTIME_ID, &this->starttime) == 0; + } +} + +query_tag_perf_counter::~query_tag_perf_counter() { + if (!this->started) return; + struct timespec endtime; + if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &endtime) != 0) return; + + const int64_t cputime = timespec_diff(this->starttime, endtime); + if (cputime < 0) return; // skip if overflow + + DBUG_ASSERT(thd->num_queries > 0); + + std::lock_guard lock(stats_mutex); + cpu_and_num_queries &val = stats[thd->query_type]; + std::get<0>(val) += cputime; + std::get<1>(val) += thd->num_queries; +} + +int fill_query_tag_perf_counter(THD *thd, TABLE_LIST *tables, Item *) { + std::lock_guard lock(stats_mutex); + + DBUG_ENTER("fill_query_tag_perf_counter"); + + TABLE *table = tables->table; + for (const auto &row : stats) { + restore_record(table, s->default_values); + Field **field = table->field; + + const std::string &query_type = row.first; + const cpu_and_num_queries &val = row.second; + const uint64_t cpu_time = std::get<0>(val); + const uint64_t num_queries = std::get<1>(val); + + field[0]->store(query_type.c_str(), query_type.length(), + system_charset_info); + field[1]->store(cpu_time, true); + field[2]->store(num_queries, true); + + if (schema_table_store_record(thd, table)) { + DBUG_RETURN(-1); + } + } + DBUG_RETURN(0); +} + +const uint query_type_field_length = 254; + +ST_FIELD_INFO query_tag_perf_fields_info[] = { + {"QUERY_TYPE", query_type_field_length, MYSQL_TYPE_STRING, 0, 0, 0, + SKIP_OPEN_TABLE}, + {"CPU", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, 0, + SKIP_OPEN_TABLE}, + {"NUM_QUERIES", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, 0, + SKIP_OPEN_TABLE}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}}; + +static int64_t timespec_diff(const timespec &start, const timespec &stop) { + const int64_t sec = stop.tv_sec - start.tv_sec; + const int64_t nsec = stop.tv_nsec - start.tv_nsec; + const int64_t diff = sec * 1000000000LL + nsec; + return diff; +} +} // namespace qutils diff --git a/sql/query_tag_perf_counter.h b/sql/query_tag_perf_counter.h new file mode 100644 index 00000000000..6d739943588 --- /dev/null +++ b/sql/query_tag_perf_counter.h @@ -0,0 +1,33 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#ifndef QUERY_TAG_PERF_COUNTER_H_ +#define QUERY_TAG_PERF_COUNTER_H_ + +#include +#include + +class Item; +class THD; +struct TABLE_LIST; +struct ST_FIELD_INFO; + +namespace qutils { + +extern ST_FIELD_INFO query_tag_perf_fields_info[]; +extern int fill_query_tag_perf_counter(THD *thd, TABLE_LIST *tables, + Item *cond); + +class query_tag_perf_counter { + public: + query_tag_perf_counter(THD *thd); + ~query_tag_perf_counter(); + + private: + struct timespec starttime; // query start timestamp + bool started; // query_info attribute detected + THD *thd; // reference to outer THD +}; + +} // namespace qutils + +#endif /* QUERY_TAG_PERF_COUNTER_H_ */ diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f4dc1a696c5..002165b007c 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -31,6 +31,11 @@ #include #include +#include +#include +#include +#include +#include #include "binary_log_types.h" #include "m_ctype.h" #include "m_string.h" @@ -83,9 +88,12 @@ #include "sql/thr_malloc.h" #include "sql/transaction.h" // trans_rollback #include "sql/transaction_info.h" + #include "sql/xa.h" #include "thr_mutex.h" +using boost::property_tree::ptree; + using std::max; using std::min; using std::unique_ptr; @@ -2772,3 +2780,61 @@ bool THD::sql_parser() { } return false; } +static std::string net_read_str(const char **ptr) { + size_t len = net_field_length((uchar **)ptr); + const char *str = *ptr; + *ptr += len; + return std::string(str, len); +} + +static void set_attrs_map( + const char *ptr, size_t length, + std::unordered_map &attrs_map) { + const char *end = ptr + length; + + attrs_map.clear(); + while (ptr < end) { + std::string key = net_read_str(&ptr); + std::string value = net_read_str(&ptr); + attrs_map[key] = value; + } +} + +void THD::set_connection_attrs(const char *attrs, size_t length) { + mysql_mutex_lock(&LOCK_thd_data); + set_attrs_map(attrs, length, connection_attrs_map); + mysql_mutex_unlock(&LOCK_thd_data); +} + +void THD::set_query_attrs(const char *attrs, size_t length) { + query_attrs_string = std::string(attrs, length); + + mysql_mutex_lock(&LOCK_thd_data); + set_attrs_map(query_attrs_string.c_str(), query_attrs_string.length(), + query_attrs_map); + mysql_mutex_unlock(&LOCK_thd_data); +} + +int THD::parse_query_info_attr() { + static const std::string query_info_key = "query_info"; + + auto it = this->query_attrs_map.find(query_info_key); + if (it == this->query_attrs_map.end()) return 0; + ptree root; + try { + std::istringstream query_info_attr(it->second); + boost::property_tree::read_json(query_info_attr, root); + } catch (const boost::property_tree::json_parser::json_parser_error &e) { + return -1; // invalid json + } + try { + boost::optional trace_id = + root.get_optional("traceid"); + if (trace_id) this->trace_id = *trace_id; + this->query_type = root.get("query_type"); + this->num_queries = root.get("num_queries"); + } catch (const boost::property_tree::ptree_error &e) { + return -1; // invalid key or value + } + return 0; +} diff --git a/sql/sql_class.h b/sql/sql_class.h index 2bb84a4ffc5..4d2f6fcb47e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -3721,14 +3721,30 @@ class THD : public MDL_context_owner, void mark_transaction_to_rollback(bool all); - void set_query_attrs(const LEX_CSTRING &arg) { query_attrs_string = arg; } - void reset_query_attrs() { set_query_attrs(LEX_CSTRING()); } - inline const char *query_attrs() const { return query_attrs_string.str; } - inline uint32 query_attrs_length() const { return query_attrs_string.length; } + void set_connection_attrs(const char *attrs, size_t length); + void set_query_attrs(const char *attrs, size_t length); + int parse_query_info_attr(); + void reset_query_attrs() { + mysql_mutex_lock(&LOCK_thd_data); + query_attrs_map.clear(); + mysql_mutex_unlock(&LOCK_thd_data); - private: - LEX_CSTRING query_attrs_string; + query_attrs_string.clear(); + trace_id.clear(); + num_queries = 0; + query_type.clear(); + } + inline const char *query_attrs() const { return query_attrs_string.c_str(); } + inline uint32 query_attrs_length() const { + return query_attrs_string.length(); + } + std::unordered_map query_attrs_map; + std::unordered_map connection_attrs_map; + uint64_t num_queries; + std::string query_type; + std::string trace_id; + private: /** The current internal error handler for this thread, or NULL. */ Internal_error_handler *m_internal_handler; @@ -3770,6 +3786,7 @@ class THD : public MDL_context_owner, friend class Protocol_classic; private: + std::string query_attrs_string; /** Optimizer cost model for server operations. */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b51a758aacd..587b4acf79f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -168,6 +168,7 @@ #include "thr_lock.h" #include "violite.h" +#include "query_tag_perf_counter.h" namespace dd { class Spatial_reference_system; } // namespace dd @@ -1370,6 +1371,7 @@ bool dispatch_command(THD *thd, const COM_DATA *com_data, /* For per-query performance counters with log_slow_statement */ struct System_status_var query_start_status; struct System_status_var *query_start_status_ptr = NULL; + if (opt_log_slow_extra) { query_start_status_ptr = &query_start_status; query_start_status = thd->status_var; @@ -1611,13 +1613,18 @@ bool dispatch_command(THD *thd, const COM_DATA *com_data, DBUG_ASSERT(thd->m_digest == NULL); thd->m_digest = &thd->m_digest_state; thd->m_digest->reset(thd->m_token_array, max_digest_length); - thd->set_query_attrs({com_data->com_query.query_attrs, - com_data->com_query.query_attrs_length}); + + const char *attrs = com_data->com_query.query_attrs; + const unsigned int attrslen = com_data->com_query.query_attrs_length; + thd->set_query_attrs(attrs, attrslen); + thd->parse_query_info_attr(); if (alloc_query(thd, com_data->com_query.query, com_data->com_query.length)) break; // fatal error is set + qutils::query_tag_perf_counter counter(thd); + const char *packet_end = thd->query().str + thd->query().length; if (opt_general_log_raw) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3059006dfd5..f111bdf2cdd 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -136,6 +136,8 @@ bool iterate_all_dynamic_privileges(THD *thd, using std::max; using std::min; +#include "query_tag_perf_counter.h" + #define STR_OR_NIL(S) ((S) ? (S) : "") /** @@ -4998,6 +5000,9 @@ ST_SCHEMA_TABLE schema_tables[] = { make_old_format, 0, -1, -1, 0, 0}, {"PROCESSLIST", processlist_fields_info, create_schema_table, fill_schema_processlist, make_old_format, 0, -1, -1, 0, 0}, + {"QUERY_PERF_COUNTER", qutils::query_tag_perf_fields_info, + create_schema_table, qutils::fill_query_tag_perf_counter, NULL, NULL, -1, + -1, false, 0}, {"PROFILING", query_profile_statistics_info, create_schema_table, fill_query_profile_statistics_info, make_profile_table_for_show, NULL, -1, -1, false, 0},