From 85517f609a070aa9414fa8b2a1a9ff25e9bb9af8 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sun, 11 Feb 2024 00:05:24 +0400 Subject: [PATCH 001/106] MDEV-33393 audit plugin do not report user did the action.. The '' user is assigned to the slave replication thread so this name appears in the auditing logs. --- mysql-test/suite/rpl/r/rpl_auditing.result | 64 ++++++++++++++++++ mysql-test/suite/rpl/t/rpl_auditing.test | 77 ++++++++++++++++++++++ sql/mysqld.cc | 3 +- sql/mysqld.h | 2 +- sql/slave.cc | 1 + sql/sql_acl.cc | 2 +- sql/sql_class.cc | 2 +- sql/sql_class.h | 2 + sql/sql_show.cc | 9 +-- 9 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_auditing.result create mode 100644 mysql-test/suite/rpl/t/rpl_auditing.test diff --git a/mysql-test/suite/rpl/r/rpl_auditing.result b/mysql-test/suite/rpl/r/rpl_auditing.result new file mode 100644 index 00000000000..1861beb4e8f --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_auditing.result @@ -0,0 +1,64 @@ +include/master-slave.inc +[connection master] +drop table if exists t1; +connection slave; +reset master; +CREATE TABLE IF NOT EXISTS mysql.server_audit_filters ( +filtername char(80) COLLATE utf8_bin NOT NULL DEFAULT '', +rule longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT 'true' CHECK (json_valid(rule)), +CONSTRAINT c_filtername UNIQUE (filtername) +) ENGINE=Aria; +CREATE TABLE IF NOT EXISTS mysql.server_audit_users (host char(60) COLLATE utf8_bin NOT NULL DEFAULT '', +user char(80) COLLATE utf8_bin NOT NULL DEFAULT '', +filtername char(80) NOT NULL DEFAULT '', +CONSTRAINT c_host_user UNIQUE (host, user) +) ENGINE=Aria; +INSERT INTO mysql.server_audit_filters VALUES ('ignore_sys', '{"ignore_tables" : "mysql.*"}'); +INSERT INTO mysql.server_audit_users VALUES ('%','','ignore_sys'); +INSERT INTO mysql.server_audit_users VALUES ('%','root','ignore_sys'); +install plugin server_audit soname 'server_audit2'; +set global server_audit_logging=on; +connection master; +create table t1 (a int); +insert into t1 values (1); +truncate t1; +drop table t1; +connection slave; +set global server_audit_logging=off; +truncate mysql.server_audit_filters; +truncate mysql.server_audit_users; +INSERT INTO mysql.server_audit_filters VALUES ('no_logging','false'); +INSERT INTO mysql.server_audit_users VALUES ('%','','no_logging'); +set global server_audit_logging=on; +connection master; +create table t1 (a int); +insert into t1 values (1); +truncate t1; +drop table t1; +connection slave; +set global server_audit_logging=off; +uninstall plugin server_audit; +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown +truncate mysql.server_audit_filters; +truncate mysql.server_audit_users; +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,file_path=server_audit.log,0 +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,rotate_size=1000000,0 +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,file_rotations=9,0 +TIME,HOSTNAME,root,localhost,ID,0,AUDIT_CONFIG,test,logging=ON,0 +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_logging=on',0 +TIME,HOSTNAME,,,ID,ID,CREATE,test,t1, +TIME,HOSTNAME,,,ID,ID,WRITE,test,t1, +TIME,HOSTNAME,,,ID,ID,CREATE,test,t1, +TIME,HOSTNAME,,,ID,ID,DROP,test,t1, +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select master_pos_wait(\'master-bin.#', POS, 300, \'\')',0 +TIME,HOSTNAME,root,localhost,ID,0,AUDIT_CONFIG,test,logging=OFF,0 +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,file_path=server_audit.log,0 +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,rotate_size=1000000,0 +TIME,HOSTNAME,,,0,0,AUDIT_CONFIG,,file_rotations=9,0 +TIME,HOSTNAME,root,localhost,ID,0,AUDIT_CONFIG,test,logging=ON,0 +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'set global server_audit_logging=on',0 +TIME,HOSTNAME,root,localhost,ID,ID,QUERY,test,'select master_pos_wait(\'master-bin.#', POS, 300, \'\')',0 +TIME,HOSTNAME,root,localhost,ID,0,AUDIT_CONFIG,test,logging=OFF,0 +connection master; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_auditing.test b/mysql-test/suite/rpl/t/rpl_auditing.test new file mode 100644 index 00000000000..3d3cee9a7a0 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_auditing.test @@ -0,0 +1,77 @@ +if (!$SERVER_AUDIT2_SO) { + skip No SERVER_AUDIT2 plugin; +} + +source include/master-slave.inc; + +--disable_warnings +drop table if exists t1; +sync_slave_with_master; +reset master; +--enable_warnings + +--disable_warnings +CREATE TABLE IF NOT EXISTS mysql.server_audit_filters ( + filtername char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + rule longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT 'true' CHECK (json_valid(rule)), + CONSTRAINT c_filtername UNIQUE (filtername) +) ENGINE=Aria; + +CREATE TABLE IF NOT EXISTS mysql.server_audit_users (host char(60) COLLATE utf8_bin NOT NULL DEFAULT '', + user char(80) COLLATE utf8_bin NOT NULL DEFAULT '', + filtername char(80) NOT NULL DEFAULT '', + CONSTRAINT c_host_user UNIQUE (host, user) +) ENGINE=Aria; +--enable_warnings + +INSERT INTO mysql.server_audit_filters VALUES ('ignore_sys', '{"ignore_tables" : "mysql.*"}'); +INSERT INTO mysql.server_audit_users VALUES ('%','','ignore_sys'); +INSERT INTO mysql.server_audit_users VALUES ('%','root','ignore_sys'); + +install plugin server_audit soname 'server_audit2'; +set global server_audit_logging=on; + +# this is done to make test deterministic +# so the above 'set' command is always logged before the 'create table t1' +-- disable_query_log +-- disable_result_log +select * from mysql.server_audit_filters; +select * from mysql.server_audit_users; +-- enable_result_log +-- enable_query_log + +connection master; +create table t1 (a int); +insert into t1 values (1); +truncate t1; +drop table t1; +sync_slave_with_master; + +set global server_audit_logging=off; + +truncate mysql.server_audit_filters; +truncate mysql.server_audit_users; +INSERT INTO mysql.server_audit_filters VALUES ('no_logging','false'); +INSERT INTO mysql.server_audit_users VALUES ('%','','no_logging'); + +set global server_audit_logging=on; + +connection master; +create table t1 (a int); +insert into t1 values (1); +truncate t1; +drop table t1; +sync_slave_with_master; + +set global server_audit_logging=off; +uninstall plugin server_audit; +truncate mysql.server_audit_filters; +truncate mysql.server_audit_users; +let $MYSQLD_DATADIR= `SELECT @@datadir`; +# replace the timestamp and the hostname with constant values +--replace_regex /[0-9]* [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\,[^,]*\,/TIME,HOSTNAME,/ /\,[1-9][0-9]*\,/,1,/ /\,[1-9][0-9]*/,ID/ /000001\\', [0-9]*,/#', POS,/ +cat_file $MYSQLD_DATADIR/server_audit.log; +remove_file $MYSQLD_DATADIR/server_audit.log; + +connection master; +--source include/rpl_end.inc diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 82bed1ccff2..f03e5780ad9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -297,7 +297,8 @@ static TYPELIB tc_heuristic_recover_typelib= }; const char *first_keyword= "first"; -const char *my_localhost= "localhost", *delayed_user= "DELAYED"; +const char *my_localhost= "localhost", + *delayed_user= "delayed", *slave_user= ""; bool opt_large_files= sizeof(my_off_t) > 4; static my_bool opt_autocommit; ///< for --autocommit command-line option diff --git a/sql/mysqld.h b/sql/mysqld.h index 8d26bcbb5f0..5fa8e22c2ab 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -264,7 +264,7 @@ extern time_t server_start_time, flush_status_time; extern char *opt_mysql_tmpdir, mysql_charsets_dir[]; extern size_t mysql_unpacked_real_data_home_len; extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list; -extern const char *first_keyword, *delayed_user; +extern const char *first_keyword, *delayed_user, *slave_user; extern MYSQL_PLUGIN_IMPORT const char *my_localhost; extern MYSQL_PLUGIN_IMPORT const char **errmesg; /* Error messages */ extern const char *myisam_recover_options_str; diff --git a/sql/slave.cc b/sql/slave.cc index 3726bc1a6f6..f70336e980a 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3511,6 +3511,7 @@ static int init_slave_thread(THD* thd, Master_info *mi, } thd->security_ctx->skip_grants(); + thd->security_ctx->user=(char*) slave_user; thd->slave_thread= 1; thd->connection_name= mi->connection_name; thd->variables.sql_log_slow= !MY_TEST(thd->variables.log_slow_disabled_statements & LOG_SLOW_DISABLE_SLAVE); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 39b1be87040..1c207cd54eb 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7532,7 +7532,7 @@ static bool can_grant_role(THD *thd, ACL_ROLE *role) { Security_context *sctx= thd->security_ctx; - if (!sctx->user) // replication + if (!sctx->is_user_defined()) // galera return true; ACL_USER *grantee= find_user_exact(sctx->priv_host, sctx->priv_user); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a358d9c3351..ad8e961d6d8 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -4504,7 +4504,7 @@ void Security_context::destroy() my_free((char*) host); host= NULL; } - if (user != delayed_user) + if (is_user_defined()) { my_free((char*) user); user= NULL; diff --git a/sql/sql_class.h b/sql/sql_class.h index a8ef8648210..f887a6cfa92 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1506,6 +1506,8 @@ public: */ bool check_access(const privilege_t want_access, bool match_any = false); bool is_priv_user(const char *user, const char *host); + bool is_user_defined() const + { return user && user != delayed_user && user != slave_user; }; }; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 9f1dee1f598..63c00f8614e 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2776,9 +2776,10 @@ static my_bool list_callback(THD *tmp, list_callback_arg *arg) thd_info->thread_id=tmp->thread_id; thd_info->os_thread_id=tmp->os_thread_id; - thd_info->user= arg->thd->strdup(tmp_sctx->user ? tmp_sctx->user : - (tmp->system_thread ? - "system user" : "unauthenticated user")); + thd_info->user= arg->thd->strdup(tmp_sctx->user && tmp_sctx->user != slave_user ? + tmp_sctx->user : + (tmp->system_thread ? + "system user" : "unauthenticated user")); if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) && arg->thd->security_ctx->host_or_ip[0]) { @@ -3225,7 +3226,7 @@ static my_bool processlist_callback(THD *tmp, processlist_callback_arg *arg) /* ID */ arg->table->field[0]->store((longlong) tmp->thread_id, TRUE); /* USER */ - val= tmp_sctx->user ? tmp_sctx->user : + val= tmp_sctx->user && tmp_sctx->user != slave_user ? tmp_sctx->user : (tmp->system_thread ? "system user" : "unauthenticated user"); arg->table->field[1]->store(val, strlen(val), cs); /* HOST */ From 0185ac64f390528ec89b4be6d970c4f5c54fbe08 Mon Sep 17 00:00:00 2001 From: Dave Gosselin Date: Thu, 11 Jan 2024 10:02:58 -0500 Subject: [PATCH 002/106] MDEV-30975 Wrong result with cross Join given join order For queries with derived tables populated having some side-effect, we will fill such a derived table more than once, but without clearing its rows. Consequently it will have duplicate rows. An example query exhibiting the problem is SELECT STRAIGHT_JOIN c1 FROM t1 JOIN (SELECT @a := 0) x; Since mysql_derived_fill will, for UNCACHEABLE_DEPENDENT tables, drop all rows and repopulate, we relax the condition at line 1204: rather than assume all uncacheable values prevent early return, we now allow an early return for uncacheable values other than UNCACHEABLE_DEPENDENT. In general, we only populate derived tables once unless they're dependent tables. --- mysql-test/main/join.result | 56 +++++++++++++++++++++++++++++++++++++ mysql-test/main/join.test | 46 ++++++++++++++++++++++++++++++ sql/sql_derived.cc | 9 ++++-- 3 files changed, 109 insertions(+), 2 deletions(-) diff --git a/mysql-test/main/join.result b/mysql-test/main/join.result index e4b92b4234b..07579a065f9 100644 --- a/mysql-test/main/join.result +++ b/mysql-test/main/join.result @@ -3423,6 +3423,62 @@ SELECT COUNT(*) FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2. COUNT(*) 2 DROP TABLE t1, t2, t3; +# +# MDEV-30975: Wrong result with cross Join given join order +# +CREATE TABLE `t1` ( +`t1_seq` INT NOT NULL, +`c1` VARCHAR(10) NOT NULL , +PRIMARY KEY (`t1_seq`) USING BTREE +); +CREATE TABLE `t2` ( +`t2_seq` INT NOT NULL, +`t1_seq` INT NOT NULL, +`c2` VARCHAR(10) NOT NULL , +PRIMARY KEY (`t2_seq`, `t1_seq`) USING BTREE +); +INSERT INTO t1 VALUES(1, 'A'); +INSERT INTO t2 VALUES(1, 1, 'T2-1-1'); +INSERT INTO t2 VALUES(2, 1, 'T2-1-2'); +INSERT INTO t2 VALUES(3, 1, 'T2-1-3'); +SELECT LPAD(@rownum := @rownum + 1, 8, 0) AS str_num +, t1.t1_seq +, t2.t2_seq +, t1.c1 +, t2.c2 +FROM t1 +INNER JOIN t2 ON (t1.t1_seq = t2.t1_seq) +CROSS JOIN ( SELECT @rownum := 0 ) X; +str_num t1_seq t2_seq c1 c2 +00000001 1 1 A T2-1-1 +00000002 1 2 A T2-1-2 +00000003 1 3 A T2-1-3 +SELECT STRAIGHT_JOIN LPAD(@rownum := @rownum + 1, 8, 0) AS str_num +, t1.t1_seq +, t2.t2_seq +, t1.c1 +, t2.c2 +FROM t1 +INNER JOIN t2 ON (t1.t1_seq = t2.t1_seq) +CROSS JOIN ( SELECT @rownum := 0 ) X; +str_num t1_seq t2_seq c1 c2 +00000001 1 1 A T2-1-1 +00000002 1 2 A T2-1-2 +00000003 1 3 A T2-1-3 +SELECT STRAIGHT_JOIN * FROM t1 JOIN t2 ON (t1.t1_seq = t2.t1_seq) JOIN (SELECT @a := 0) x; +t1_seq c1 t2_seq t1_seq c2 @a := 0 +1 A 1 1 T2-1-1 0 +1 A 2 1 T2-1-2 0 +1 A 3 1 T2-1-3 0 +SELECT * FROM t1 JOIN t2 ON (t1.t1_seq = t2.t1_seq) JOIN (SELECT @a := 0) x; +t1_seq c1 t2_seq t1_seq c2 @a := 0 +1 A 1 1 T2-1-1 0 +1 A 2 1 T2-1-2 0 +1 A 3 1 T2-1-3 0 +SELECT STRAIGHT_JOIN c1 FROM t1 JOIN (SELECT @a := 0) x; +c1 +A +DROP TABLE t1, t2; # End of 10.5 tests # # MDEV-31449: Assertion s->table->opt_range_condition_rows <= s->found_records diff --git a/mysql-test/main/join.test b/mysql-test/main/join.test index 2f94daf4616..f8abc3fac22 100644 --- a/mysql-test/main/join.test +++ b/mysql-test/main/join.test @@ -1838,6 +1838,52 @@ SELECT * FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2.b; SELECT COUNT(*) FROM t1 LEFT JOIN (t2 LEFT JOIN t3 ON t2.b = t3.c) ON t1.a = t2.b; DROP TABLE t1, t2, t3; +--echo # +--echo # MDEV-30975: Wrong result with cross Join given join order +--echo # + +CREATE TABLE `t1` ( + `t1_seq` INT NOT NULL, + `c1` VARCHAR(10) NOT NULL , + PRIMARY KEY (`t1_seq`) USING BTREE +); + +CREATE TABLE `t2` ( + `t2_seq` INT NOT NULL, + `t1_seq` INT NOT NULL, + `c2` VARCHAR(10) NOT NULL , + PRIMARY KEY (`t2_seq`, `t1_seq`) USING BTREE +); + +INSERT INTO t1 VALUES(1, 'A'); +INSERT INTO t2 VALUES(1, 1, 'T2-1-1'); +INSERT INTO t2 VALUES(2, 1, 'T2-1-2'); +INSERT INTO t2 VALUES(3, 1, 'T2-1-3'); + +SELECT LPAD(@rownum := @rownum + 1, 8, 0) AS str_num + , t1.t1_seq + , t2.t2_seq + , t1.c1 + , t2.c2 + FROM t1 + INNER JOIN t2 ON (t1.t1_seq = t2.t1_seq) + CROSS JOIN ( SELECT @rownum := 0 ) X; + +SELECT STRAIGHT_JOIN LPAD(@rownum := @rownum + 1, 8, 0) AS str_num + , t1.t1_seq + , t2.t2_seq + , t1.c1 + , t2.c2 + FROM t1 + INNER JOIN t2 ON (t1.t1_seq = t2.t1_seq) + CROSS JOIN ( SELECT @rownum := 0 ) X; + +SELECT STRAIGHT_JOIN * FROM t1 JOIN t2 ON (t1.t1_seq = t2.t1_seq) JOIN (SELECT @a := 0) x; +SELECT * FROM t1 JOIN t2 ON (t1.t1_seq = t2.t1_seq) JOIN (SELECT @a := 0) x; +SELECT STRAIGHT_JOIN c1 FROM t1 JOIN (SELECT @a := 0) x; + +DROP TABLE t1, t2; + --echo # End of 10.5 tests --echo # diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index e0f3ec18bf0..a721875051b 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1201,8 +1201,12 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) (derived->alias.str ? derived->alias.str : ""), derived->get_unit())); - if (unit->executed && !unit->uncacheable && !unit->describe && - !derived_is_recursive) + /* + Only fill derived tables once, unless the derived table is dependent in + which case we will delete all of its rows and refill it below. + */ + if (unit->executed && !(unit->uncacheable & UNCACHEABLE_DEPENDENT) && + !unit->describe && !derived_is_recursive) DBUG_RETURN(FALSE); /*check that table creation passed without problems. */ DBUG_ASSERT(derived->table && derived->table->is_created()); @@ -1261,6 +1265,7 @@ bool mysql_derived_fill(THD *thd, LEX *lex, TABLE_LIST *derived) } else { + DBUG_ASSERT(!unit->executed || (unit->uncacheable & UNCACHEABLE_DEPENDENT)); SELECT_LEX *first_select= unit->first_select(); unit->set_limit(unit->global_parameters()); if (unit->lim.is_unlimited()) From 8a1904d7825f9897cd237fc6a1d8a57a9f2108de Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 25 Jan 2024 16:07:51 +1100 Subject: [PATCH 003/106] MDEV-33301 memlock with systemd still not working CapabilityBoundingSet included CAP_IPC_LOCK in MDEV-9095, however it requires that the executable has the capability marked in extended attributes also. The alternate to this is raising the RLIMIT_MEMLOCK for the service/ process to be able to complete the mlockall system call. This needs to be adjusted to whatever the MariaDB server was going to allocate. Rather than leave the non-obvious mapping of settings and tuning, add the capability so its easier for the user. We set the capability, if possible, but may never be used depending on user settings. As such in the Debian postinst script, don't complain if this fails. The CAP_IPC_LOCK also facilitates the mmaping of huge memory pages. (see man mmap), like mariadb uses with --large-pages. --- cmake/cpack_rpm.cmake | 1 + debian/mariadb-server-core-10.5.postinst | 26 +++++++++++++++++++ support-files/policy/apparmor/usr.sbin.mysqld | 1 + .../policy/selinux/mariadb-server.te | 4 ++- 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 debian/mariadb-server-core-10.5.postinst diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 65a739dc03e..414b4f6a902 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -163,6 +163,7 @@ SET(CPACK_RPM_server_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*" "%config(noreplace) ${INSTALL_SYSCONFDIR}/logrotate.d/mysql" + "%caps(cap_ipc_lock=pe) %{_sbindir}/mysqld" ) SET(CPACK_RPM_common_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONFDIR}/my.cnf") SET(CPACK_RPM_shared_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*") diff --git a/debian/mariadb-server-core-10.5.postinst b/debian/mariadb-server-core-10.5.postinst new file mode 100644 index 00000000000..5f79bed2402 --- /dev/null +++ b/debian/mariadb-server-core-10.5.postinst @@ -0,0 +1,26 @@ +#!/bin/sh + +set -e + +# inspired by iputils-ping +# +# cap_ipc_lock is required if a user wants to use --memlock +# and has insufficient RLIMIT_MEMLOCK (MDEV-33301) + +PROGRAM=$(dpkg-divert --truename /usr/sbin/mysqld) + +if [ "$1" = configure ]; then + # If we have setcap installed, try setting + # which allows us to install our binaries without the setuid + # bit. + if command -v setcap > /dev/null; then + if ! setcap cap_ipc_lock+ep "$PROGRAM"; then + echo "Setcap failed on $PROGRAM, required with --memlock if insufficent RLIMIT_MEMLOCK" >&2 + fi + fi +fi + + +#DEBHELPER# + +exit 0 diff --git a/support-files/policy/apparmor/usr.sbin.mysqld b/support-files/policy/apparmor/usr.sbin.mysqld index c60ecd28531..732f4b3a97a 100644 --- a/support-files/policy/apparmor/usr.sbin.mysqld +++ b/support-files/policy/apparmor/usr.sbin.mysqld @@ -14,6 +14,7 @@ capability chown, capability dac_override, + capability ipc_lock, capability setgid, capability setuid, capability sys_rawio, diff --git a/support-files/policy/selinux/mariadb-server.te b/support-files/policy/selinux/mariadb-server.te index 89846063506..ba53c97d4a8 100644 --- a/support-files/policy/selinux/mariadb-server.te +++ b/support-files/policy/selinux/mariadb-server.te @@ -25,7 +25,7 @@ require { class lnk_file read; class process { getattr signull }; class unix_stream_socket connectto; - class capability { sys_resource sys_nice }; + class capability { ipc_lock sys_resource sys_nice }; class tcp_socket { name_bind name_connect }; class file { execute setattr read create getattr execute_no_trans write ioctl open append unlink }; class sock_file { create unlink getattr }; @@ -87,6 +87,8 @@ allow mysqld_t bin_t:file { getattr read execute open execute_no_trans ioctl }; # MariaDB additions allow mysqld_t self:process setpgid; +allow mysqld_t self:capability { ipc_lock }; + # This rule allows port tcp/4444 allow mysqld_t kerberos_port_t:tcp_socket { name_bind name_connect }; # This rule allows port tcp/4567 (tram_port_t may not be available on From c73c6aea637e2002d7b64ea9f7fdb594cc2ab392 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sun, 11 Feb 2024 11:57:42 +0100 Subject: [PATCH 004/106] MDEV-33426: Aria temptables wrong thread-specific memory accounting in slave thread Aria temporary tables account allocated memory as specific to the current THD. But this fails for slave threads, where the temporary tables need to be detached from any specific THD. Introduce a new flag to mark temporary tables in replication as "global", and use that inside Aria to not account memory allocations as thread specific for such tables. Based on original suggestion by Monty. Reviewed-by: Monty Signed-off-by: Kristian Nielsen --- include/my_base.h | 7 ++++++ .../suite/rpl/r/rpl_parallel_temptable.result | 18 ++++++++++++++ .../suite/rpl/t/rpl_parallel_temptable.test | 24 +++++++++++++++++++ sql/handler.cc | 15 +++++++++++- sql/handler.h | 6 +++++ sql/temporary_tables.cc | 11 ++++++--- storage/maria/ha_maria.cc | 2 ++ storage/maria/ma_bitmap.c | 2 +- storage/maria/ma_blockrec.c | 12 ++++------ storage/maria/ma_check.c | 4 ++-- storage/maria/ma_create.c | 2 +- storage/maria/ma_dynrec.c | 8 +++---- storage/maria/ma_extra.c | 2 +- storage/maria/ma_open.c | 14 ++++++----- storage/maria/ma_packrec.c | 8 +++---- storage/maria/maria_def.h | 5 ++++ 16 files changed, 110 insertions(+), 30 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index 32e3aa06d27..7a57fbf0ff7 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -49,6 +49,7 @@ #define HA_OPEN_MERGE_TABLE 2048U #define HA_OPEN_FOR_CREATE 4096U #define HA_OPEN_FOR_DROP (1U << 13) /* Open part of drop */ +#define HA_OPEN_GLOBAL_TMP_TABLE (1U << 14) /* TMP table used by repliction */ /* Allow opening even if table is incompatible as this is for ALTER TABLE which @@ -367,6 +368,12 @@ enum ha_base_keytype { #define HA_CREATE_INTERNAL_TABLE 256U #define HA_PRESERVE_INSERT_ORDER 512U #define HA_CREATE_NO_ROLLBACK 1024U +/* + A temporary table that can be used by different threads, eg. replication + threads. This flag ensure that memory is not allocated with THREAD_SPECIFIC, + as we do for other temporary tables. +*/ +#define HA_CREATE_GLOBAL_TMP_TABLE 2048U /* Flags used by start_bulk_insert */ diff --git a/mysql-test/suite/rpl/r/rpl_parallel_temptable.result b/mysql-test/suite/rpl/r/rpl_parallel_temptable.result index 1a1c12f836d..c0ccdd3d4ff 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_temptable.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_temptable.result @@ -203,6 +203,24 @@ a b include/stop_slave.inc SET GLOBAL slave_parallel_mode=@old_mode; include/start_slave.inc +*** MDEV33426: Memory allocation accounting incorrect for replicated temptable +connection server_1; +CREATE TEMPORARY TABLE t5 (a int) ENGINE=Aria; +CREATE TEMPORARY TABLE t6 (a int) ENGINE=Heap; +INSERT INTO t5 VALUES (1); +INSERT INTO t6 VALUES (2); +connection server_2; +include/stop_slave.inc +connection server_1; +INSERT INTO t1 SELECT a+40, 5 FROM t5; +INSERT INTO t1 SELECT a+40, 6 FROM t6; +DROP TABLE t5, t6; +connection server_2; +include/start_slave.inc +SELECT * FROM t1 WHERE a>=40 ORDER BY a; +a b +41 5 +42 6 connection server_2; include/stop_slave.inc SET GLOBAL slave_parallel_threads=@old_parallel_threads; diff --git a/mysql-test/suite/rpl/t/rpl_parallel_temptable.test b/mysql-test/suite/rpl/t/rpl_parallel_temptable.test index edb854842e1..eb5f88a1c15 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_temptable.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_temptable.test @@ -265,6 +265,30 @@ SET GLOBAL slave_parallel_mode=@old_mode; --source include/start_slave.inc +--echo *** MDEV33426: Memory allocation accounting incorrect for replicated temptable +--connection server_1 +CREATE TEMPORARY TABLE t5 (a int) ENGINE=Aria; +CREATE TEMPORARY TABLE t6 (a int) ENGINE=Heap; +INSERT INTO t5 VALUES (1); +INSERT INTO t6 VALUES (2); +--save_master_pos + +--connection server_2 +--sync_with_master +--source include/stop_slave.inc + +--connection server_1 +INSERT INTO t1 SELECT a+40, 5 FROM t5; +INSERT INTO t1 SELECT a+40, 6 FROM t6; +DROP TABLE t5, t6; + +--save_master_pos + +--connection server_2 +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 WHERE a>=40 ORDER BY a; + # Clean up. --connection server_2 diff --git a/sql/handler.cc b/sql/handler.cc index 486beb56788..4421d222add 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2827,6 +2827,17 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode, DBUG_ASSERT(alloc_root_inited(&table->mem_root)); set_partitions_to_open(partitions_to_open); + internal_tmp_table= MY_TEST(test_if_locked & HA_OPEN_INTERNAL_TABLE); + + if (!internal_tmp_table && (test_if_locked & HA_OPEN_TMP_TABLE) && + current_thd->slave_thread) + { + /* + This is a temporary table used by replication that is not attached + to a THD. Mark it as a global temporary table. + */ + test_if_locked|= HA_OPEN_GLOBAL_TMP_TABLE; + } if (unlikely((error=open(name,mode,test_if_locked)))) { @@ -2872,7 +2883,6 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode, cached_table_flags= table_flags(); } reset_statistics(); - internal_tmp_table= MY_TEST(test_if_locked & HA_OPEN_INTERNAL_TABLE); DBUG_RETURN(error); } @@ -4857,6 +4867,9 @@ handler::ha_create(const char *name, TABLE *form, HA_CREATE_INFO *info_arg) { DBUG_ASSERT(m_lock_type == F_UNLCK); mark_trx_read_write(); + if ((info_arg->options & HA_LEX_CREATE_TMP_TABLE) && + current_thd->slave_thread) + info_arg->options|= HA_LEX_CREATE_GLOBAL_TMP_TABLE; int error= create(name, form, info_arg); if (!error && !(info_arg->options & (HA_LEX_CREATE_TMP_TABLE | HA_CREATE_TMP_ALTER))) diff --git a/sql/handler.h b/sql/handler.h index 6085111bc25..1ec1164ce8f 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -465,6 +465,12 @@ enum enum_alter_inplace_result { #define HA_LEX_CREATE_SEQUENCE 16U #define HA_VERSIONED_TABLE 32U #define HA_SKIP_KEY_SORT 64U +/* + A temporary table that can be used by different threads, eg. replication + threads. This flag ensure that memory is not allocated with THREAD_SPECIFIC, + as we do for other temporary tables. +*/ +#define HA_LEX_CREATE_GLOBAL_TMP_TABLE 128U #define HA_MAX_REC_LENGTH 65535 diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index 4ffae3d53bf..294d8d304db 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -1115,11 +1115,16 @@ TABLE *THD::open_temporary_table(TMP_TABLE_SHARE *share, DBUG_RETURN(NULL); /* Out of memory */ } + uint flags= ha_open_options | (open_options & HA_OPEN_FOR_CREATE); + /* + In replication, temporary tables are not confined to a single + thread/THD. + */ + if (slave_thread) + flags|= HA_OPEN_GLOBAL_TMP_TABLE; if (open_table_from_share(this, share, &alias, (uint) HA_OPEN_KEYFILE, - EXTRA_RECORD, - (ha_open_options | - (open_options & HA_OPEN_FOR_CREATE)), + EXTRA_RECORD, flags, table, false)) { my_free(table); diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 6639fc39caf..f74abf30196 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -3188,6 +3188,8 @@ int ha_maria::create(const char *name, TABLE *table_arg, if (ha_create_info->tmp_table()) { create_flags|= HA_CREATE_TMP_TABLE | HA_CREATE_DELAY_KEY_WRITE; + if (ha_create_info->options & HA_LEX_CREATE_GLOBAL_TMP_TABLE) + create_flags|= HA_CREATE_GLOBAL_TMP_TABLE; create_info.transactional= 0; } if (ha_create_info->options & HA_CREATE_KEEP_FILES) diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index 4f3a2ae5f89..c55737057bf 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -232,7 +232,7 @@ my_bool _ma_bitmap_init(MARIA_SHARE *share, File file, uint max_page_size; MARIA_FILE_BITMAP *bitmap= &share->bitmap; uint size= share->block_size; - myf flag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); + myf flag= MY_WME | share->malloc_flag; pgcache_page_no_t first_bitmap_with_space; #ifndef DBUG_OFF /* We want to have a copy of the bitmap to be able to print differences */ diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 436f07ff7e3..615ff875249 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -485,7 +485,7 @@ my_bool _ma_init_block_record(MARIA_HA *info) { MARIA_ROW *row= &info->cur_row, *new_row= &info->new_row; MARIA_SHARE *share= info->s; - myf flag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); + myf flag= MY_WME | share->malloc_flag; uint default_extents; DBUG_ENTER("_ma_init_block_record"); @@ -2642,7 +2642,6 @@ static my_bool write_block_record(MARIA_HA *info, LSN lsn; my_off_t position; uint save_my_errno; - myf myflag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); DBUG_ENTER("write_block_record"); head_block= bitmap_blocks->block; @@ -2709,7 +2708,7 @@ static my_bool write_block_record(MARIA_HA *info, for every data segment we want to store. */ if (_ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, - row->head_length, myflag)) + row->head_length, MY_WME | share->malloc_flag)) DBUG_RETURN(1); tmp_data_used= 0; /* Either 0 or last used uchar in 'data' */ @@ -4719,7 +4718,7 @@ int _ma_read_block_record2(MARIA_HA *info, uchar *record, MARIA_EXTENT_CURSOR extent; MARIA_COLUMNDEF *column, *end_column; MARIA_ROW *cur_row= &info->cur_row; - myf myflag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); + myf myflag= MY_WME | share->malloc_flag; DBUG_ENTER("_ma_read_block_record2"); start_of_data= data; @@ -5052,7 +5051,6 @@ static my_bool read_row_extent_info(MARIA_HA *info, uchar *buff, uint flag, row_extents, row_extents_size; uint field_lengths __attribute__ ((unused)); uchar *extents, *end; - myf myflag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); DBUG_ENTER("read_row_extent_info"); if (!(data= get_record_position(share, buff, @@ -5076,7 +5074,7 @@ static my_bool read_row_extent_info(MARIA_HA *info, uchar *buff, if (info->cur_row.extents_buffer_length < row_extents_size && _ma_alloc_buffer(&info->cur_row.extents, &info->cur_row.extents_buffer_length, - row_extents_size, myflag)) + row_extents_size, MY_WME | share->malloc_flag)) DBUG_RETURN(1); memcpy(info->cur_row.extents, data, ROW_EXTENT_SIZE); data+= ROW_EXTENT_SIZE; @@ -5247,7 +5245,7 @@ my_bool _ma_cmp_block_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, my_bool _ma_scan_init_block_record(MARIA_HA *info) { MARIA_SHARE *share= info->s; - myf flag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); + myf flag= MY_WME | share->malloc_flag; DBUG_ENTER("_ma_scan_init_block_record"); DBUG_ASSERT(info->dfile.file == share->bitmap.file.file); diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 9b3c14d40e3..e53f77daf96 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -1271,7 +1271,6 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend, ulong UNINIT_VAR(left_length); uint b_type; char llbuff[22],llbuff2[22],llbuff3[22]; - myf myflag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); DBUG_ENTER("check_dynamic_record"); pos= 0; @@ -1379,7 +1378,8 @@ static int check_dynamic_record(HA_CHECK *param, MARIA_HA *info, int extend, { if (_ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, block_info.rec_len + - share->base.extra_rec_buff_size, myflag)) + share->base.extra_rec_buff_size, + MY_WME | share->malloc_flag)) { _ma_check_print_error(param, diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 3352a494d16..4399b435d5d 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -103,7 +103,7 @@ int maria_create(const char *name, enum data_file_type datafile_type, DBUG_ASSERT(maria_inited); - if (flags & HA_CREATE_TMP_TABLE) + if ((flags & HA_CREATE_TMP_TABLE) && !(flags & HA_CREATE_GLOBAL_TMP_TABLE)) common_flag|= MY_THREAD_SPECIFIC; if (!ci) diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c index 829e5b5cd02..2d846b81462 100644 --- a/storage/maria/ma_dynrec.c +++ b/storage/maria/ma_dynrec.c @@ -1478,7 +1478,6 @@ int _ma_read_dynamic_record(MARIA_HA *info, uchar *buf, uchar *UNINIT_VAR(to); uint UNINIT_VAR(left_length); MARIA_SHARE *share= info->s; - myf flag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); DBUG_ENTER("_ma_read_dynamic_record"); if (filepos == HA_OFFSET_ERROR) @@ -1515,7 +1514,8 @@ int _ma_read_dynamic_record(MARIA_HA *info, uchar *buf, { if (_ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, block_info.rec_len + - share->base.extra_rec_buff_size, flag)) + share->base.extra_rec_buff_size, + MY_WME | share->malloc_flag)) goto err; } to= info->rec_buff; @@ -1771,7 +1771,6 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, uchar *UNINIT_VAR(to); MARIA_BLOCK_INFO block_info; MARIA_SHARE *share= info->s; - myf flag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); DBUG_ENTER("_ma_read_rnd_dynamic_record"); #ifdef MARIA_EXTERNAL_LOCKING @@ -1862,7 +1861,8 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info, { if (_ma_alloc_buffer(&info->rec_buff, &info->rec_buff_size, block_info.rec_len + - share->base.extra_rec_buff_size, flag)) + share->base.extra_rec_buff_size, + MY_WME | share->malloc_flag)) goto err; } to= info->rec_buff; diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index fe2a4c9b8ac..106df5c5214 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -539,7 +539,7 @@ int maria_reset(MARIA_HA *info) { int error= 0; MARIA_SHARE *share= info->s; - myf flag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); + myf flag= MY_WME | share->malloc_flag; DBUG_ENTER("maria_reset"); /* Free buffers and reset the following flags: diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c index 7b59351e24b..241994cc7f0 100644 --- a/storage/maria/ma_open.c +++ b/storage/maria/ma_open.c @@ -98,7 +98,7 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, uint errpos; MARIA_HA info,*m_info; my_bitmap_map *changed_fields_bitmap; - myf flag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); + myf flag= MY_WME | share->malloc_flag; DBUG_ENTER("maria_clone_internal"); errpos= 0; @@ -265,7 +265,9 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) uint i,j,len,errpos,head_length,base_pos,keys, realpath_err, key_parts,base_key_parts,unique_key_parts,fulltext_keys,uniques; uint internal_table= MY_TEST(open_flags & HA_OPEN_INTERNAL_TABLE); - myf common_flag= open_flags & HA_OPEN_TMP_TABLE ? MY_THREAD_SPECIFIC : 0; + myf common_flag= (((open_flags & HA_OPEN_TMP_TABLE) && + !(open_flags & HA_OPEN_GLOBAL_TMP_TABLE)) ? + MY_THREAD_SPECIFIC : 0); uint file_version; size_t info_length; char name_buff[FN_REFLEN], org_name[FN_REFLEN], index_name[FN_REFLEN], @@ -885,9 +887,10 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags) if (open_flags & HA_OPEN_TMP_TABLE || share->options & HA_OPTION_TMP_TABLE) { - common_flag|= MY_THREAD_SPECIFIC; share->options|= HA_OPTION_TMP_TABLE; share->temporary= share->delay_key_write= 1; + share->malloc_flag= + (open_flags & HA_OPEN_GLOBAL_TMP_TABLE) ? 0 : MY_THREAD_SPECIFIC; share->write_flag=MYF(MY_NABP); share->w_locks++; /* We don't have to update status */ share->tot_locks++; @@ -1954,9 +1957,8 @@ void _ma_set_index_pagecache_callbacks(PAGECACHE_FILE *file, int _ma_open_datafile(MARIA_HA *info, MARIA_SHARE *share) { - myf flags= MY_WME | (share->mode & O_NOFOLLOW ? MY_NOSYMLINKS : 0); - if (share->temporary) - flags|= MY_THREAD_SPECIFIC; + myf flags= MY_WME | (share->mode & O_NOFOLLOW ? MY_NOSYMLINKS : 0) | + share->malloc_flag; DEBUG_SYNC_C("mi_open_datafile"); info->dfile.file= share->bitmap.file.file= mysql_file_open(key_file_dfile, share->data_file_name.str, diff --git a/storage/maria/ma_packrec.c b/storage/maria/ma_packrec.c index d1c30a57146..3f0f110e258 100644 --- a/storage/maria/ma_packrec.c +++ b/storage/maria/ma_packrec.c @@ -1414,7 +1414,6 @@ uint _ma_pack_get_block_info(MARIA_HA *maria, MARIA_BIT_BUFF *bit_buff, uchar *header= info->header; uint head_length,UNINIT_VAR(ref_length); MARIA_SHARE *share= maria->s; - myf flag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); if (file >= 0) { @@ -1441,7 +1440,8 @@ uint _ma_pack_get_block_info(MARIA_HA *maria, MARIA_BIT_BUFF *bit_buff, */ if (_ma_alloc_buffer(rec_buff_p, rec_buff_size_p, info->rec_len + info->blob_len + - share->base.extra_rec_buff_size, flag)) + share->base.extra_rec_buff_size, + MY_WME | share->malloc_flag)) return BLOCK_FATAL_ERROR; /* not enough memory */ bit_buff->blob_pos= *rec_buff_p + info->rec_len; bit_buff->blob_end= bit_buff->blob_pos + info->blob_len; @@ -1583,7 +1583,6 @@ _ma_mempack_get_block_info(MARIA_HA *maria, uchar *header) { MARIA_SHARE *share= maria->s; - myf flag= MY_WME | (share->temporary ? MY_THREAD_SPECIFIC : 0); header+= read_pack_length((uint) share->pack.version, header, &info->rec_len); @@ -1593,7 +1592,8 @@ _ma_mempack_get_block_info(MARIA_HA *maria, &info->blob_len); /* _ma_alloc_rec_buff sets my_errno on error */ if (_ma_alloc_buffer(rec_buff_p, rec_buff_size_p, - info->blob_len + share->base.extra_rec_buff_size, flag)) + info->blob_len + share->base.extra_rec_buff_size, + MY_WME | share->malloc_flag)) return 0; /* not enough memory */ bit_buff->blob_pos= *rec_buff_p; bit_buff->blob_end= *rec_buff_p + info->blob_len; diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index f4799eef379..3ac449422c8 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -454,6 +454,11 @@ typedef struct st_maria_share ulong max_pack_length; ulong state_diff_length; uint rec_reflength; /* rec_reflength in use now */ + /* + Extra flag to use for my_malloc(); set to MY_THREAD_SPECIFIC for temporary + tables whose memory allocation should be accounted to the current THD. + */ + uint malloc_flag; uint keypage_header; uint32 ftkeys; /* Number of distinct full-text keys + 1 */ From fdaa7a96edb1b958d755ac1b85925eb9b548daeb Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Mon, 12 Feb 2024 12:00:58 +0100 Subject: [PATCH 005/106] MDEV-33443: Unsafe use of LOCK_thd_kill in my_malloc_size_cb_func() my_malloc_size_cb_func() can be called from contexts where it is not safe to wait for LOCK_thd_kill, for example while holding LOCK_plugin. This could lead to (probably very unlikely) deadlock of the server. Fix by skipping the enforcement of --max-session-mem-used in the rare cases when LOCK_thd_kill cannot be obtained. The limit will instead be enforced on the following memory allocation. This does not significantly degrade the behaviour of --max-session-mem-used; that limit is in any case only enforced "softly", not taking effect until the next point at which the thread does a check_killed(). Reviewed-by: Monty Signed-off-by: Kristian Nielsen --- sql/mysqld.cc | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5713045056d..50b2698ccba 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3789,20 +3789,35 @@ static void my_malloc_size_cb_func(long long size, my_bool is_thread_specific) thd->status_var.local_memory_used > (int64)thd->variables.max_mem_used && likely(!thd->killed) && !thd->get_stmt_da()->is_set()) { - /* Ensure we don't get called here again */ - char buf[50], *buf2; - thd->set_killed(KILL_QUERY); - my_snprintf(buf, sizeof(buf), "--max-session-mem-used=%llu", - thd->variables.max_mem_used); - if ((buf2= (char*) thd->alloc(256))) - { - my_snprintf(buf2, 256, ER_THD(thd, ER_OPTION_PREVENTS_STATEMENT), buf); - thd->set_killed(KILL_QUERY, ER_OPTION_PREVENTS_STATEMENT, buf2); - } - else - { - thd->set_killed(KILL_QUERY, ER_OPTION_PREVENTS_STATEMENT, - "--max-session-mem-used"); + /* + Ensure we don't get called here again. + + It is not safe to wait for LOCK_thd_kill here, as we could be called + from almost any context. For example while LOCK_plugin is being held; + but THD::awake() locks LOCK_thd_kill and LOCK_plugin in the opposite + order (MDEV-33443). + + So ignore the max_mem_used limit in the unlikely case we cannot obtain + LOCK_thd_kill here (the limit will be enforced on the next allocation). + */ + if (!mysql_mutex_trylock(&thd->LOCK_thd_kill)) { + char buf[50], *buf2; + thd->set_killed_no_mutex(KILL_QUERY); + my_snprintf(buf, sizeof(buf), "--max-session-mem-used=%llu", + thd->variables.max_mem_used); + if ((buf2= (char*) thd->alloc(256))) + { + my_snprintf(buf2, 256, + ER_THD(thd, ER_OPTION_PREVENTS_STATEMENT), buf); + thd->set_killed_no_mutex(KILL_QUERY, + ER_OPTION_PREVENTS_STATEMENT, buf2); + } + else + { + thd->set_killed_no_mutex(KILL_QUERY, ER_OPTION_PREVENTS_STATEMENT, + "--max-session-mem-used"); + } + mysql_mutex_unlock(&thd->LOCK_thd_kill); } } DBUG_ASSERT((longlong) thd->status_var.local_memory_used >= 0 || From 5707f1efda643f94ea6b38051e94d427f6786c2c Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Thu, 15 Feb 2024 10:41:23 +0100 Subject: [PATCH 006/106] MDEV-33468: Crash due to missing stack overrun check in two recursive functions Thanks to Yury Chaikou for finding this problem (and the fix). Reviewed-by: Monty Signed-off-by: Kristian Nielsen --- sql/item.cc | 6 +++++- sql/sql_select.cc | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/sql/item.cc b/sql/item.cc index 383c9e4b68e..07463b202f9 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -27,6 +27,7 @@ #include "sp_rcontext.h" #include "sp_head.h" #include "sql_trigger.h" +#include "sql_parse.h" #include "sql_select.h" #include "sql_show.h" // append_identifier #include "sql_view.h" // VIEW_ANY_SQL @@ -485,7 +486,10 @@ void Item::print_parenthesised(String *str, enum_query_type query_type, bool need_parens= precedence() < parent_prec; if (need_parens) str->append('('); - print(str, query_type); + if (check_stack_overrun(current_thd, STACK_MIN_SIZE, NULL)) + str->append(""); + else + print(str, query_type); if (need_parens) str->append(')'); } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 978bd4ebe26..9e8b8e4ebe0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -17662,6 +17662,12 @@ Item_cond::remove_eq_conds(THD *thd, Item::cond_result *cond_value, bool and_level= functype() == Item_func::COND_AND_FUNC; List *cond_arg_list= argument_list(); + if (check_stack_overrun(thd, STACK_MIN_SIZE, NULL)) + { + *cond_value= Item::COND_FALSE; + return (COND*) 0; // Fatal error flag is set! + } + if (and_level) { /* From 8a505980c52e9d56e3aa523d17b6c1bc1f259ce5 Mon Sep 17 00:00:00 2001 From: Xiaotong Niu Date: Fri, 27 Oct 2023 12:44:57 +0800 Subject: [PATCH 007/106] MDEV-28430: Fix memory barrier missing of lf_alloc on Arm64 When testing MariaDB on Arm64, a stall issue will occur, jira link: https://jira.mariadb.org/browse/MDEV-28430. The stall occurs because of an unexpected circular reference in the LF_PINS->purgatory list which is traversed in lf_pinbox_real_free(). We found that on Arm64, ABA problem in LF_ALLOCATOR->top list was not solved, and various undefined problems will occur, including circular reference in LF_PINS->purgatory list. The following codes are used to solve ABA problem, code copied from below link. https://github.com/MariaDB/server/blob/cb4c2713553c5f522d2a4ebf186c6505384c748d/mysys/lf_alloc-pin.c#L501-#L505 do { 503 node= allocator->top; 504 lf_pin(pins, 0, node); 505 } while (node != allocator->top && LF_BACKOFF()); 1. ABA problem on Arm64 Combine the below steps to analyze how ABA problem occur on Arm64, the relevant codes in steps are simplified, code line numbers below are in MariaDB v10.4. ------------------------------------------------------------------------ Abnormal case. Initial state: pin = 0, top = A, top list: A->B T1 T2 step1. write top=B //seq-cst, #L517 step2. write A->next= "any" step3. read pin==0 //relaxed, #L295 step1. write pin=A //seq-cst, #L504 step2. read old value of top==A //relaxed, #L505 step3. next=A->next="any" //#L517 step4. write A->next=B,top=A //#L420-435 step4. CAS(top,A,next) //#L517 step5. write pin=0 //#L521 ------------------------------------------------------------------------ Above case is due to T1.step2 reading the old value of top, causing "T1.step3, T1.step4" and "T2.step4" to occur at the same time, in other words, they are not mutually exclusive. It may happen that T2.step4 is sandwiched between T1.step3 and T1.step4, which cause top to be updated to "any", which may be in-use or invalid address. 2. Analyze above issue with Dekker's algorithm Above problem can be mapped to Dekker's algorithm, link is as below https://en.wikipedia.org/wiki/Dekker%27s_algorithm. The following extracts the read and write operations on 'top' and 'pin', and maps them to Dekker's algorithm to analyze the root cause. ------------------------------------------------------------------------ Initial state: top = A, pin = 0 T1 T2 store_seq_cst(pin, A) // write pin store_seq_cst(top, B) //write top rt= load_relaxed(top) // read top rp= load_relaxed(pin) //read pin if (rt == A && rp == 0) printf("oops\n"); // will "oops" be printed? ------------------------------------------------------------------------ How T1 and T2 enter their critical section: (1) T1, write pin, if T1 reads that top has not been updated, T1 enter its critical section(T1.step3 and T1.step4, try to obtain 'A', #L517), otherwise just give up (T1 without priority). (2) T2, write top, if T2 reads that pin has not been updated, T2 enter critical section(T2.step4, try to add 'A' to top list again, #L420-435), otherwise wait until pin!=A (T2 with priority). In the previous code, due to load 'top' and 'pin' with relaxed semantic, on arm and ppc, there is no guarantee that the above critical sections are mutually exclusive, in other words, "oops" will be printed. This bug only happens on arm and ppc, not x86. On current x86 implementation, load is always seq-cst (relaxed and seq-cst load generates same machine code), as shown in https://godbolt.org/z/sEzMvnjd9 3. Fix method Add sequential-consistency semantic to read 'top' in #L505(T1.step2), Add sequential-consistency semantic to read "el->pin[i]" in #L295 and #L320. 4. Issue reproduce Add "delay" after #L503 in lf_alloc-pin.c, When run unit.lf, can quickly get segment fault because "top" point to an invalid address. For detail, see comment area of below link. https://jira.mariadb.org/browse/MDEV-28430. 5. Futher improvement To make this code more robust and safe on all platforms, we recommend replacing volatile with C11 atomics and to fix all data races. This will also make the code easier to reason. Signed-off-by: Xiaotong Niu --- mysys/lf_alloc-pin.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index 6d80b381e5e..0b15fe28ba5 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -292,7 +292,7 @@ static int harvest_pins(LF_PINS *el, struct st_harvester *hv) { for (i= 0; i < LF_PINBOX_PINS; i++) { - void *p= el->pin[i]; + void *p= my_atomic_loadptr((void **)&el->pin[i]); if (p) *hv->granary++= p; } @@ -317,7 +317,7 @@ static int match_pins(LF_PINS *el, void *addr) LF_PINS *el_end= el+LF_DYNARRAY_LEVEL_LENGTH; for (; el < el_end; el++) for (i= 0; i < LF_PINBOX_PINS; i++) - if (el->pin[i] == addr) + if (my_atomic_loadptr((void **)&el->pin[i]) == addr) return 1; return 0; } @@ -502,7 +502,8 @@ void *lf_alloc_new(LF_PINS *pins) { node= allocator->top; lf_pin(pins, 0, node); - } while (node != allocator->top && LF_BACKOFF()); + } while (node != my_atomic_loadptr((void **)(char *)&allocator->top) + && LF_BACKOFF()); if (!node) { node= (void *)my_malloc(allocator->element_size, MYF(MY_WME)); From d510f80549121ac2a07588b5ee9d0252e2b3b60f Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Sat, 10 Feb 2024 00:30:47 +0100 Subject: [PATCH 008/106] MDEV-33482: Optimize WolfSSL for improved performance - Use "new" math library WOLFSSL_SP_MATH_ALL, which is now promoted by WolfSSL for faster performance. "fastmath" we used previously is going to be deprecated, it was not really always fast. - Optimize common RSA math operations with WOLFSSL_HAVE_SP_RSA - Incorporate assembly optimizations, currently for Intel x64 only This patch significantly reduces execution time for SSL tests like main.ssl-big and main.ssl_connect, which now run 2 to 3 times faster. Notably, when this patch is applied to 11.4, server startup in with ephemeral certificates becomes approximately 10x faster due to optimized wolfSSL_EVP_PKEY_keygen(). Additionally, refactored WolfSSL by removing old workarounds and consolidating wolfssl and wolfcrypt into a single library wolfssl, just like it was done in WolfSSL's own CMake. --- cmake/os/Windows.cmake | 8 ++ cmake/ssl.cmake | 2 +- extra/wolfssl/CMakeLists.txt | 192 ++++++++++++------------------- extra/wolfssl/user_settings.h.in | 18 +-- 4 files changed, 93 insertions(+), 127 deletions(-) diff --git a/cmake/os/Windows.cmake b/cmake/os/Windows.cmake index f47d4ebc98d..1a853349ae5 100644 --- a/cmake/os/Windows.cmake +++ b/cmake/os/Windows.cmake @@ -24,6 +24,14 @@ INCLUDE (CheckCSourceRuns) INCLUDE (CheckSymbolExists) INCLUDE (CheckTypeSize) +IF(MSVC) + IF(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL ARM64) + SET(MSVC_ARM64 1) + SET(MSVC_INTEL 0) + ELSE() + SET(MSVC_INTEL 1) + ENDIF() +ENDIF() # avoid running system checks by using pre-cached check results # system checks are expensive on VS since every tiny program is to be compiled in diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake index 646aa37a91c..51176a84c51 100644 --- a/cmake/ssl.cmake +++ b/cmake/ssl.cmake @@ -53,7 +53,7 @@ MACRO (MYSQL_USE_BUNDLED_SSL) ${CMAKE_SOURCE_DIR}/extra/wolfssl/wolfssl ${CMAKE_SOURCE_DIR}/extra/wolfssl/wolfssl/wolfssl ) - SET(SSL_LIBRARIES wolfssl wolfcrypt) + SET(SSL_LIBRARIES wolfssl) SET(SSL_INCLUDE_DIRS ${INC_DIRS}) SET(SSL_DEFINES "-DHAVE_OPENSSL -DHAVE_WOLFSSL -DWOLFSSL_USER_SETTINGS") SET(HAVE_ERR_remove_thread_state ON CACHE INTERNAL "wolfssl doesn't have ERR_remove_thread_state") diff --git a/extra/wolfssl/CMakeLists.txt b/extra/wolfssl/CMakeLists.txt index 69f7801d4e3..e3f8da21f76 100644 --- a/extra/wolfssl/CMakeLists.txt +++ b/extra/wolfssl/CMakeLists.txt @@ -1,86 +1,57 @@ -IF(MSVC) +IF(MSVC_INTEL) PROJECT(wolfssl C ASM_MASM) ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64") - PROJECT(wolfssl C ASM) + PROJECT(wolfssl C ASM) ELSE() PROJECT(wolfssl C) ENDIF() IF(CMAKE_SIZEOF_VOID_P MATCHES 8) -IF(MSVC) +IF(MSVC_INTEL AND NOT (CMAKE_C_COMPILER_ID MATCHES Clang)) SET(WOLFSSL_INTELASM ON) - SET(WOLFSSL_X86_64_BUILD 1) SET(HAVE_INTEL_RDSEED 1) SET(HAVE_INTEL_RDRAND 1) -ELSEIF(CMAKE_ASM_COMPILER_ID MATCHES "Clang" AND CMAKE_VERSION VERSION_LESS 3.16) - - # WolfSSL 5.5.4 bug workaround below does not work, due to some CMake bug ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64") - SET(WOLFSSL_X86_64_BUILD 1) IF(CMAKE_C_COMPILER_ID MATCHES GNU AND CMAKE_C_COMPILER_VERSION VERSION_LESS 4.9) MESSAGE_ONCE(NO_INTEL_ASSEMBLY "Disable Intel assembly for WolfSSL - compiler is too old") + ELSEIF(WITH_MSAN) + MESSAGE_ONCE(MSAN_CANT_HANDLE_IT "Disable Intel assembly for WolfSSL - MSAN can't handle it") ELSE() - IF(WITH_MSAN) - MESSAGE_ONCE(MSAN_CANT_HANDLE_IT - "Disable Intel assembly for WolfSSL - MSAN can't handle it") - ELSE() - MY_CHECK_C_COMPILER_FLAG(-maes) - MY_CHECK_C_COMPILER_FLAG(-msse4) - MY_CHECK_C_COMPILER_FLAG(-mpclmul) - IF(have_C__maes AND have_C__msse4 AND have_C__mpclmul) - SET(WOLFSSL_INTELASM ON) + MY_CHECK_C_COMPILER_FLAG(-maes) + MY_CHECK_C_COMPILER_FLAG(-msse4) + MY_CHECK_C_COMPILER_FLAG(-mpclmul) + IF(have_C__maes AND have_C__msse4 AND have_C__mpclmul) + SET(WOLFSSL_INTELASM ON) + MY_CHECK_C_COMPILER_FLAG(-mrdrnd) + MY_CHECK_C_COMPILER_FLAG(-mrdseed) + IF(have_C__mrdrnd) + SET(HAVE_INTEL_RDRAND ON) + ENDIF() + IF(have_C__mrdseed) + SET(HAVE_INTEL_RDSEED ON) ENDIF() - ENDIF() - MY_CHECK_C_COMPILER_FLAG(-mrdrnd) - MY_CHECK_C_COMPILER_FLAG(-mrdseed) - IF(have_C__mrdrnd) - SET(HAVE_INTEL_RDRAND ON) - ENDIF() - IF(have_C__mrdseed) - SET(HAVE_INTEL_RDSEED ON) ENDIF() ENDIF() ENDIF() ENDIF() SET(WOLFSSL_SRCDIR ${CMAKE_CURRENT_SOURCE_DIR}/wolfssl/src) -ADD_DEFINITIONS(${SSL_DEFINES}) - -SET(WOLFSSL_SOURCES - ${WOLFSSL_SRCDIR}/crl.c - ${WOLFSSL_SRCDIR}/internal.c - ${WOLFSSL_SRCDIR}/keys.c - ${WOLFSSL_SRCDIR}/tls.c - ${WOLFSSL_SRCDIR}/wolfio.c - ${WOLFSSL_SRCDIR}/ocsp.c - ${WOLFSSL_SRCDIR}/ssl.c - ${WOLFSSL_SRCDIR}/tls13.c) - -ADD_DEFINITIONS(-DWOLFSSL_LIB -DBUILDING_WOLFSSL) - -INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/wolfssl) -IF(MSVC) - # size_t to long truncation warning - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -wd4267 -wd4334 -wd4028 -wd4244") -ENDIF() - -ADD_CONVENIENCE_LIBRARY(wolfssl ${WOLFSSL_SOURCES}) - -# Workaround linker crash with older Ubuntu binutils -# e.g aborting at ../../bfd/merge.c line 873 in _bfd_merged_section_offset -IF(CMAKE_SYSTEM_NAME MATCHES "Linux") - STRING(REPLACE "-g " "-g1 " CMAKE_C_FLAGS_RELWITHDEBINFO - ${CMAKE_C_FLAGS_RELWITHDEBINFO}) - STRING(REPLACE "-g " "-g1 " CMAKE_C_FLAGS_DEBUG - ${CMAKE_C_FLAGS_DEBUG}) - STRING(REPLACE "-ggdb3 " " " CMAKE_C_FLAGS_RELWITHDEBINFO - ${CMAKE_C_FLAGS_RELWITHDEBINFO}) - STRING(REPLACE "-ggdb3 " " " CMAKE_C_FLAGS_DEBUG - ${CMAKE_C_FLAGS_DEBUG}) -ENDIF() - SET(WOLFCRYPT_SRCDIR ${CMAKE_CURRENT_SOURCE_DIR}/wolfssl/wolfcrypt/src) -SET(WOLFCRYPT_SOURCES +ADD_DEFINITIONS(${SSL_DEFINES}) +ADD_DEFINITIONS(-DWOLFSSL_LIB -DBUILDING_WOLFSSL) +ADD_DEFINITIONS(-DWOLFSSL_SP_4096) +INCLUDE_DIRECTORIES(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/wolfssl) +INCLUDE_DIRECTORIES(${SSL_INCLUDE_DIRS}) + +add_library(wolfssl STATIC +${WOLFSSL_SRCDIR}/crl.c +${WOLFSSL_SRCDIR}/internal.c +${WOLFSSL_SRCDIR}/keys.c +${WOLFSSL_SRCDIR}/tls.c +${WOLFSSL_SRCDIR}/wolfio.c +${WOLFSSL_SRCDIR}/ocsp.c +${WOLFSSL_SRCDIR}/ssl.c +${WOLFSSL_SRCDIR}/tls13.c ${WOLFCRYPT_SRCDIR}/aes.c ${WOLFCRYPT_SRCDIR}/arc4.c ${WOLFCRYPT_SRCDIR}/asn.c @@ -110,69 +81,56 @@ ${WOLFCRYPT_SRCDIR}/wc_encrypt.c ${WOLFCRYPT_SRCDIR}/hash.c ${WOLFCRYPT_SRCDIR}/wolfmath.c ${WOLFCRYPT_SRCDIR}/kdf.c +${WOLFCRYPT_SRCDIR}/sp_int.c +${WOLFCRYPT_SRCDIR}/sp_c32.c +${WOLFCRYPT_SRCDIR}/sp_c64.c ) -# Use fastmath large number math library. -IF(NOT (MSVC AND CMAKE_C_COMPILER_ID MATCHES Clang)) - # Can't use clang-cl with WOLFSSL_FASTMATH - # due to https://bugs.llvm.org/show_bug.cgi?id=25305 - SET(WOLFSSL_FASTMATH 1) -ENDIF() - -IF(WOLFSSL_FASTMATH) - SET(USE_FAST_MATH 1) - SET(TFM_TIMING_RESISTANT 1) - # FP_MAX_BITS is set high solely to satisfy ssl_8k_key.test - # WolfSSL will use more stack space with it - SET(FP_MAX_BITS 16384) - SET(WOLFCRYPT_SOURCES ${WOLFCRYPT_SOURCES} ${WOLFCRYPT_SRCDIR}/tfm.c) - IF((CMAKE_SIZEOF_VOID_P MATCHES 4) AND (CMAKE_SYSTEM_PROCESSOR MATCHES "86") - AND (NOT MSVC)) - # Workaround https://github.com/wolfSSL/wolfssl/issues/4245 - # On 32bit Intel, to satisfy inline assembly's wish for free registers - # 1. use -fomit-frame-pointer - # 2. With GCC 4, additionally use -fno-PIC, which works on x86 - # (modern GCC has PIC optimizations, that make it unnecessary) - # The following assumes GCC or Clang - SET(TFM_COMPILE_FLAGS "-fomit-frame-pointer") - IF(CMAKE_C_COMPILER_VERSION VERSION_LESS "5") - SET(TFM_COMPILE_FLAGS "${TFM_COMPILE_FLAGS} -fno-PIC") - ENDIF() - SET_SOURCE_FILES_PROPERTIES(${WOLFCRYPT_SRCDIR}/tfm.c - PROPERTIES COMPILE_FLAGS ${TFM_COMPILE_FLAGS}) - ENDIF() -ELSE() - SET(WOLFSSL_SP_MATH_ALL 1) - SET(WOLFCRYPT_SOURCES ${WOLFCRYPT_SOURCES} ${WOLFCRYPT_SRCDIR}/sp_int.c) -ENDIF() - -IF(WOLFSSL_X86_64_BUILD) - LIST(APPEND WOLFCRYPT_SOURCES ${WOLFCRYPT_SRCDIR}/cpuid.c) - IF(MSVC) - SET(WOLFSSL_AESNI 1) - LIST(APPEND WOLFCRYPT_SOURCES - ${WOLFCRYPT_SRCDIR}/aes_asm.asm - ${WOLFCRYPT_SRCDIR}/aes_gcm_asm.asm) - IF(CMAKE_C_COMPILER_ID MATCHES Clang) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -msse4.2 -mpclmul -mrdrnd -mrdseed") - ENDIF() - ELSEIF(WOLFSSL_INTELASM) - SET(WOLFSSL_AESNI 1) - SET(USE_INTEL_SPEEDUP 1) - LIST(APPEND WOLFCRYPT_SOURCES +# Optimizations, assembly +if(WOLFSSL_INTELASM) + set(WOLFSSL_X86_64_BUILD 1) + set(WOLFSSL_SP_X86_64 1) + set(WOLFSSL_SP_X86_64_ASM 1) + set(WOLFSSL_AESNI 1) + target_sources(wolfssl PRIVATE + ${WOLFCRYPT_SRCDIR}/cpuid.c + ${WOLFCRYPT_SRCDIR}/sp_x86_64.c + ) + if(MSVC_INTEL) + target_sources(wolfssl PRIVATE + ${WOLFCRYPT_SRCDIR}/aes_asm.asm + ${WOLFCRYPT_SRCDIR}/aes_gcm_asm.asm + ${WOLFCRYPT_SRCDIR}/sp_x86_64_asm.asm + ) + target_compile_options(wolfssl PRIVATE + $<$:-maes -msse4.2 -mpclmul -mrdrnd -mrdseed> + $<$:/Zi> + ) + else() + set(USE_INTEL_SPEEDUP 1) + target_sources(wolfssl PRIVATE ${WOLFCRYPT_SRCDIR}/aes_asm.S ${WOLFCRYPT_SRCDIR}/aes_gcm_asm.S ${WOLFCRYPT_SRCDIR}/chacha_asm.S ${WOLFCRYPT_SRCDIR}/poly1305_asm.S ${WOLFCRYPT_SRCDIR}/sha512_asm.S - ${WOLFCRYPT_SRCDIR}/sha256_asm.S) - ADD_DEFINITIONS(-maes -msse4.2 -mpclmul) - # WolfSSL 5.5.4 bug - user_settings.h not included into aes_asm.S - SET_PROPERTY(SOURCE ${WOLFCRYPT_SRCDIR}/aes_asm.S APPEND PROPERTY COMPILE_OPTIONS "-DWOLFSSL_X86_64_BUILD") - ENDIF() -ENDIF() + ${WOLFCRYPT_SRCDIR}/sha256_asm.S + ${WOLFCRYPT_SRCDIR}/sp_x86_64_asm.S + ) + target_compile_options(wolfssl PRIVATE -maes -msse4.2 -mpclmul) + # Workaround 5.5.4 bug (user_settings.h not included into aes_asm.S) + set_property(SOURCE ${WOLFCRYPT_SRCDIR}/aes_asm.S APPEND PROPERTY COMPILE_OPTIONS "-DWOLFSSL_X86_64_BUILD") + endif() +endif() + +# Silence some warnings +if(MSVC) + # truncation warnings + target_compile_options(wolfssl PRIVATE $<$:/wd4244>) + if(CMAKE_C_COMPILER_ID MATCHES Clang) + target_compile_options(wolfssl PRIVATE $<$:-Wno-incompatible-function-pointer-types>) + endif() +endif() CONFIGURE_FILE(user_settings.h.in user_settings.h) -INCLUDE_DIRECTORIES(${SSL_INCLUDE_DIRS}) -ADD_CONVENIENCE_LIBRARY(wolfcrypt ${WOLFCRYPT_SOURCES}) diff --git a/extra/wolfssl/user_settings.h.in b/extra/wolfssl/user_settings.h.in index baa64fcdfbe..489118b33b4 100644 --- a/extra/wolfssl/user_settings.h.in +++ b/extra/wolfssl/user_settings.h.in @@ -21,6 +21,7 @@ #define HAVE_AESGCM #define HAVE_CHACHA #define HAVE_POLY1305 +#define HAVE_THREAD_LS #define WOLFSSL_AES_COUNTER #define NO_WOLFSSL_STUB #define OPENSSL_ALL @@ -51,20 +52,19 @@ #define NO_RABBIT #define NO_RC4 -/* - FP_MAX_BITS is set high solely to satisfy ssl_8k_key.test - WolfSSL will use more stack space with it, with fastmath -*/ -#cmakedefine FP_MAX_BITS 16384 #define RSA_MAX_SIZE 8192 +#define WOLFSSL_SP_MATH_ALL +#define WOLFSSL_HAVE_SP_RSA +#ifndef WOLFSSL_SP_4096 +#define WOLFSSL_SP_4096 +#endif + #cmakedefine WOLFSSL_AESNI -#cmakedefine USE_FAST_MATH -#cmakedefine TFM_TIMING_RESISTANT #cmakedefine HAVE_INTEL_RDSEED #cmakedefine HAVE_INTEL_RDRAND #cmakedefine USE_INTEL_SPEEDUP -#cmakedefine USE_FAST_MATH #cmakedefine WOLFSSL_X86_64_BUILD -#cmakedefine WOLFSSL_SP_MATH_ALL +#cmakedefine WOLFSSL_SP_X86_64 +#cmakedefine WOLFSSL_SP_X86_64_ASM #endif /* WOLFSSL_USER_SETTINGS_H */ From c492c34f67f89c2575b8f2789962359bce4d0a00 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Mon, 19 Feb 2024 15:12:16 +1100 Subject: [PATCH 009/106] MDEV-33434 spider direct sql: Check length before memcpy similar to MDEV-30981 --- .../spider/bugfix/r/mdev_33434.result | 12 ++ .../spider/bugfix/t/mdev_33434.test | 15 ++ storage/spider/spd_direct_sql.cc | 135 +++++++----------- 3 files changed, 80 insertions(+), 82 deletions(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_33434.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_33434.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33434.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33434.result new file mode 100644 index 00000000000..2cbcff38752 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33434.result @@ -0,0 +1,12 @@ +# +# MDEV-33434 MDEV-33434 UBSAN null pointer passed as argument 2, which is declared to never be null in spider_udf_direct_sql_create_conn +# +INSTALL SONAME 'ha_spider'; +SET character_set_connection=ucs2; +SELECT SPIDER_DIRECT_SQL('SELECT SLEEP(1)', '', 'srv "dummy", port "3307"'); +ERROR HY000: Unable to connect to foreign data source: localhost +Warnings: +Warning 1620 Plugin is busy and will be uninstalled on shutdown +# +# end of test mdev_33434 +# diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33434.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33434.test new file mode 100644 index 00000000000..dd9f882f42e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33434.test @@ -0,0 +1,15 @@ +--echo # +--echo # MDEV-33434 MDEV-33434 UBSAN null pointer passed as argument 2, which is declared to never be null in spider_udf_direct_sql_create_conn +--echo # + +INSTALL SONAME 'ha_spider'; +SET character_set_connection=ucs2; +--error ER_CONNECT_TO_FOREIGN_DATA_SOURCE +SELECT SPIDER_DIRECT_SQL('SELECT SLEEP(1)', '', 'srv "dummy", port "3307"'); +--disable_query_log +--source ../../include/clean_up_spider.inc +--enable_query_log + +--echo # +--echo # end of test mdev_33434 +--echo # diff --git a/storage/spider/spd_direct_sql.cc b/storage/spider/spd_direct_sql.cc index 2a29007a915..5de6123874f 100644 --- a/storage/spider/spd_direct_sql.cc +++ b/storage/spider/spd_direct_sql.cc @@ -413,6 +413,23 @@ int spider_udf_direct_sql_create_conn_key( DBUG_RETURN(0); } +static inline void spider_maybe_memcpy_string( + char **dest, + char *src, + char *tmp, + uint *dest_len, + uint src_len) +{ + *dest_len= src_len; + if (src_len) + { + *dest= tmp; + memcpy(*dest, src, src_len); + } else + *dest= NULL; +} + + SPIDER_CONN *spider_udf_direct_sql_create_conn( const SPIDER_DIRECT_SQL *direct_sql, int *error_num @@ -504,89 +521,43 @@ SPIDER_CONN *spider_udf_direct_sql_create_conn( { #endif conn->tgt_port = direct_sql->tgt_port; - conn->tgt_socket_length = direct_sql->tgt_socket_length; - conn->tgt_socket = tmp_socket; - memcpy(conn->tgt_socket, direct_sql->tgt_socket, - direct_sql->tgt_socket_length); + spider_maybe_memcpy_string( + &conn->tgt_socket, direct_sql->tgt_socket, tmp_socket, + &conn->tgt_socket_length, direct_sql->tgt_socket_length); if (!tables_on_different_db_are_joinable) - { - conn->tgt_db_length = direct_sql->tgt_default_db_name_length; - conn->tgt_db = tmp_db; - memcpy(conn->tgt_db, direct_sql->tgt_default_db_name, - direct_sql->tgt_default_db_name_length); - } - conn->tgt_username_length = direct_sql->tgt_username_length; - conn->tgt_username = tmp_username; - memcpy(conn->tgt_username, direct_sql->tgt_username, - direct_sql->tgt_username_length); - conn->tgt_password_length = direct_sql->tgt_password_length; - conn->tgt_password = tmp_password; - memcpy(conn->tgt_password, direct_sql->tgt_password, - direct_sql->tgt_password_length); - conn->tgt_ssl_ca_length = direct_sql->tgt_ssl_ca_length; - if (conn->tgt_ssl_ca_length) - { - conn->tgt_ssl_ca = tmp_ssl_ca; - memcpy(conn->tgt_ssl_ca, direct_sql->tgt_ssl_ca, - direct_sql->tgt_ssl_ca_length); - } else - conn->tgt_ssl_ca = NULL; - conn->tgt_ssl_capath_length = direct_sql->tgt_ssl_capath_length; - if (conn->tgt_ssl_capath_length) - { - conn->tgt_ssl_capath = tmp_ssl_capath; - memcpy(conn->tgt_ssl_capath, direct_sql->tgt_ssl_capath, - direct_sql->tgt_ssl_capath_length); - } else - conn->tgt_ssl_capath = NULL; - conn->tgt_ssl_cert_length = direct_sql->tgt_ssl_cert_length; - if (conn->tgt_ssl_cert_length) - { - conn->tgt_ssl_cert = tmp_ssl_cert; - memcpy(conn->tgt_ssl_cert, direct_sql->tgt_ssl_cert, - direct_sql->tgt_ssl_cert_length); - } else - conn->tgt_ssl_cert = NULL; - conn->tgt_ssl_cipher_length = direct_sql->tgt_ssl_cipher_length; - if (conn->tgt_ssl_cipher_length) - { - conn->tgt_ssl_cipher = tmp_ssl_cipher; - memcpy(conn->tgt_ssl_cipher, direct_sql->tgt_ssl_cipher, - direct_sql->tgt_ssl_cipher_length); - } else - conn->tgt_ssl_cipher = NULL; - conn->tgt_ssl_key_length = direct_sql->tgt_ssl_key_length; - if (conn->tgt_ssl_key_length) - { - conn->tgt_ssl_key = tmp_ssl_key; - memcpy(conn->tgt_ssl_key, direct_sql->tgt_ssl_key, - direct_sql->tgt_ssl_key_length); - } else - conn->tgt_ssl_key = NULL; - conn->tgt_default_file_length = direct_sql->tgt_default_file_length; - if (conn->tgt_default_file_length) - { - conn->tgt_default_file = tmp_default_file; - memcpy(conn->tgt_default_file, direct_sql->tgt_default_file, - direct_sql->tgt_default_file_length); - } else - conn->tgt_default_file = NULL; - conn->tgt_default_group_length = direct_sql->tgt_default_group_length; - if (conn->tgt_default_group_length) - { - conn->tgt_default_group = tmp_default_group; - memcpy(conn->tgt_default_group, direct_sql->tgt_default_group, - direct_sql->tgt_default_group_length); - } else - conn->tgt_default_group = NULL; - conn->tgt_dsn_length = direct_sql->tgt_dsn_length; - if (conn->tgt_dsn_length) - { - conn->tgt_dsn = tmp_dsn; - memcpy(conn->tgt_dsn, direct_sql->tgt_dsn, - direct_sql->tgt_dsn_length); - } else - conn->tgt_dsn = NULL; + spider_maybe_memcpy_string( + &conn->tgt_db, direct_sql->tgt_default_db_name, tmp_db, + &conn->tgt_db_length, direct_sql->tgt_default_db_name_length); + spider_maybe_memcpy_string( + &conn->tgt_username, direct_sql->tgt_username, tmp_username, + &conn->tgt_username_length, direct_sql->tgt_username_length); + spider_maybe_memcpy_string( + &conn->tgt_password, direct_sql->tgt_password, tmp_password, + &conn->tgt_password_length, direct_sql->tgt_password_length); + spider_maybe_memcpy_string( + &conn->tgt_ssl_ca, direct_sql->tgt_ssl_ca, tmp_ssl_ca, + &conn->tgt_ssl_ca_length, direct_sql->tgt_ssl_ca_length); + spider_maybe_memcpy_string( + &conn->tgt_ssl_capath, direct_sql->tgt_ssl_capath, tmp_ssl_capath, + &conn->tgt_ssl_capath_length, direct_sql->tgt_ssl_capath_length); + spider_maybe_memcpy_string( + &conn->tgt_ssl_cert, direct_sql->tgt_ssl_cert, tmp_ssl_cert, + &conn->tgt_ssl_cert_length, direct_sql->tgt_ssl_cert_length); + spider_maybe_memcpy_string( + &conn->tgt_ssl_cipher, direct_sql->tgt_ssl_cipher, tmp_ssl_cipher, + &conn->tgt_ssl_cipher_length, direct_sql->tgt_ssl_cipher_length); + spider_maybe_memcpy_string( + &conn->tgt_ssl_key, direct_sql->tgt_ssl_key, tmp_ssl_key, + &conn->tgt_ssl_key_length, direct_sql->tgt_ssl_key_length); + spider_maybe_memcpy_string( + &conn->tgt_default_file, direct_sql->tgt_default_file, tmp_default_file, + &conn->tgt_default_file_length, direct_sql->tgt_default_file_length); + spider_maybe_memcpy_string( + &conn->tgt_default_group, direct_sql->tgt_default_group, tmp_default_group, + &conn->tgt_default_group_length, direct_sql->tgt_default_group_length); + spider_maybe_memcpy_string( + &conn->tgt_dsn, direct_sql->tgt_dsn, tmp_dsn, + &conn->tgt_dsn_length, direct_sql->tgt_dsn_length); conn->tgt_ssl_vsc = direct_sql->tgt_ssl_vsc; #if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET) } else { From 75c0f9512a11088eeddbcfa0c07484c0628cf28a Mon Sep 17 00:00:00 2001 From: Andrew Daugherity Date: Tue, 21 Nov 2023 19:43:52 -0600 Subject: [PATCH 010/106] fix markdown headings Should be h2 rather than h1, and GitHub requires an intervening space. --- plugin/auth_gssapi/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugin/auth_gssapi/README.md b/plugin/auth_gssapi/README.md index ea8deaafa94..635982234c4 100644 --- a/plugin/auth_gssapi/README.md +++ b/plugin/auth_gssapi/README.md @@ -49,7 +49,7 @@ Usually nothing need to be done. MariaDB server should to run on a domain joine Creating service principal is not required here (but you can still do it using [_setspn_](https://technet.microsoft.com/en-us/library/cc731241.aspx) tool) -# Installing plugin +## Installing plugin - Start the server - On Unix, edit my the my.cnf/my.ini configuration file, set the parameter gssapi-keytab-path to point to previously @@ -72,7 +72,7 @@ configure alternative principal name with INSTALL SONAME 'auth_gssapi' ``` -#Creating users +## Creating users Now, you can create a user for GSSAPI/SSPI authentication. CREATE USER command, for Kerberos user would be like this (*long* form, see below for short one) @@ -94,7 +94,7 @@ CREATE USER usr1 IDENTIFIED WITH gssapi; If this syntax is used, realm part is *not* used for comparison thus 'usr1@EXAMPLE.COM', 'usr1@EXAMPLE.CO.UK' and 'mymachine\usr1' will all identify as 'usr1'. -#Login as GSSAPI user with command line clients +## Login as GSSAPI user with command line clients Using command line client, do @@ -102,7 +102,7 @@ Using command line client, do mysql --plugin-dir=/path/to/plugin-dir -u usr1 ``` -#Plugin variables +## Plugin variables - **gssapi-keytab-path** (Unix only) - Path to the server keytab file - **gssapi-principal-name** - name of the service principal. - **gssapi-mech-name** (Windows only) - Name of the SSPI package used by server. Can be either 'Kerberos' or 'Negotiate'. @@ -111,7 +111,7 @@ mysql --plugin-dir=/path/to/plugin-dir -u usr1 to allow non-domain environment (e.g if server does not run in domain environment). -#Implementation +## Implementation Overview of the protocol between client and server From 90bbeafb7a2c848153aa09b7004ac23a8be68905 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 20 Feb 2024 13:20:12 +0200 Subject: [PATCH 011/106] Get rid of error when running mariadb-install-db with --log-bin This removes the error: "Failed to load slave replication state from table mysql.gtid_slave_pos: 1017: Can't find file: './mysql/' (errno: 2 "No such file or directory") --- sql/mysqld.cc | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f03e5780ad9..25630aae76f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4710,9 +4710,9 @@ static int init_server_components() proc_info_hook= set_thd_stage_info; /* - Print source revision hash, as one of the first lines, if not the - first in error log, for troubleshooting and debugging purposes - */ + Print source revision hash, as one of the first lines, if not the + first in error log, for troubleshooting and debugging purposes + */ if (!opt_help) sql_print_information("Starting MariaDB %s source revision %s as process %lu", server_version, SOURCE_REVISION, (ulong) getpid()); @@ -4740,6 +4740,19 @@ static int init_server_components() xid_cache_init(); + /* + Do not open binlong when doing bootstrap. + This ensures that rpl_load_gtid_slave_state() will not fail with an error + as the mysql schema does not yet exists. + This also ensures that we don't get an empty binlog file if the user has + log-bin in his config files. + */ + if (opt_bootstrap) + { + opt_bin_log= opt_bin_log_used= binlog_format_used= 0; + opt_log_slave_updates= 0; + } + /* need to configure logging before initializing storage engines */ if (!opt_bin_log_used && !WSREP_ON) { From 1bbbb66e4685ba3ab3cf9ed4e4b85a5a77c4c5d2 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 20 Feb 2024 13:48:20 +0200 Subject: [PATCH 012/106] Disable error messages in mysql-install-db for not writable log directory --- scripts/mysql_install_db.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 3bc4d63b7df..70ca9b0e0cb 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -537,6 +537,25 @@ else filter_cmd_line="cat" fi +# Disable log error if the user don't have right to write/create the file +# This is common when a user tries to install a personal mariadbd server and +# the global config in /etc is using --log-error. +# The server will internally change log-error to stderr to stderr if it cannot +# write the the log file. This code only disables the error message from a not +# writable log-error, which can be confusing. +if test -n "$log_error" +then + if test \( -e "$log_error" -a \! -w "$log_error" \) -o \( ! -e "$log_error" -a ! -w "`dirname "$log_error"`" \) + then + if test -n "$verbose" + then + echo "resetting log-error '$log_error' because no write access" + fi + log_error="" + args="$args --skip-log-error" + fi +fi + # Configure mysqld command line mysqld_bootstrap="${MYSQLD_BOOTSTRAP-$mysqld}" mysqld_install_cmd_line() From a5998145ba52613e4dfa08d9fe33754d14210bf4 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Tue, 20 Feb 2024 13:36:18 +0100 Subject: [PATCH 013/106] Record correct mutex (LOCK_STATUS and acl_cache) order for debugging. --- sql/sql_acl.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 1949a0c02b6..c0593b2d19b 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2770,6 +2770,7 @@ bool acl_reload(THD *thd) } acl_cache->clear(0); + mysql_mutex_record_order(&acl_cache->lock, &LOCK_status); mysql_mutex_lock(&acl_cache->lock); old_acl_hosts= acl_hosts; From b04c857596722f892cf01cf931b33472ba1ca180 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Tue, 20 Feb 2024 08:16:15 -0700 Subject: [PATCH 014/106] MDEV-33500: rpl.rpl_parallel_sbm can fail on slow machines, e.g. MSAN/Valgrind builders In an addition to test rpl.rpl_parallel_sbm added by MDEV-32265, the test uses sleep statements alone to test Seconds_Behind_Master with delayed replication. On slow running machines, the test can pass the intended MASTER_DELAY duration and Seconds_Behind_Master can become 0, when the test expects the transaction to still be actively in a delaying state. This can be consistently reproduced by adding a sleep statement before the call to --let = query_get_value(SHOW SLAVE STATUS, Seconds_Behind_Master, 1) to sleep past the delay end point. This patch fixes this by locking the table which the delayed transaction targets so Second_Behind_Master cannot be updated before the test reads it for validation. --- mysql-test/suite/rpl/r/rpl_parallel_sbm.result | 7 +++++++ mysql-test/suite/rpl/t/rpl_parallel_sbm.test | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_parallel_sbm.result b/mysql-test/suite/rpl/r/rpl_parallel_sbm.result index 7990a663f04..e349353ac59 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_sbm.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_sbm.result @@ -27,12 +27,19 @@ connection slave; # delaying a transaction; then when the reciprocal START SLAVE occurs, # if the event is still to be delayed, SBM should resume accordingly include/stop_slave.inc +# Lock t1 on slave to ensure the event can't finish (and thereby update +# Seconds_Behind_Master) so slow running servers don't accidentally +# catch up to the master before checking SBM. +connection server_2; +LOCK TABLES t1 WRITE; include/start_slave.inc connection slave; # Waiting for replica to resume the delay for the transaction # Sleeping 1s to increment SBM # Ensuring Seconds_Behind_Master increases after sleeping.. # ..done +connection server_2; +UNLOCK TABLES; include/sync_with_master_gtid.inc # # Pt 2) If the worker threads have not entered an idle state, ensure diff --git a/mysql-test/suite/rpl/t/rpl_parallel_sbm.test b/mysql-test/suite/rpl/t/rpl_parallel_sbm.test index 58c0db15e47..9c502ff6cb9 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_sbm.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_sbm.test @@ -67,6 +67,13 @@ if (`SELECT $sbm_trx1_arrive > ($seconds_since_idling + 1)`) --echo # if the event is still to be delayed, SBM should resume accordingly --source include/stop_slave.inc + +--echo # Lock t1 on slave to ensure the event can't finish (and thereby update +--echo # Seconds_Behind_Master) so slow running servers don't accidentally +--echo # catch up to the master before checking SBM. +--connection server_2 +LOCK TABLES t1 WRITE; + --source include/start_slave.inc --connection slave @@ -86,6 +93,9 @@ if (`SELECT $sbm_trx1_after_1s_sleep <= $sbm_trx1_arrive`) } --echo # ..done +--connection server_2 +UNLOCK TABLES; + --source include/sync_with_master_gtid.inc --echo # From 0f0da95db09a0e6046b9436efda307e1ffd715f5 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Wed, 21 Feb 2024 14:17:34 +1100 Subject: [PATCH 015/106] MDEV-33493 Spider: Make a symlink result file a normal file --- .../r/udf_mysql_func_early_init_file.result | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) mode change 120000 => 100644 storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early_init_file.result diff --git a/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early_init_file.result b/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early_init_file.result deleted file mode 120000 index 045ddc4372c..00000000000 --- a/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early_init_file.result +++ /dev/null @@ -1 +0,0 @@ -udf_mysql_func_early.result \ No newline at end of file diff --git a/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early_init_file.result b/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early_init_file.result new file mode 100644 index 00000000000..b84f60a67fb --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/udf_mysql_func_early_init_file.result @@ -0,0 +1,43 @@ +# +# Test that udf created by inserting into mysql_func works as expected +# +CREATE SERVER s_1 FOREIGN DATA WRAPPER mysql OPTIONS ( +HOST 'localhost', +DATABASE 'auto_test_local', +USER 'root', +PASSWORD '', +SOCKET '$MASTER_1_MYSOCK' + ); +CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS ( +HOST 'localhost', +DATABASE 'auto_test_remote', +USER 'root', +PASSWORD '', +SOCKET '$CHILD2_1_MYSOCK' + ); +connect master_1, localhost, root, , , $MASTER_1_MYPORT, $MASTER_1_MYSOCK; +connect child2_1, localhost, root, , , $CHILD2_1_MYPORT, $CHILD2_1_MYSOCK; +connection child2_1; +CREATE DATABASE auto_test_remote; +USE auto_test_remote; +CREATE TABLE tbl_a ( +a INT +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +insert into tbl_a values (42); +connection master_1; +CREATE DATABASE auto_test_local; +USE auto_test_local; +CREATE TABLE tbl_a ( +a INT +) ENGINE=Spider DEFAULT CHARSET=utf8 COMMENT='table "tbl_a", srv "s_2_1"'; +create temporary table results (a int); +SELECT SPIDER_DIRECT_SQL('select * from tbl_a', 'results', 'srv "s_2_1", database "auto_test_remote"'); +SPIDER_DIRECT_SQL('select * from tbl_a', 'results', 'srv "s_2_1", database "auto_test_remote"') +1 +select * from results; +a +42 +connection master_1; +DROP DATABASE IF EXISTS auto_test_local; +connection child2_1; +DROP DATABASE IF EXISTS auto_test_remote; From d57c44f62635d6afe026345c11b13f543741e83e Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 20 Feb 2024 22:05:00 -0800 Subject: [PATCH 016/106] MDEV-31277 Wrong result on 2-nd execution of PS to select from view using derived As a result of this bug the second execution of the prepared statement created for select from materialized view could return a wrong result set if - the specification of the view used a left join - an inner table the left join was a mergeable derived table - the derived table contained a constant column. The problem appeared because the flag 'maybe-null' of the wrapper Item_direct_view_ref constructed for the constant field of the mergeable derived table was not set to 'true' on the second execution of the prepared statement. The patch always sets this flag properly when calling the function Item_direct_view_ref::set_null_ref-table(). The latter is invoked in Item_direct_view_ref constructor if it is created for some reference of a constant column belonging to a mergeable derived table. Approved by Oleksandr Byelkin --- mysql-test/main/derived_view.result | 32 +++++++++++++++++++++++++ mysql-test/main/derived_view.test | 36 +++++++++++++++++++++++++++++ mysql-test/main/join_outer.test | 12 ---------- sql/item.h | 2 ++ 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/mysql-test/main/derived_view.result b/mysql-test/main/derived_view.result index c2fe217ee97..64113cbe403 100644 --- a/mysql-test/main/derived_view.result +++ b/mysql-test/main/derived_view.result @@ -4250,3 +4250,35 @@ dim1 dim2 dim3 p SUM(p) 100 10 1 2 371 DROP VIEW v; # End of 10.4 tests +# +# MDEV-31277: 2-nd execution of PS to select from materialized view +# specified as left join whose inner table is mergeable +# derived containing a constant column +# +create table t1 ( +Election int(10) unsigned NOT NULL +) engine=MyISAM; +insert into t1 (Election) values (1), (4); +create table t2 ( +VoteID int(10), +ElectionID int(10), +UserID int(10) +); +insert into t2 (ElectionID, UserID) values (2, 30), (3, 30); +create view v1 as select * from t1 +left join ( select 'Y' AS Voted, ElectionID from t2 ) AS T +on T.ElectionID = t1.Election +limit 9; +prepare stmt1 from "select * from v1"; +execute stmt1; +Election Voted ElectionID +1 NULL NULL +4 NULL NULL +execute stmt1; +Election Voted ElectionID +1 NULL NULL +4 NULL NULL +deallocate prepare stmt1; +drop view v1; +drop table t1, t2; +# End of 10.5 tests diff --git a/mysql-test/main/derived_view.test b/mysql-test/main/derived_view.test index f9ab0443bc0..9747f1df61f 100644 --- a/mysql-test/main/derived_view.test +++ b/mysql-test/main/derived_view.test @@ -2832,3 +2832,39 @@ SELECT d.*, SUM(p) FROM demo d; DROP VIEW v; --echo # End of 10.4 tests + +--echo # +--echo # MDEV-31277: 2-nd execution of PS to select from materialized view +--echo # specified as left join whose inner table is mergeable +--echo # derived containing a constant column +--echo # + +create table t1 ( + Election int(10) unsigned NOT NULL +) engine=MyISAM; + +insert into t1 (Election) values (1), (4); + +create table t2 ( + VoteID int(10), + ElectionID int(10), + UserID int(10) +); + +insert into t2 (ElectionID, UserID) values (2, 30), (3, 30); +create view v1 as select * from t1 + left join ( select 'Y' AS Voted, ElectionID from t2 ) AS T + on T.ElectionID = t1.Election +limit 9; + +prepare stmt1 from "select * from v1"; + +execute stmt1; +execute stmt1; + +deallocate prepare stmt1; + +drop view v1; +drop table t1, t2; + +--echo # End of 10.5 tests diff --git a/mysql-test/main/join_outer.test b/mysql-test/main/join_outer.test index 857a9ced41b..da3c82109d8 100644 --- a/mysql-test/main/join_outer.test +++ b/mysql-test/main/join_outer.test @@ -2372,11 +2372,8 @@ create view v1 as select * from t1 left join ( select 'Y' AS Voted, ElectionID from t2 ) AS T on T.ElectionID = t1.Election limit 9; -#enable after fix MDEV-31277 ---disable_ps2_protocol # limit X causes merge algorithm select as opposed to temp table select * from v1; ---enable_ps2_protocol drop table t1, t2; drop view v1; @@ -2391,10 +2388,7 @@ create view v10 as select *, 'U' as u from t10 left join (select 'Y' as y, t20.b create table t30 (c int); insert into t30 values (1),(3); create view v20 as select * from t30 left join (select 'X' as x, v10.u, v10.y, v10.b from v10) dt2 on t30.c=dt2.b limit 6; -#check after fix MDEV-31277 ---disable_ps2_protocol select * from v20 limit 9; ---enable_ps2_protocol drop view v10, v20; drop table t10, t20, t30; @@ -2408,8 +2402,6 @@ insert into t3 values (3),(1); create table t1 (a int); insert into t1 values (1),(2),(7),(1); -#check after fix MDEV-31277 ---disable_ps2_protocol select * from ( select * from @@ -2422,7 +2414,6 @@ select * from on dt1.a=dt2.b limit 9 ) dt; ---enable_ps2_protocol ## Same as dt3 above create view v3(x,c) as select * from (select 'X' as x, t3.c from t3) dt3; @@ -2436,10 +2427,7 @@ create view v0(y,b,x,c) as select * from v2 left join v3 on v2.b=v3.c; # Same as above select statement create view v1 as select 'Z' as z, t1.a, v0.* from t1 left join v0 on t1.a=v0.b limit 9; -#check after fix MDEV-31277 ---disable_ps2_protocol select * from v1; ---enable_ps2_protocol set statement join_cache_level=0 for select * from v1; diff --git a/sql/item.h b/sql/item.h index c08671d46bb..f5c9ed2a7ab 100644 --- a/sql/item.h +++ b/sql/item.h @@ -5876,6 +5876,8 @@ class Item_direct_view_ref :public Item_direct_ref if (!view->is_inner_table_of_outer_join() || !(null_ref_table= view->get_real_join_table())) null_ref_table= NO_NULL_TABLE; + if (null_ref_table && null_ref_table != NO_NULL_TABLE) + maybe_null= true; } bool check_null_ref() From e66928ab28dbff3563a134c423b4ac1eb348f7c0 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Thu, 22 Feb 2024 16:50:58 +0530 Subject: [PATCH 017/106] MDEV-33462 Server aborts while altering an InnoDB statistics table Problem: ======= - When online alter of InnoDB statistics table happens, any transaction which updates the statistics table has to read the undo log and log the DML changes during transaction commit. Applying undo log (UndorecApplier::apply_undo_rec) requires a shared lock on dictionary cache but dict_stats_save() already holds write lock on dictionary cache. This leads to abort of server during commit of statistics table changes. Solution: ======== - Disallow LOCK=NONE operation for the InnoDB statistics table. The reasoning is that statistics tables are typically rather small, so any blocking would be rather short. Writes to the statistics tables should be a rare operation. --- mysql-test/suite/innodb/r/innodb_stats_fetch.result | 7 +++++++ mysql-test/suite/innodb/t/innodb_stats_fetch.test | 8 ++++++++ storage/innobase/handler/handler0alter.cc | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/mysql-test/suite/innodb/r/innodb_stats_fetch.result b/mysql-test/suite/innodb/r/innodb_stats_fetch.result index df6bc4b0cf7..cb205b1827b 100644 --- a/mysql-test/suite/innodb/r/innodb_stats_fetch.result +++ b/mysql-test/suite/innodb/r/innodb_stats_fetch.result @@ -174,3 +174,10 @@ SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_VIRTUAL LIMIT ROWS EXAMINED 5; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN LIMIT ROWS EXAMINED 5; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS LIMIT ROWS EXAMINED 5; DROP TABLE t1; +# +# MDEV-33462 Disallow LOCK=NONE operation on statistics table +# +ALTER TABLE mysql.innodb_table_stats FORCE, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: innodb_table_stats. Try LOCK=SHARED +ALTER TABLE mysql.innodb_index_stats FORCE, LOCK=NONE; +ERROR 0A000: LOCK=NONE is not supported. Reason: innodb_index_stats. Try LOCK=SHARED diff --git a/mysql-test/suite/innodb/t/innodb_stats_fetch.test b/mysql-test/suite/innodb/t/innodb_stats_fetch.test index 99fc115af1d..d02cd3b8959 100644 --- a/mysql-test/suite/innodb/t/innodb_stats_fetch.test +++ b/mysql-test/suite/innodb/t/innodb_stats_fetch.test @@ -96,3 +96,11 @@ SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_VIRTUAL LIMIT ROWS EXAMINED 5; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN LIMIT ROWS EXAMINED 5; SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS LIMIT ROWS EXAMINED 5; DROP TABLE t1; + +--echo # +--echo # MDEV-33462 Disallow LOCK=NONE operation on statistics table +--echo # +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE mysql.innodb_table_stats FORCE, LOCK=NONE; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE mysql.innodb_index_stats FORCE, LOCK=NONE; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 63778ddddb2..f278c428d62 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -2815,6 +2815,14 @@ cannot_create_many_fulltext_index: } } + if (m_prebuilt->table->is_stats_table()) { + if (ha_alter_info->online) { + ha_alter_info->unsupported_reason = + table_share->table_name.str; + } + online= false; + } + // FIXME: implement Online DDL for system-versioned operations if (ha_alter_info->handler_flags & INNOBASE_ALTER_VERSIONED_REBUILD) { if (ha_alter_info->online) { From e309e02447c44463f2638330241ef001c8c32d6d Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 23 Feb 2024 13:42:46 +0530 Subject: [PATCH 018/106] MDEV-30655 IMPORT TABLESPACE fails with column count or index count mismatch update_vcol_pos(): pass table id as table_id_t instead of ulint. --- storage/innobase/row/row0import.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index f8bb022b95f..fb598e0597c 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -4521,7 +4521,7 @@ static void row_import_autoinc(dict_table_t *table, row_prebuilt_t *prebuilt, @param new_pos position value @param trx transaction @return DB_SUCCESS or error code */ -dberr_t update_vcol_pos(ulint table_id, ulint new_pos, trx_t *trx) +dberr_t update_vcol_pos(table_id_t table_id, ulint new_pos, trx_t *trx) { pars_info_t *info= pars_info_create(); pars_info_add_ull_literal(info, "id", table_id); From 5b8493ba34a4e5393ad9bdfe2803a11780ef3f52 Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Fri, 23 Feb 2024 21:29:21 +0700 Subject: [PATCH 019/106] MDEV-15656 follow-up: fix rocksdb.group_min_max test --- storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result b/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result index a070ba91a55..e993e9dd5b9 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result @@ -3514,7 +3514,7 @@ SHOW SESSION STATUS LIKE 'Handler_read%'; Variable_name Value Handler_read_first 0 Handler_read_key 3 -Handler_read_last 1 +Handler_read_last 0 Handler_read_next 0 Handler_read_prev 0 Handler_read_retry 0 From e63311c2cf9c4cf9071429370a1567ce4c6f369b Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 21 Feb 2024 11:41:50 +0400 Subject: [PATCH 020/106] MDEV-33496 Out of range error in AVG(YEAR(datetime)) due to a wrong data type Functions extracting non-negative datetime components: - YEAR(dt), EXTRACT(YEAR FROM dt) - QUARTER(td), EXTRACT(QUARTER FROM dt) - MONTH(dt), EXTRACT(MONTH FROM dt) - WEEK(dt), EXTRACT(WEEK FROM dt) - HOUR(dt), - MINUTE(dt), - SECOND(dt), - MICROSECOND(dt), - DAYOFYEAR(dt) - EXTRACT(YEAR_MONTH FROM dt) did not set their max_length properly, so in the DECIMAL context they created a too small DECIMAL column, which led to the 'Out of range value' error. The problem is that most of these functions historically returned the signed INT data type. There were two simple ways to fix these functions: 1. Add +1 to max_length. But this would also change their size in the string context and create too long VARCHAR columns, with +1 excessive size. 2. Preserve max_length, but change the data type from INT to INT UNSIGNED. But this would break backward compatibility. Also, using UNSIGNED is generally not desirable, it's better to stay with signed when possible. This fix implements another solution, which it makes all these functions work well in all contexts: int, decimal, string. Fix details: - Adding a new special class Type_handler_long_ge0 - the data type handler for expressions which: * should look like normal signed INT * but which known not to return negative values Expressions handled by Type_handler_long_ge0 store in Item::max_length only the number of digits, without adding +1 for the sign. - Fixing Item_extract to use Type_handler_long_ge0 for non-negative datetime components: YEAR, YEAR_MONTH, QUARTER, MONTH, WEEK - Adding a new abstract class Item_long_ge0_func, for functions returning non-negative datetime components. Item_long_ge0_func uses Type_handler_long_ge0 as the type handler. The class hierarchy now looks as follows: Item_long_ge0_func Item_long_func_date_field Item_func_to_days Item_func_dayofmonth Item_func_dayofyear Item_func_quarter Item_func_year Item_long_func_time_field Item_func_hour Item_func_minute Item_func_second Item_func_microsecond - Cleanup: EXTRACT(QUARTER FROM dt) created an excessive VARCHAR column in string context. Changing its length from 2 to 1. --- mysql-test/main/func_extract.result | 882 +++++++++++++++++++++++++ mysql-test/main/func_extract.test | 251 +++++++ mysql-test/main/func_time.result | 20 +- mysql-test/main/ps_2myisam.result | 4 +- mysql-test/main/ps_3innodb.result | 4 +- mysql-test/main/ps_4heap.result | 4 +- mysql-test/main/ps_5merge.result | 8 +- mysql-test/suite/maria/ps_maria.result | 4 +- sql/item_func.cc | 32 +- sql/item_func.h | 27 + sql/item_sum.cc | 15 + sql/item_sum.h | 1 + sql/item_timefunc.cc | 2 +- sql/item_timefunc.h | 33 +- sql/sql_type.cc | 91 +++ sql/sql_type.h | 33 + 16 files changed, 1373 insertions(+), 38 deletions(-) diff --git a/mysql-test/main/func_extract.result b/mysql-test/main/func_extract.result index bebb8c717f6..dc71f6ae27a 100644 --- a/mysql-test/main/func_extract.result +++ b/mysql-test/main/func_extract.result @@ -590,3 +590,885 @@ Warning 1292 Truncated incorrect time value: '01:02:03/' Warning 1292 Truncated incorrect time value: '01:02:03/' Warning 1292 Truncated incorrect INTERVAL DAY TO SECOND value: '01:02:03/' DROP TABLE t1; +# +# Start of 10.5 tests +# +# +# MDEV-33496 Out of range error in AVG(YEAR(datetime)) due to a wrong data type +# +CREATE FUNCTION select01() RETURNS TEXT RETURN 'SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?'; +CREATE FUNCTION select02() RETURNS TEXT RETURN 'SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)'; +CREATE TABLE t1 (a DATETIME(6)); +INSERT INTO t1 VALUES ('2001-12-31 10:20:30.999999'); +CREATE FUNCTION params(expr TEXT, count INT) RETURNS TEXT +BEGIN +RETURN CONCAT(expr, REPEAT(CONCAT(', ', expr), count-1)); +END; +$$ +CREATE PROCEDURE show_drop() +BEGIN +SELECT TABLE_NAME, COLUMN_TYPE, COLUMN_NAME +FROM INFORMATION_SCHEMA.COLUMNS +WHERE TABLE_SCHEMA='test' + AND TABLE_NAME IN ('t1e_nm','t2e_nm','t1f_nm','t2f_nm', +'t1e_ps','t1f_ps','t2e_ps','t2f_ps') +ORDER BY LEFT(TABLE_NAME, 2), ORDINAL_POSITION, TABLE_NAME; +FOR rec IN (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA='test' + AND TABLE_NAME IN ('t1e_nm','t2e_nm','t1f_nm','t2f_nm', +'t1e_ps','t1f_ps','t2e_ps','t2f_ps')) +DO +EXECUTE IMMEDIATE CONCAT('DROP TABLE ', rec.TABLE_NAME); +END FOR; +END; +$$ +CREATE PROCEDURE p1(unit VARCHAR(32)) +BEGIN +DECLARE do_extract BOOL DEFAULT unit NOT IN('DAYOFYEAR'); +DECLARE query01 TEXT DEFAULT +CONCAT('CREATE TABLE t2 AS ', select01(), ' FROM t1'); +DECLARE query02 TEXT DEFAULT +CONCAT('CREATE TABLE t2 AS ', select02(), ' FROM t1'); +IF (do_extract) +THEN +EXECUTE IMMEDIATE REPLACE(REPLACE(query01,'t2','t1e_nm'),'?', CONCAT('EXTRACT(',unit,' FROM a)')); +EXECUTE IMMEDIATE REPLACE(REPLACE(query02,'t2','t2e_nm'),'?', CONCAT('EXTRACT(',unit,' FROM a)')); +END IF; +EXECUTE IMMEDIATE REPLACE(REPLACE(query01,'t2','t1f_nm'),'?', CONCAT(unit,'(a)')); +EXECUTE IMMEDIATE REPLACE(REPLACE(query02,'t2','t2f_nm'),'?', CONCAT(unit,'(a)')); +END; +$$ + + +# EXTRACT(YEAR FROM expr) and YEAR(expr) are equivalent +CALL p1('YEAR'); +EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(YEAR FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), YEAR(TIMESTAMP'2001-12-13 10:20:30.999999'); +CALL show_drop; +TABLE_NAME COLUMN_TYPE COLUMN_NAME +t1e_nm int(5) EXTRACT(YEAR FROM a) +t1e_ps int(5) ? +t1f_nm int(5) YEAR(a) +t1f_ps int(5) ? +t1e_nm int(4) unsigned CAST(EXTRACT(YEAR FROM a) AS UNSIGNED) +t1e_ps int(4) unsigned CAST(? AS UNSIGNED) +t1f_nm int(4) unsigned CAST(YEAR(a) AS UNSIGNED) +t1f_ps int(4) unsigned CAST(? AS UNSIGNED) +t1e_nm int(5) CAST(EXTRACT(YEAR FROM a) AS SIGNED) +t1e_ps int(5) CAST(? AS SIGNED) +t1f_nm int(5) CAST(YEAR(a) AS SIGNED) +t1f_ps int(5) CAST(? AS SIGNED) +t1e_nm int(5) ABS(EXTRACT(YEAR FROM a)) +t1e_ps int(5) ABS(?) +t1f_nm int(5) ABS(YEAR(a)) +t1f_ps int(5) ABS(?) +t1e_nm int(5) ROUND(EXTRACT(YEAR FROM a)) +t1e_ps int(5) ROUND(?) +t1f_nm int(5) ROUND(YEAR(a)) +t1f_ps int(5) ROUND(?) +t1e_nm int(5) -EXTRACT(YEAR FROM a) +t1e_ps int(5) -? +t1f_nm int(5) -YEAR(a) +t1f_ps int(5) -? +t1e_nm int(6) ROUND(EXTRACT(YEAR FROM a),-1) +t1e_ps int(6) ROUND(?,-1) +t1f_nm int(6) ROUND(YEAR(a),-1) +t1f_ps int(6) ROUND(?,-1) +t1e_nm int(6) EXTRACT(YEAR FROM a)+0 +t1e_ps int(6) ?+0 +t1f_nm int(6) YEAR(a)+0 +t1f_ps int(6) ?+0 +t1e_nm decimal(6,1) EXTRACT(YEAR FROM a)+0.0 +t1e_ps decimal(6,1) ?+0.0 +t1f_nm decimal(6,1) YEAR(a)+0.0 +t1f_ps decimal(6,1) ?+0.0 +t1e_nm varchar(4) CONCAT(EXTRACT(YEAR FROM a)) +t1e_ps varchar(4) CONCAT(?) +t1f_nm varchar(4) CONCAT(YEAR(a)) +t1f_ps varchar(4) CONCAT(?) +t1e_nm int(5) LEAST(EXTRACT(YEAR FROM a),EXTRACT(YEAR FROM a)) +t1e_ps int(5) LEAST(?,?) +t1f_nm int(5) LEAST(YEAR(a),YEAR(a)) +t1f_ps int(5) LEAST(?,?) +t1e_nm int(5) COALESCE(EXTRACT(YEAR FROM a)) +t1e_ps int(5) COALESCE(?) +t1f_nm int(5) COALESCE(YEAR(a)) +t1f_ps int(5) COALESCE(?) +t1e_nm int(5) COALESCE(EXTRACT(YEAR FROM a),CAST(1 AS SIGNED)) +t1e_ps int(5) COALESCE(?,CAST(1 AS SIGNED)) +t1f_nm int(5) COALESCE(YEAR(a),CAST(1 AS SIGNED)) +t1f_ps int(5) COALESCE(?,CAST(1 AS SIGNED)) +t1e_nm decimal(4,0) COALESCE(EXTRACT(YEAR FROM a),CAST(1 AS UNSIGNED)) +t1e_ps decimal(4,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1f_nm decimal(4,0) COALESCE(YEAR(a),CAST(1 AS UNSIGNED)) +t1f_ps decimal(4,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1e_nm int(5) @a:=EXTRACT(YEAR FROM a) +t1e_ps int(5) @a:=? +t1f_nm int(5) @a:=YEAR(a) +t1f_ps int(5) @a:=? +t2e_nm decimal(8,4) AVG(EXTRACT(YEAR FROM a)) +t2e_ps decimal(8,4) AVG(?) +t2f_nm decimal(8,4) AVG(YEAR(a)) +t2f_ps decimal(8,4) AVG(?) +t2e_nm bigint(5) MIN(EXTRACT(YEAR FROM a)) +t2e_ps bigint(5) MIN(?) +t2f_nm bigint(5) MIN(YEAR(a)) +t2f_ps bigint(5) MIN(?) +t2e_nm bigint(5) MAX(EXTRACT(YEAR FROM a)) +t2e_ps bigint(5) MAX(?) +t2f_nm bigint(5) MAX(YEAR(a)) +t2f_ps bigint(5) MAX(?) +t2e_nm mediumtext GROUP_CONCAT(EXTRACT(YEAR FROM a)) +t2e_ps mediumtext GROUP_CONCAT(?) +t2f_nm mediumtext GROUP_CONCAT(YEAR(a)) +t2f_ps mediumtext GROUP_CONCAT(?) + + +# EXTRACT(QUARTER FROM expr) and QUARTER(expr) are equavalent +CALL p1('QUARTER'); +EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(QUARTER FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'), QUARTER(TIMESTAMP'2001-12-13 10:20:30.999999'); +CALL show_drop; +TABLE_NAME COLUMN_TYPE COLUMN_NAME +t1e_nm int(2) EXTRACT(QUARTER FROM a) +t1e_ps int(2) ? +t1f_nm int(2) QUARTER(a) +t1f_ps int(2) ? +t1e_nm int(1) unsigned CAST(EXTRACT(QUARTER FROM a) AS UNSIGNED) +t1e_ps int(1) unsigned CAST(? AS UNSIGNED) +t1f_nm int(1) unsigned CAST(QUARTER(a) AS UNSIGNED) +t1f_ps int(1) unsigned CAST(? AS UNSIGNED) +t1e_nm int(2) CAST(EXTRACT(QUARTER FROM a) AS SIGNED) +t1e_ps int(2) CAST(? AS SIGNED) +t1f_nm int(2) CAST(QUARTER(a) AS SIGNED) +t1f_ps int(2) CAST(? AS SIGNED) +t1e_nm int(2) ABS(EXTRACT(QUARTER FROM a)) +t1e_ps int(2) ABS(?) +t1f_nm int(2) ABS(QUARTER(a)) +t1f_ps int(2) ABS(?) +t1e_nm int(2) ROUND(EXTRACT(QUARTER FROM a)) +t1e_ps int(2) ROUND(?) +t1f_nm int(2) ROUND(QUARTER(a)) +t1f_ps int(2) ROUND(?) +t1e_nm int(2) -EXTRACT(QUARTER FROM a) +t1e_ps int(2) -? +t1f_nm int(2) -QUARTER(a) +t1f_ps int(2) -? +t1e_nm int(3) ROUND(EXTRACT(QUARTER FROM a),-1) +t1e_ps int(3) ROUND(?,-1) +t1f_nm int(3) ROUND(QUARTER(a),-1) +t1f_ps int(3) ROUND(?,-1) +t1e_nm int(3) EXTRACT(QUARTER FROM a)+0 +t1e_ps int(3) ?+0 +t1f_nm int(3) QUARTER(a)+0 +t1f_ps int(3) ?+0 +t1e_nm decimal(3,1) EXTRACT(QUARTER FROM a)+0.0 +t1e_ps decimal(3,1) ?+0.0 +t1f_nm decimal(3,1) QUARTER(a)+0.0 +t1f_ps decimal(3,1) ?+0.0 +t1e_nm varchar(1) CONCAT(EXTRACT(QUARTER FROM a)) +t1e_ps varchar(1) CONCAT(?) +t1f_nm varchar(1) CONCAT(QUARTER(a)) +t1f_ps varchar(1) CONCAT(?) +t1e_nm int(2) LEAST(EXTRACT(QUARTER FROM a),EXTRACT(QUARTER FROM a)) +t1e_ps int(2) LEAST(?,?) +t1f_nm int(2) LEAST(QUARTER(a),QUARTER(a)) +t1f_ps int(2) LEAST(?,?) +t1e_nm int(2) COALESCE(EXTRACT(QUARTER FROM a)) +t1e_ps int(2) COALESCE(?) +t1f_nm int(2) COALESCE(QUARTER(a)) +t1f_ps int(2) COALESCE(?) +t1e_nm int(2) COALESCE(EXTRACT(QUARTER FROM a),CAST(1 AS SIGNED)) +t1e_ps int(2) COALESCE(?,CAST(1 AS SIGNED)) +t1f_nm int(2) COALESCE(QUARTER(a),CAST(1 AS SIGNED)) +t1f_ps int(2) COALESCE(?,CAST(1 AS SIGNED)) +t1e_nm decimal(1,0) COALESCE(EXTRACT(QUARTER FROM a),CAST(1 AS UNSIGNED)) +t1e_ps decimal(1,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1f_nm decimal(1,0) COALESCE(QUARTER(a),CAST(1 AS UNSIGNED)) +t1f_ps decimal(1,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1e_nm int(2) @a:=EXTRACT(QUARTER FROM a) +t1e_ps int(2) @a:=? +t1f_nm int(2) @a:=QUARTER(a) +t1f_ps int(2) @a:=? +t2e_nm decimal(5,4) AVG(EXTRACT(QUARTER FROM a)) +t2e_ps decimal(5,4) AVG(?) +t2f_nm decimal(5,4) AVG(QUARTER(a)) +t2f_ps decimal(5,4) AVG(?) +t2e_nm bigint(2) MIN(EXTRACT(QUARTER FROM a)) +t2e_ps bigint(2) MIN(?) +t2f_nm bigint(2) MIN(QUARTER(a)) +t2f_ps bigint(2) MIN(?) +t2e_nm bigint(2) MAX(EXTRACT(QUARTER FROM a)) +t2e_ps bigint(2) MAX(?) +t2f_nm bigint(2) MAX(QUARTER(a)) +t2f_ps bigint(2) MAX(?) +t2e_nm mediumtext GROUP_CONCAT(EXTRACT(QUARTER FROM a)) +t2e_ps mediumtext GROUP_CONCAT(?) +t2f_nm mediumtext GROUP_CONCAT(QUARTER(a)) +t2f_ps mediumtext GROUP_CONCAT(?) + + +# EXTRACT(MONTH FROM expr) and MONTH(expr) are equavalent +CALL p1('MONTH'); +EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MONTH FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'), MONTH(TIMESTAMP'2001-12-13 10:20:30.999999'); +CALL show_drop; +TABLE_NAME COLUMN_TYPE COLUMN_NAME +t1e_nm int(3) EXTRACT(MONTH FROM a) +t1e_ps int(3) ? +t1f_nm int(3) MONTH(a) +t1f_ps int(3) ? +t1e_nm int(2) unsigned CAST(EXTRACT(MONTH FROM a) AS UNSIGNED) +t1e_ps int(2) unsigned CAST(? AS UNSIGNED) +t1f_nm int(2) unsigned CAST(MONTH(a) AS UNSIGNED) +t1f_ps int(2) unsigned CAST(? AS UNSIGNED) +t1e_nm int(3) CAST(EXTRACT(MONTH FROM a) AS SIGNED) +t1e_ps int(3) CAST(? AS SIGNED) +t1f_nm int(3) CAST(MONTH(a) AS SIGNED) +t1f_ps int(3) CAST(? AS SIGNED) +t1e_nm int(3) ABS(EXTRACT(MONTH FROM a)) +t1e_ps int(3) ABS(?) +t1f_nm int(3) ABS(MONTH(a)) +t1f_ps int(3) ABS(?) +t1e_nm int(3) ROUND(EXTRACT(MONTH FROM a)) +t1e_ps int(3) ROUND(?) +t1f_nm int(3) ROUND(MONTH(a)) +t1f_ps int(3) ROUND(?) +t1e_nm int(3) -EXTRACT(MONTH FROM a) +t1e_ps int(3) -? +t1f_nm int(3) -MONTH(a) +t1f_ps int(3) -? +t1e_nm int(4) ROUND(EXTRACT(MONTH FROM a),-1) +t1e_ps int(4) ROUND(?,-1) +t1f_nm int(4) ROUND(MONTH(a),-1) +t1f_ps int(4) ROUND(?,-1) +t1e_nm int(4) EXTRACT(MONTH FROM a)+0 +t1e_ps int(4) ?+0 +t1f_nm int(4) MONTH(a)+0 +t1f_ps int(4) ?+0 +t1e_nm decimal(4,1) EXTRACT(MONTH FROM a)+0.0 +t1e_ps decimal(4,1) ?+0.0 +t1f_nm decimal(4,1) MONTH(a)+0.0 +t1f_ps decimal(4,1) ?+0.0 +t1e_nm varchar(2) CONCAT(EXTRACT(MONTH FROM a)) +t1e_ps varchar(2) CONCAT(?) +t1f_nm varchar(2) CONCAT(MONTH(a)) +t1f_ps varchar(2) CONCAT(?) +t1e_nm int(3) LEAST(EXTRACT(MONTH FROM a),EXTRACT(MONTH FROM a)) +t1e_ps int(3) LEAST(?,?) +t1f_nm int(3) LEAST(MONTH(a),MONTH(a)) +t1f_ps int(3) LEAST(?,?) +t1e_nm int(3) COALESCE(EXTRACT(MONTH FROM a)) +t1e_ps int(3) COALESCE(?) +t1f_nm int(3) COALESCE(MONTH(a)) +t1f_ps int(3) COALESCE(?) +t1e_nm int(3) COALESCE(EXTRACT(MONTH FROM a),CAST(1 AS SIGNED)) +t1e_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1f_nm int(3) COALESCE(MONTH(a),CAST(1 AS SIGNED)) +t1f_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1e_nm decimal(2,0) COALESCE(EXTRACT(MONTH FROM a),CAST(1 AS UNSIGNED)) +t1e_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1f_nm decimal(2,0) COALESCE(MONTH(a),CAST(1 AS UNSIGNED)) +t1f_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1e_nm int(3) @a:=EXTRACT(MONTH FROM a) +t1e_ps int(3) @a:=? +t1f_nm int(3) @a:=MONTH(a) +t1f_ps int(3) @a:=? +t2e_nm decimal(6,4) AVG(EXTRACT(MONTH FROM a)) +t2e_ps decimal(6,4) AVG(?) +t2f_nm decimal(6,4) AVG(MONTH(a)) +t2f_ps decimal(6,4) AVG(?) +t2e_nm bigint(3) MIN(EXTRACT(MONTH FROM a)) +t2e_ps bigint(3) MIN(?) +t2f_nm bigint(3) MIN(MONTH(a)) +t2f_ps bigint(3) MIN(?) +t2e_nm bigint(3) MAX(EXTRACT(MONTH FROM a)) +t2e_ps bigint(3) MAX(?) +t2f_nm bigint(3) MAX(MONTH(a)) +t2f_ps bigint(3) MAX(?) +t2e_nm mediumtext GROUP_CONCAT(EXTRACT(MONTH FROM a)) +t2e_ps mediumtext GROUP_CONCAT(?) +t2f_nm mediumtext GROUP_CONCAT(MONTH(a)) +t2f_ps mediumtext GROUP_CONCAT(?) + + +# EXTRACT(WEEK FROM expr) and WEEK(expr) are equavalent +CALL p1('WEEK'); +EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(WEEK FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'), WEEK(TIMESTAMP'2001-12-13 10:20:30.999999'); +CALL show_drop; +TABLE_NAME COLUMN_TYPE COLUMN_NAME +t1e_nm int(3) EXTRACT(WEEK FROM a) +t1e_ps int(3) ? +t1f_nm int(3) WEEK(a) +t1f_ps int(3) ? +t1e_nm int(2) unsigned CAST(EXTRACT(WEEK FROM a) AS UNSIGNED) +t1e_ps int(2) unsigned CAST(? AS UNSIGNED) +t1f_nm int(2) unsigned CAST(WEEK(a) AS UNSIGNED) +t1f_ps int(2) unsigned CAST(? AS UNSIGNED) +t1e_nm int(3) CAST(EXTRACT(WEEK FROM a) AS SIGNED) +t1e_ps int(3) CAST(? AS SIGNED) +t1f_nm int(3) CAST(WEEK(a) AS SIGNED) +t1f_ps int(3) CAST(? AS SIGNED) +t1e_nm int(3) ABS(EXTRACT(WEEK FROM a)) +t1e_ps int(3) ABS(?) +t1f_nm int(3) ABS(WEEK(a)) +t1f_ps int(3) ABS(?) +t1e_nm int(3) ROUND(EXTRACT(WEEK FROM a)) +t1e_ps int(3) ROUND(?) +t1f_nm int(3) ROUND(WEEK(a)) +t1f_ps int(3) ROUND(?) +t1e_nm int(3) -EXTRACT(WEEK FROM a) +t1e_ps int(3) -? +t1f_nm int(3) -WEEK(a) +t1f_ps int(3) -? +t1e_nm int(4) ROUND(EXTRACT(WEEK FROM a),-1) +t1e_ps int(4) ROUND(?,-1) +t1f_nm int(4) ROUND(WEEK(a),-1) +t1f_ps int(4) ROUND(?,-1) +t1e_nm int(4) EXTRACT(WEEK FROM a)+0 +t1e_ps int(4) ?+0 +t1f_nm int(4) WEEK(a)+0 +t1f_ps int(4) ?+0 +t1e_nm decimal(4,1) EXTRACT(WEEK FROM a)+0.0 +t1e_ps decimal(4,1) ?+0.0 +t1f_nm decimal(4,1) WEEK(a)+0.0 +t1f_ps decimal(4,1) ?+0.0 +t1e_nm varchar(2) CONCAT(EXTRACT(WEEK FROM a)) +t1e_ps varchar(2) CONCAT(?) +t1f_nm varchar(2) CONCAT(WEEK(a)) +t1f_ps varchar(2) CONCAT(?) +t1e_nm int(3) LEAST(EXTRACT(WEEK FROM a),EXTRACT(WEEK FROM a)) +t1e_ps int(3) LEAST(?,?) +t1f_nm int(3) LEAST(WEEK(a),WEEK(a)) +t1f_ps int(3) LEAST(?,?) +t1e_nm int(3) COALESCE(EXTRACT(WEEK FROM a)) +t1e_ps int(3) COALESCE(?) +t1f_nm int(3) COALESCE(WEEK(a)) +t1f_ps int(3) COALESCE(?) +t1e_nm int(3) COALESCE(EXTRACT(WEEK FROM a),CAST(1 AS SIGNED)) +t1e_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1f_nm int(3) COALESCE(WEEK(a),CAST(1 AS SIGNED)) +t1f_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1e_nm decimal(2,0) COALESCE(EXTRACT(WEEK FROM a),CAST(1 AS UNSIGNED)) +t1e_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1f_nm decimal(2,0) COALESCE(WEEK(a),CAST(1 AS UNSIGNED)) +t1f_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1e_nm int(3) @a:=EXTRACT(WEEK FROM a) +t1e_ps int(3) @a:=? +t1f_nm int(3) @a:=WEEK(a) +t1f_ps int(3) @a:=? +t2e_nm decimal(6,4) AVG(EXTRACT(WEEK FROM a)) +t2e_ps decimal(6,4) AVG(?) +t2f_nm decimal(6,4) AVG(WEEK(a)) +t2f_ps decimal(6,4) AVG(?) +t2e_nm bigint(3) MIN(EXTRACT(WEEK FROM a)) +t2e_ps bigint(3) MIN(?) +t2f_nm bigint(3) MIN(WEEK(a)) +t2f_ps bigint(3) MIN(?) +t2e_nm bigint(3) MAX(EXTRACT(WEEK FROM a)) +t2e_ps bigint(3) MAX(?) +t2f_nm bigint(3) MAX(WEEK(a)) +t2f_ps bigint(3) MAX(?) +t2e_nm mediumtext GROUP_CONCAT(EXTRACT(WEEK FROM a)) +t2e_ps mediumtext GROUP_CONCAT(?) +t2f_nm mediumtext GROUP_CONCAT(WEEK(a)) +t2f_ps mediumtext GROUP_CONCAT(?) + + +# EXTRACT(DAY FROM expr) returns hours/24 and includes the sign for TIME +# DAY(expr) returns the DD part of CAST(expr AS DATETIME) +CALL p1('DAY'); +EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(DAY FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'), DAY(TIMESTAMP'2001-12-13 10:20:30.999999'); +CALL show_drop; +TABLE_NAME COLUMN_TYPE COLUMN_NAME +t1e_nm int(3) EXTRACT(DAY FROM a) +t1e_ps int(3) ? +t1f_nm int(3) DAY(a) +t1f_ps int(3) ? +t1e_nm bigint(20) unsigned CAST(EXTRACT(DAY FROM a) AS UNSIGNED) +t1e_ps bigint(20) unsigned CAST(? AS UNSIGNED) +t1f_nm int(2) unsigned CAST(DAY(a) AS UNSIGNED) +t1f_ps int(2) unsigned CAST(? AS UNSIGNED) +t1e_nm int(3) CAST(EXTRACT(DAY FROM a) AS SIGNED) +t1e_ps int(3) CAST(? AS SIGNED) +t1f_nm int(3) CAST(DAY(a) AS SIGNED) +t1f_ps int(3) CAST(? AS SIGNED) +t1e_nm int(3) ABS(EXTRACT(DAY FROM a)) +t1e_ps int(3) ABS(?) +t1f_nm int(3) ABS(DAY(a)) +t1f_ps int(3) ABS(?) +t1e_nm int(3) ROUND(EXTRACT(DAY FROM a)) +t1e_ps int(3) ROUND(?) +t1f_nm int(3) ROUND(DAY(a)) +t1f_ps int(3) ROUND(?) +t1e_nm int(4) -EXTRACT(DAY FROM a) +t1e_ps int(4) -? +t1f_nm int(3) -DAY(a) +t1f_ps int(3) -? +t1e_nm int(4) ROUND(EXTRACT(DAY FROM a),-1) +t1e_ps int(4) ROUND(?,-1) +t1f_nm int(4) ROUND(DAY(a),-1) +t1f_ps int(4) ROUND(?,-1) +t1e_nm int(4) EXTRACT(DAY FROM a)+0 +t1e_ps int(4) ?+0 +t1f_nm int(4) DAY(a)+0 +t1f_ps int(4) ?+0 +t1e_nm decimal(4,1) EXTRACT(DAY FROM a)+0.0 +t1e_ps decimal(4,1) ?+0.0 +t1f_nm decimal(4,1) DAY(a)+0.0 +t1f_ps decimal(4,1) ?+0.0 +t1e_nm varchar(3) CONCAT(EXTRACT(DAY FROM a)) +t1e_ps varchar(3) CONCAT(?) +t1f_nm varchar(2) CONCAT(DAY(a)) +t1f_ps varchar(2) CONCAT(?) +t1e_nm int(3) LEAST(EXTRACT(DAY FROM a),EXTRACT(DAY FROM a)) +t1e_ps int(3) LEAST(?,?) +t1f_nm int(3) LEAST(DAY(a),DAY(a)) +t1f_ps int(3) LEAST(?,?) +t1e_nm int(3) COALESCE(EXTRACT(DAY FROM a)) +t1e_ps int(3) COALESCE(?) +t1f_nm int(3) COALESCE(DAY(a)) +t1f_ps int(3) COALESCE(?) +t1e_nm int(3) COALESCE(EXTRACT(DAY FROM a),CAST(1 AS SIGNED)) +t1e_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1f_nm int(3) COALESCE(DAY(a),CAST(1 AS SIGNED)) +t1f_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1e_nm decimal(2,0) COALESCE(EXTRACT(DAY FROM a),CAST(1 AS UNSIGNED)) +t1e_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1f_nm decimal(2,0) COALESCE(DAY(a),CAST(1 AS UNSIGNED)) +t1f_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1e_nm int(3) @a:=EXTRACT(DAY FROM a) +t1e_ps int(3) @a:=? +t1f_nm int(3) @a:=DAY(a) +t1f_ps int(3) @a:=? +t2e_nm decimal(6,4) AVG(EXTRACT(DAY FROM a)) +t2e_ps decimal(6,4) AVG(?) +t2f_nm decimal(6,4) AVG(DAY(a)) +t2f_ps decimal(6,4) AVG(?) +t2e_nm bigint(3) MIN(EXTRACT(DAY FROM a)) +t2e_ps bigint(3) MIN(?) +t2f_nm bigint(3) MIN(DAY(a)) +t2f_ps bigint(3) MIN(?) +t2e_nm bigint(3) MAX(EXTRACT(DAY FROM a)) +t2e_ps bigint(3) MAX(?) +t2f_nm bigint(3) MAX(DAY(a)) +t2f_ps bigint(3) MAX(?) +t2e_nm mediumtext GROUP_CONCAT(EXTRACT(DAY FROM a)) +t2e_ps mediumtext GROUP_CONCAT(?) +t2f_nm mediumtext GROUP_CONCAT(DAY(a)) +t2f_ps mediumtext GROUP_CONCAT(?) + + +# EXTRACT(HOUR FROM expr) returns hours%24 and includes the sign for TIME +# HOUR(expr) returns the hh part of CAST(expr AS DATETIME) +CALL p1('HOUR'); +EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(HOUR FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'), HOUR(TIMESTAMP'2001-12-13 10:20:30.999999'); +CALL show_drop; +TABLE_NAME COLUMN_TYPE COLUMN_NAME +t1e_nm int(3) EXTRACT(HOUR FROM a) +t1e_ps int(3) ? +t1f_nm int(3) HOUR(a) +t1f_ps int(3) ? +t1e_nm bigint(20) unsigned CAST(EXTRACT(HOUR FROM a) AS UNSIGNED) +t1e_ps bigint(20) unsigned CAST(? AS UNSIGNED) +t1f_nm int(2) unsigned CAST(HOUR(a) AS UNSIGNED) +t1f_ps int(2) unsigned CAST(? AS UNSIGNED) +t1e_nm int(3) CAST(EXTRACT(HOUR FROM a) AS SIGNED) +t1e_ps int(3) CAST(? AS SIGNED) +t1f_nm int(3) CAST(HOUR(a) AS SIGNED) +t1f_ps int(3) CAST(? AS SIGNED) +t1e_nm int(3) ABS(EXTRACT(HOUR FROM a)) +t1e_ps int(3) ABS(?) +t1f_nm int(3) ABS(HOUR(a)) +t1f_ps int(3) ABS(?) +t1e_nm int(3) ROUND(EXTRACT(HOUR FROM a)) +t1e_ps int(3) ROUND(?) +t1f_nm int(3) ROUND(HOUR(a)) +t1f_ps int(3) ROUND(?) +t1e_nm int(4) -EXTRACT(HOUR FROM a) +t1e_ps int(4) -? +t1f_nm int(3) -HOUR(a) +t1f_ps int(3) -? +t1e_nm int(4) ROUND(EXTRACT(HOUR FROM a),-1) +t1e_ps int(4) ROUND(?,-1) +t1f_nm int(4) ROUND(HOUR(a),-1) +t1f_ps int(4) ROUND(?,-1) +t1e_nm int(4) EXTRACT(HOUR FROM a)+0 +t1e_ps int(4) ?+0 +t1f_nm int(4) HOUR(a)+0 +t1f_ps int(4) ?+0 +t1e_nm decimal(4,1) EXTRACT(HOUR FROM a)+0.0 +t1e_ps decimal(4,1) ?+0.0 +t1f_nm decimal(4,1) HOUR(a)+0.0 +t1f_ps decimal(4,1) ?+0.0 +t1e_nm varchar(3) CONCAT(EXTRACT(HOUR FROM a)) +t1e_ps varchar(3) CONCAT(?) +t1f_nm varchar(2) CONCAT(HOUR(a)) +t1f_ps varchar(2) CONCAT(?) +t1e_nm int(3) LEAST(EXTRACT(HOUR FROM a),EXTRACT(HOUR FROM a)) +t1e_ps int(3) LEAST(?,?) +t1f_nm int(3) LEAST(HOUR(a),HOUR(a)) +t1f_ps int(3) LEAST(?,?) +t1e_nm int(3) COALESCE(EXTRACT(HOUR FROM a)) +t1e_ps int(3) COALESCE(?) +t1f_nm int(3) COALESCE(HOUR(a)) +t1f_ps int(3) COALESCE(?) +t1e_nm int(3) COALESCE(EXTRACT(HOUR FROM a),CAST(1 AS SIGNED)) +t1e_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1f_nm int(3) COALESCE(HOUR(a),CAST(1 AS SIGNED)) +t1f_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1e_nm decimal(2,0) COALESCE(EXTRACT(HOUR FROM a),CAST(1 AS UNSIGNED)) +t1e_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1f_nm decimal(2,0) COALESCE(HOUR(a),CAST(1 AS UNSIGNED)) +t1f_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1e_nm int(3) @a:=EXTRACT(HOUR FROM a) +t1e_ps int(3) @a:=? +t1f_nm int(3) @a:=HOUR(a) +t1f_ps int(3) @a:=? +t2e_nm decimal(6,4) AVG(EXTRACT(HOUR FROM a)) +t2e_ps decimal(6,4) AVG(?) +t2f_nm decimal(6,4) AVG(HOUR(a)) +t2f_ps decimal(6,4) AVG(?) +t2e_nm bigint(3) MIN(EXTRACT(HOUR FROM a)) +t2e_ps bigint(3) MIN(?) +t2f_nm bigint(3) MIN(HOUR(a)) +t2f_ps bigint(3) MIN(?) +t2e_nm bigint(3) MAX(EXTRACT(HOUR FROM a)) +t2e_ps bigint(3) MAX(?) +t2f_nm bigint(3) MAX(HOUR(a)) +t2f_ps bigint(3) MAX(?) +t2e_nm mediumtext GROUP_CONCAT(EXTRACT(HOUR FROM a)) +t2e_ps mediumtext GROUP_CONCAT(?) +t2f_nm mediumtext GROUP_CONCAT(HOUR(a)) +t2f_ps mediumtext GROUP_CONCAT(?) + + +# EXTRACT(MINUTE FROM expr) includes the sign for TIME +# MINUTE(expr) returns the absolute value +CALL p1('MINUTE'); +EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MINUTE FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'), MINUTE(TIMESTAMP'2001-12-13 10:20:30.999999'); +CALL show_drop; +TABLE_NAME COLUMN_TYPE COLUMN_NAME +t1e_nm int(3) EXTRACT(MINUTE FROM a) +t1e_ps int(3) ? +t1f_nm int(3) MINUTE(a) +t1f_ps int(3) ? +t1e_nm bigint(20) unsigned CAST(EXTRACT(MINUTE FROM a) AS UNSIGNED) +t1e_ps bigint(20) unsigned CAST(? AS UNSIGNED) +t1f_nm int(2) unsigned CAST(MINUTE(a) AS UNSIGNED) +t1f_ps int(2) unsigned CAST(? AS UNSIGNED) +t1e_nm int(3) CAST(EXTRACT(MINUTE FROM a) AS SIGNED) +t1e_ps int(3) CAST(? AS SIGNED) +t1f_nm int(3) CAST(MINUTE(a) AS SIGNED) +t1f_ps int(3) CAST(? AS SIGNED) +t1e_nm int(3) ABS(EXTRACT(MINUTE FROM a)) +t1e_ps int(3) ABS(?) +t1f_nm int(3) ABS(MINUTE(a)) +t1f_ps int(3) ABS(?) +t1e_nm int(3) ROUND(EXTRACT(MINUTE FROM a)) +t1e_ps int(3) ROUND(?) +t1f_nm int(3) ROUND(MINUTE(a)) +t1f_ps int(3) ROUND(?) +t1e_nm int(4) -EXTRACT(MINUTE FROM a) +t1e_ps int(4) -? +t1f_nm int(3) -MINUTE(a) +t1f_ps int(3) -? +t1e_nm int(4) ROUND(EXTRACT(MINUTE FROM a),-1) +t1e_ps int(4) ROUND(?,-1) +t1f_nm int(4) ROUND(MINUTE(a),-1) +t1f_ps int(4) ROUND(?,-1) +t1e_nm int(4) EXTRACT(MINUTE FROM a)+0 +t1e_ps int(4) ?+0 +t1f_nm int(4) MINUTE(a)+0 +t1f_ps int(4) ?+0 +t1e_nm decimal(4,1) EXTRACT(MINUTE FROM a)+0.0 +t1e_ps decimal(4,1) ?+0.0 +t1f_nm decimal(4,1) MINUTE(a)+0.0 +t1f_ps decimal(4,1) ?+0.0 +t1e_nm varchar(3) CONCAT(EXTRACT(MINUTE FROM a)) +t1e_ps varchar(3) CONCAT(?) +t1f_nm varchar(2) CONCAT(MINUTE(a)) +t1f_ps varchar(2) CONCAT(?) +t1e_nm int(3) LEAST(EXTRACT(MINUTE FROM a),EXTRACT(MINUTE FROM a)) +t1e_ps int(3) LEAST(?,?) +t1f_nm int(3) LEAST(MINUTE(a),MINUTE(a)) +t1f_ps int(3) LEAST(?,?) +t1e_nm int(3) COALESCE(EXTRACT(MINUTE FROM a)) +t1e_ps int(3) COALESCE(?) +t1f_nm int(3) COALESCE(MINUTE(a)) +t1f_ps int(3) COALESCE(?) +t1e_nm int(3) COALESCE(EXTRACT(MINUTE FROM a),CAST(1 AS SIGNED)) +t1e_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1f_nm int(3) COALESCE(MINUTE(a),CAST(1 AS SIGNED)) +t1f_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1e_nm decimal(2,0) COALESCE(EXTRACT(MINUTE FROM a),CAST(1 AS UNSIGNED)) +t1e_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1f_nm decimal(2,0) COALESCE(MINUTE(a),CAST(1 AS UNSIGNED)) +t1f_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1e_nm int(3) @a:=EXTRACT(MINUTE FROM a) +t1e_ps int(3) @a:=? +t1f_nm int(3) @a:=MINUTE(a) +t1f_ps int(3) @a:=? +t2e_nm decimal(6,4) AVG(EXTRACT(MINUTE FROM a)) +t2e_ps decimal(6,4) AVG(?) +t2f_nm decimal(6,4) AVG(MINUTE(a)) +t2f_ps decimal(6,4) AVG(?) +t2e_nm bigint(3) MIN(EXTRACT(MINUTE FROM a)) +t2e_ps bigint(3) MIN(?) +t2f_nm bigint(3) MIN(MINUTE(a)) +t2f_ps bigint(3) MIN(?) +t2e_nm bigint(3) MAX(EXTRACT(MINUTE FROM a)) +t2e_ps bigint(3) MAX(?) +t2f_nm bigint(3) MAX(MINUTE(a)) +t2f_ps bigint(3) MAX(?) +t2e_nm mediumtext GROUP_CONCAT(EXTRACT(MINUTE FROM a)) +t2e_ps mediumtext GROUP_CONCAT(?) +t2f_nm mediumtext GROUP_CONCAT(MINUTE(a)) +t2f_ps mediumtext GROUP_CONCAT(?) + + +# EXTRACT(SECONDS FROM expr) includes the sign for TIME +# SECONDS(expr) returns the absolute value +CALL p1('SECOND'); +EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(SECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), SECOND(TIMESTAMP'2001-12-13 10:20:30.999999'); +CALL show_drop; +TABLE_NAME COLUMN_TYPE COLUMN_NAME +t1e_nm int(3) EXTRACT(SECOND FROM a) +t1e_ps int(3) ? +t1f_nm int(3) SECOND(a) +t1f_ps int(3) ? +t1e_nm bigint(20) unsigned CAST(EXTRACT(SECOND FROM a) AS UNSIGNED) +t1e_ps bigint(20) unsigned CAST(? AS UNSIGNED) +t1f_nm int(2) unsigned CAST(SECOND(a) AS UNSIGNED) +t1f_ps int(2) unsigned CAST(? AS UNSIGNED) +t1e_nm int(3) CAST(EXTRACT(SECOND FROM a) AS SIGNED) +t1e_ps int(3) CAST(? AS SIGNED) +t1f_nm int(3) CAST(SECOND(a) AS SIGNED) +t1f_ps int(3) CAST(? AS SIGNED) +t1e_nm int(3) ABS(EXTRACT(SECOND FROM a)) +t1e_ps int(3) ABS(?) +t1f_nm int(3) ABS(SECOND(a)) +t1f_ps int(3) ABS(?) +t1e_nm int(3) ROUND(EXTRACT(SECOND FROM a)) +t1e_ps int(3) ROUND(?) +t1f_nm int(3) ROUND(SECOND(a)) +t1f_ps int(3) ROUND(?) +t1e_nm int(4) -EXTRACT(SECOND FROM a) +t1e_ps int(4) -? +t1f_nm int(3) -SECOND(a) +t1f_ps int(3) -? +t1e_nm int(4) ROUND(EXTRACT(SECOND FROM a),-1) +t1e_ps int(4) ROUND(?,-1) +t1f_nm int(4) ROUND(SECOND(a),-1) +t1f_ps int(4) ROUND(?,-1) +t1e_nm int(4) EXTRACT(SECOND FROM a)+0 +t1e_ps int(4) ?+0 +t1f_nm int(4) SECOND(a)+0 +t1f_ps int(4) ?+0 +t1e_nm decimal(4,1) EXTRACT(SECOND FROM a)+0.0 +t1e_ps decimal(4,1) ?+0.0 +t1f_nm decimal(4,1) SECOND(a)+0.0 +t1f_ps decimal(4,1) ?+0.0 +t1e_nm varchar(3) CONCAT(EXTRACT(SECOND FROM a)) +t1e_ps varchar(3) CONCAT(?) +t1f_nm varchar(2) CONCAT(SECOND(a)) +t1f_ps varchar(2) CONCAT(?) +t1e_nm int(3) LEAST(EXTRACT(SECOND FROM a),EXTRACT(SECOND FROM a)) +t1e_ps int(3) LEAST(?,?) +t1f_nm int(3) LEAST(SECOND(a),SECOND(a)) +t1f_ps int(3) LEAST(?,?) +t1e_nm int(3) COALESCE(EXTRACT(SECOND FROM a)) +t1e_ps int(3) COALESCE(?) +t1f_nm int(3) COALESCE(SECOND(a)) +t1f_ps int(3) COALESCE(?) +t1e_nm int(3) COALESCE(EXTRACT(SECOND FROM a),CAST(1 AS SIGNED)) +t1e_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1f_nm int(3) COALESCE(SECOND(a),CAST(1 AS SIGNED)) +t1f_ps int(3) COALESCE(?,CAST(1 AS SIGNED)) +t1e_nm decimal(2,0) COALESCE(EXTRACT(SECOND FROM a),CAST(1 AS UNSIGNED)) +t1e_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1f_nm decimal(2,0) COALESCE(SECOND(a),CAST(1 AS UNSIGNED)) +t1f_ps decimal(2,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1e_nm int(3) @a:=EXTRACT(SECOND FROM a) +t1e_ps int(3) @a:=? +t1f_nm int(3) @a:=SECOND(a) +t1f_ps int(3) @a:=? +t2e_nm decimal(6,4) AVG(EXTRACT(SECOND FROM a)) +t2e_ps decimal(6,4) AVG(?) +t2f_nm decimal(6,4) AVG(SECOND(a)) +t2f_ps decimal(6,4) AVG(?) +t2e_nm bigint(3) MIN(EXTRACT(SECOND FROM a)) +t2e_ps bigint(3) MIN(?) +t2f_nm bigint(3) MIN(SECOND(a)) +t2f_ps bigint(3) MIN(?) +t2e_nm bigint(3) MAX(EXTRACT(SECOND FROM a)) +t2e_ps bigint(3) MAX(?) +t2f_nm bigint(3) MAX(SECOND(a)) +t2f_ps bigint(3) MAX(?) +t2e_nm mediumtext GROUP_CONCAT(EXTRACT(SECOND FROM a)) +t2e_ps mediumtext GROUP_CONCAT(?) +t2f_nm mediumtext GROUP_CONCAT(SECOND(a)) +t2f_ps mediumtext GROUP_CONCAT(?) + + +# EXTRACT(MICROSECONDS FROM expr) includes the sign for TIME +# MICROSECONDS(expr) returns the absolute value +CALL p1('MICROSECOND'); +EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'), EXTRACT(MICROSECOND FROM TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'), MICROSECOND(TIMESTAMP'2001-12-13 10:20:30.999999'); +CALL show_drop; +TABLE_NAME COLUMN_TYPE COLUMN_NAME +t1e_nm int(7) EXTRACT(MICROSECOND FROM a) +t1e_ps int(7) ? +t1f_nm int(7) MICROSECOND(a) +t1f_ps int(7) ? +t1e_nm bigint(20) unsigned CAST(EXTRACT(MICROSECOND FROM a) AS UNSIGNED) +t1e_ps bigint(20) unsigned CAST(? AS UNSIGNED) +t1f_nm int(6) unsigned CAST(MICROSECOND(a) AS UNSIGNED) +t1f_ps int(6) unsigned CAST(? AS UNSIGNED) +t1e_nm int(7) CAST(EXTRACT(MICROSECOND FROM a) AS SIGNED) +t1e_ps int(7) CAST(? AS SIGNED) +t1f_nm int(7) CAST(MICROSECOND(a) AS SIGNED) +t1f_ps int(7) CAST(? AS SIGNED) +t1e_nm int(7) ABS(EXTRACT(MICROSECOND FROM a)) +t1e_ps int(7) ABS(?) +t1f_nm int(7) ABS(MICROSECOND(a)) +t1f_ps int(7) ABS(?) +t1e_nm int(7) ROUND(EXTRACT(MICROSECOND FROM a)) +t1e_ps int(7) ROUND(?) +t1f_nm int(7) ROUND(MICROSECOND(a)) +t1f_ps int(7) ROUND(?) +t1e_nm int(8) -EXTRACT(MICROSECOND FROM a) +t1e_ps int(8) -? +t1f_nm int(7) -MICROSECOND(a) +t1f_ps int(7) -? +t1e_nm int(8) ROUND(EXTRACT(MICROSECOND FROM a),-1) +t1e_ps int(8) ROUND(?,-1) +t1f_nm int(8) ROUND(MICROSECOND(a),-1) +t1f_ps int(8) ROUND(?,-1) +t1e_nm int(8) EXTRACT(MICROSECOND FROM a)+0 +t1e_ps int(8) ?+0 +t1f_nm int(8) MICROSECOND(a)+0 +t1f_ps int(8) ?+0 +t1e_nm decimal(8,1) EXTRACT(MICROSECOND FROM a)+0.0 +t1e_ps decimal(8,1) ?+0.0 +t1f_nm decimal(8,1) MICROSECOND(a)+0.0 +t1f_ps decimal(8,1) ?+0.0 +t1e_nm varchar(7) CONCAT(EXTRACT(MICROSECOND FROM a)) +t1e_ps varchar(7) CONCAT(?) +t1f_nm varchar(6) CONCAT(MICROSECOND(a)) +t1f_ps varchar(6) CONCAT(?) +t1e_nm int(7) LEAST(EXTRACT(MICROSECOND FROM a),EXTRACT(MICROSECOND FROM a)) +t1e_ps int(7) LEAST(?,?) +t1f_nm int(7) LEAST(MICROSECOND(a),MICROSECOND(a)) +t1f_ps int(7) LEAST(?,?) +t1e_nm int(7) COALESCE(EXTRACT(MICROSECOND FROM a)) +t1e_ps int(7) COALESCE(?) +t1f_nm int(7) COALESCE(MICROSECOND(a)) +t1f_ps int(7) COALESCE(?) +t1e_nm int(7) COALESCE(EXTRACT(MICROSECOND FROM a),CAST(1 AS SIGNED)) +t1e_ps int(7) COALESCE(?,CAST(1 AS SIGNED)) +t1f_nm int(7) COALESCE(MICROSECOND(a),CAST(1 AS SIGNED)) +t1f_ps int(7) COALESCE(?,CAST(1 AS SIGNED)) +t1e_nm decimal(6,0) COALESCE(EXTRACT(MICROSECOND FROM a),CAST(1 AS UNSIGNED)) +t1e_ps decimal(6,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1f_nm decimal(6,0) COALESCE(MICROSECOND(a),CAST(1 AS UNSIGNED)) +t1f_ps decimal(6,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1e_nm int(7) @a:=EXTRACT(MICROSECOND FROM a) +t1e_ps int(7) @a:=? +t1f_nm int(7) @a:=MICROSECOND(a) +t1f_ps int(7) @a:=? +t2e_nm decimal(10,4) AVG(EXTRACT(MICROSECOND FROM a)) +t2e_ps decimal(10,4) AVG(?) +t2f_nm decimal(10,4) AVG(MICROSECOND(a)) +t2f_ps decimal(10,4) AVG(?) +t2e_nm bigint(7) MIN(EXTRACT(MICROSECOND FROM a)) +t2e_ps bigint(7) MIN(?) +t2f_nm bigint(7) MIN(MICROSECOND(a)) +t2f_ps bigint(7) MIN(?) +t2e_nm bigint(7) MAX(EXTRACT(MICROSECOND FROM a)) +t2e_ps bigint(7) MAX(?) +t2f_nm bigint(7) MAX(MICROSECOND(a)) +t2f_ps bigint(7) MAX(?) +t2e_nm mediumtext GROUP_CONCAT(EXTRACT(MICROSECOND FROM a)) +t2e_ps mediumtext GROUP_CONCAT(?) +t2f_nm mediumtext GROUP_CONCAT(MICROSECOND(a)) +t2f_ps mediumtext GROUP_CONCAT(?) + + +# DAYOFYEAR +CALL p1('DAYOFYEAR'); +EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?' USING DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'); +EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?)' USING DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'), DAYOFYEAR(TIMESTAMP'2001-12-13 10:20:30.999999'); +CALL show_drop; +TABLE_NAME COLUMN_TYPE COLUMN_NAME +t1f_nm int(4) DAYOFYEAR(a) +t1f_ps int(4) ? +t1f_nm int(3) unsigned CAST(DAYOFYEAR(a) AS UNSIGNED) +t1f_ps int(3) unsigned CAST(? AS UNSIGNED) +t1f_nm int(4) CAST(DAYOFYEAR(a) AS SIGNED) +t1f_ps int(4) CAST(? AS SIGNED) +t1f_nm int(4) ABS(DAYOFYEAR(a)) +t1f_ps int(4) ABS(?) +t1f_nm int(4) ROUND(DAYOFYEAR(a)) +t1f_ps int(4) ROUND(?) +t1f_nm int(4) -DAYOFYEAR(a) +t1f_ps int(4) -? +t1f_nm int(5) ROUND(DAYOFYEAR(a),-1) +t1f_ps int(5) ROUND(?,-1) +t1f_nm int(5) DAYOFYEAR(a)+0 +t1f_ps int(5) ?+0 +t1f_nm decimal(5,1) DAYOFYEAR(a)+0.0 +t1f_ps decimal(5,1) ?+0.0 +t1f_nm varchar(3) CONCAT(DAYOFYEAR(a)) +t1f_ps varchar(3) CONCAT(?) +t1f_nm int(4) LEAST(DAYOFYEAR(a),DAYOFYEAR(a)) +t1f_ps int(4) LEAST(?,?) +t1f_nm int(4) COALESCE(DAYOFYEAR(a)) +t1f_ps int(4) COALESCE(?) +t1f_nm int(4) COALESCE(DAYOFYEAR(a),CAST(1 AS SIGNED)) +t1f_ps int(4) COALESCE(?,CAST(1 AS SIGNED)) +t1f_nm decimal(3,0) COALESCE(DAYOFYEAR(a),CAST(1 AS UNSIGNED)) +t1f_ps decimal(3,0) COALESCE(?,CAST(1 AS UNSIGNED)) +t1f_nm int(4) @a:=DAYOFYEAR(a) +t1f_ps int(4) @a:=? +t2f_nm decimal(7,4) AVG(DAYOFYEAR(a)) +t2f_ps decimal(7,4) AVG(?) +t2f_nm bigint(4) MIN(DAYOFYEAR(a)) +t2f_ps bigint(4) MIN(?) +t2f_nm bigint(4) MAX(DAYOFYEAR(a)) +t2f_ps bigint(4) MAX(?) +t2f_nm mediumtext GROUP_CONCAT(DAYOFYEAR(a)) +t2f_ps mediumtext GROUP_CONCAT(?) +DROP TABLE t1; +DROP PROCEDURE p1; +DROP PROCEDURE show_drop; +DROP FUNCTION params; +DROP FUNCTION select01; +DROP FUNCTION select02; +# +# End of 10.5 tests +# diff --git a/mysql-test/main/func_extract.test b/mysql-test/main/func_extract.test index 97920f1872f..dd808443f58 100644 --- a/mysql-test/main/func_extract.test +++ b/mysql-test/main/func_extract.test @@ -263,3 +263,254 @@ SELECT FROM t1; DROP TABLE t1; --enable_view_protocol + + +--echo # +--echo # Start of 10.5 tests +--echo # + +--echo # +--echo # MDEV-33496 Out of range error in AVG(YEAR(datetime)) due to a wrong data type +--echo # + +let select01=SELECT ?, CAST(? AS UNSIGNED), CAST(? AS SIGNED), ABS(?), ROUND(?), -?, ROUND(?,-1), ?+0, ?+0.0, CONCAT(?), LEAST(?,?), COALESCE(?), COALESCE(?,CAST(1 AS SIGNED)), COALESCE(?,CAST(1 AS UNSIGNED)), @a:=?; +let pcount01=16; +let select02=SELECT AVG(?), MIN(?), MAX(?), GROUP_CONCAT(?); +let pcount02=4; +let ts=TIMESTAMP'2001-12-13 10:20:30.999999'; + +eval CREATE FUNCTION select01() RETURNS TEXT RETURN '$select01'; +eval CREATE FUNCTION select02() RETURNS TEXT RETURN '$select02'; + +CREATE TABLE t1 (a DATETIME(6)); +INSERT INTO t1 VALUES ('2001-12-31 10:20:30.999999'); + +DELIMITER $$; +CREATE FUNCTION params(expr TEXT, count INT) RETURNS TEXT +BEGIN + RETURN CONCAT(expr, REPEAT(CONCAT(', ', expr), count-1)); +END; +$$ +CREATE PROCEDURE show_drop() +BEGIN + SELECT TABLE_NAME, COLUMN_TYPE, COLUMN_NAME + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA='test' + AND TABLE_NAME IN ('t1e_nm','t2e_nm','t1f_nm','t2f_nm', + 't1e_ps','t1f_ps','t2e_ps','t2f_ps') + ORDER BY LEFT(TABLE_NAME, 2), ORDINAL_POSITION, TABLE_NAME; + + FOR rec IN (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES + WHERE TABLE_SCHEMA='test' + AND TABLE_NAME IN ('t1e_nm','t2e_nm','t1f_nm','t2f_nm', + 't1e_ps','t1f_ps','t2e_ps','t2f_ps')) + DO + EXECUTE IMMEDIATE CONCAT('DROP TABLE ', rec.TABLE_NAME); + END FOR; +END; +$$ +CREATE PROCEDURE p1(unit VARCHAR(32)) +BEGIN + DECLARE do_extract BOOL DEFAULT unit NOT IN('DAYOFYEAR'); + + DECLARE query01 TEXT DEFAULT + CONCAT('CREATE TABLE t2 AS ', select01(), ' FROM t1'); + + DECLARE query02 TEXT DEFAULT + CONCAT('CREATE TABLE t2 AS ', select02(), ' FROM t1'); + + IF (do_extract) + THEN + EXECUTE IMMEDIATE REPLACE(REPLACE(query01,'t2','t1e_nm'),'?', CONCAT('EXTRACT(',unit,' FROM a)')); + EXECUTE IMMEDIATE REPLACE(REPLACE(query02,'t2','t2e_nm'),'?', CONCAT('EXTRACT(',unit,' FROM a)')); + END IF; + EXECUTE IMMEDIATE REPLACE(REPLACE(query01,'t2','t1f_nm'),'?', CONCAT(unit,'(a)')); + EXECUTE IMMEDIATE REPLACE(REPLACE(query02,'t2','t2f_nm'),'?', CONCAT(unit,'(a)')); +END; +$$ +DELIMITER ;$$ + + +--echo +--echo +--echo # EXTRACT(YEAR FROM expr) and YEAR(expr) are equivalent + +CALL p1('YEAR'); +let extr=EXTRACT(YEAR FROM $ts); +let func=YEAR($ts); +let extr01=`SELECT params("$extr", $pcount01) AS p`; +let func01=`SELECT params("$func", $pcount01) AS p`; +let extr02=`SELECT params("$extr", $pcount02) AS p`; +let func02=`SELECT params("$func", $pcount02) AS p`; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS $select01' USING $extr01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS $select01' USING $func01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS $select02' USING $extr02; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS $select02' USING $func02; +CALL show_drop; + + +--echo +--echo +--echo # EXTRACT(QUARTER FROM expr) and QUARTER(expr) are equavalent + +CALL p1('QUARTER'); +let extr=EXTRACT(QUARTER FROM $ts); +let func=QUARTER($ts); +let extr01=`SELECT params("$extr", $pcount01) AS p`; +let func01=`SELECT params("$func", $pcount01) AS p`; +let extr02=`SELECT params("$extr", $pcount02) AS p`; +let func02=`SELECT params("$func", $pcount02) AS p`; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS $select01' USING $extr01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS $select01' USING $func01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS $select02' USING $extr02; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS $select02' USING $func02; +CALL show_drop; + +--echo +--echo +--echo # EXTRACT(MONTH FROM expr) and MONTH(expr) are equavalent + +CALL p1('MONTH'); +let extr=EXTRACT(MONTH FROM $ts); +let func=MONTH($ts); +let extr01=`SELECT params("$extr", $pcount01) AS p`; +let func01=`SELECT params("$func", $pcount01) AS p`; +let extr02=`SELECT params("$extr", $pcount02) AS p`; +let func02=`SELECT params("$func", $pcount02) AS p`; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS $select01' USING $extr01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS $select01' USING $func01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS $select02' USING $extr02; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS $select02' USING $func02; +CALL show_drop; + +--echo +--echo +--echo # EXTRACT(WEEK FROM expr) and WEEK(expr) are equavalent + +CALL p1('WEEK'); +let extr=EXTRACT(WEEK FROM $ts); +let func=WEEK($ts); +let extr01=`SELECT params("$extr", $pcount01) AS p`; +let func01=`SELECT params("$func", $pcount01) AS p`; +let extr02=`SELECT params("$extr", $pcount02) AS p`; +let func02=`SELECT params("$func", $pcount02) AS p`; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS $select01' USING $extr01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS $select01' USING $func01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS $select02' USING $extr02; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS $select02' USING $func02; +CALL show_drop; + +--echo +--echo +--echo # EXTRACT(DAY FROM expr) returns hours/24 and includes the sign for TIME +--echo # DAY(expr) returns the DD part of CAST(expr AS DATETIME) + +CALL p1('DAY'); +let extr=EXTRACT(DAY FROM $ts); +let func=DAY($ts); +let extr01=`SELECT params("$extr", $pcount01) AS p`; +let func01=`SELECT params("$func", $pcount01) AS p`; +let extr02=`SELECT params("$extr", $pcount02) AS p`; +let func02=`SELECT params("$func", $pcount02) AS p`; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS $select01' USING $extr01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS $select01' USING $func01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS $select02' USING $extr02; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS $select02' USING $func02; +CALL show_drop; + +--echo +--echo +--echo # EXTRACT(HOUR FROM expr) returns hours%24 and includes the sign for TIME +--echo # HOUR(expr) returns the hh part of CAST(expr AS DATETIME) + +CALL p1('HOUR'); +let extr=EXTRACT(HOUR FROM $ts); +let func=HOUR($ts); +let extr01=`SELECT params("$extr", $pcount01) AS p`; +let func01=`SELECT params("$func", $pcount01) AS p`; +let extr02=`SELECT params("$extr", $pcount02) AS p`; +let func02=`SELECT params("$func", $pcount02) AS p`; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS $select01' USING $extr01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS $select01' USING $func01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS $select02' USING $extr02; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS $select02' USING $func02; +CALL show_drop; + +--echo +--echo +--echo # EXTRACT(MINUTE FROM expr) includes the sign for TIME +--echo # MINUTE(expr) returns the absolute value + +CALL p1('MINUTE'); +let extr=EXTRACT(MINUTE FROM $ts); +let func=MINUTE($ts); +let extr01=`SELECT params("$extr", $pcount01) AS p`; +let func01=`SELECT params("$func", $pcount01) AS p`; +let extr02=`SELECT params("$extr", $pcount02) AS p`; +let func02=`SELECT params("$func", $pcount02) AS p`; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS $select01' USING $extr01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS $select01' USING $func01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS $select02' USING $extr02; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS $select02' USING $func02; +CALL show_drop; + +--echo +--echo +--echo # EXTRACT(SECONDS FROM expr) includes the sign for TIME +--echo # SECONDS(expr) returns the absolute value + +CALL p1('SECOND'); +let extr=EXTRACT(SECOND FROM $ts); +let func=SECOND($ts); +let extr01=`SELECT params("$extr", $pcount01) AS p`; +let func01=`SELECT params("$func", $pcount01) AS p`; +let extr02=`SELECT params("$extr", $pcount02) AS p`; +let func02=`SELECT params("$func", $pcount02) AS p`; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS $select01' USING $extr01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS $select01' USING $func01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS $select02' USING $extr02; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS $select02' USING $func02; +CALL show_drop; + +--echo +--echo +--echo # EXTRACT(MICROSECONDS FROM expr) includes the sign for TIME +--echo # MICROSECONDS(expr) returns the absolute value + +CALL p1('MICROSECOND'); +let extr=EXTRACT(MICROSECOND FROM $ts); +let func=MICROSECOND($ts); +let extr01=`SELECT params("$extr", $pcount01) AS p`; +let func01=`SELECT params("$func", $pcount01) AS p`; +let extr02=`SELECT params("$extr", $pcount02) AS p`; +let func02=`SELECT params("$func", $pcount02) AS p`; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1e_ps AS $select01' USING $extr01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS $select01' USING $func01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2e_ps AS $select02' USING $extr02; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS $select02' USING $func02; +CALL show_drop; + +--echo +--echo +--echo # DAYOFYEAR + +CALL p1('DAYOFYEAR'); +let func=DAYOFYEAR($ts); +let func01=`SELECT params("$func", $pcount01) AS p`; +let func02=`SELECT params("$func", $pcount02) AS p`; +eval EXECUTE IMMEDIATE 'CREATE TABLE t1f_ps AS $select01' USING $func01; +eval EXECUTE IMMEDIATE 'CREATE TABLE t2f_ps AS $select02' USING $func02; +CALL show_drop; + + +DROP TABLE t1; +DROP PROCEDURE p1; +DROP PROCEDURE show_drop; +DROP FUNCTION params; + +DROP FUNCTION select01; +DROP FUNCTION select02; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/mysql-test/main/func_time.result b/mysql-test/main/func_time.result index e7ff2001711..0f807a691b3 100644 --- a/mysql-test/main/func_time.result +++ b/mysql-test/main/func_time.result @@ -3142,7 +3142,7 @@ Catalog Database Table Table_alias Column Column_alias Type Length Max length Is def test t1 t1 a a 12 26 26 Y 128 6 63 def EXTRACT(YEAR FROM a) 3 4 4 Y 32896 0 63 def EXTRACT(YEAR_MONTH FROM a) 3 6 6 Y 32896 0 63 -def EXTRACT(QUARTER FROM a) 3 2 1 Y 32896 0 63 +def EXTRACT(QUARTER FROM a) 3 1 1 Y 32896 0 63 def EXTRACT(MONTH FROM a) 3 2 2 Y 32896 0 63 def EXTRACT(WEEK FROM a) 3 2 2 Y 32896 0 63 def EXTRACT(DAY FROM a) 3 3 2 Y 32896 0 63 @@ -3230,11 +3230,11 @@ SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `a` datetime(6) DEFAULT NULL, - `EXTRACT(YEAR FROM a)` int(4) DEFAULT NULL, - `EXTRACT(YEAR_MONTH FROM a)` int(6) DEFAULT NULL, + `EXTRACT(YEAR FROM a)` int(5) DEFAULT NULL, + `EXTRACT(YEAR_MONTH FROM a)` int(7) DEFAULT NULL, `EXTRACT(QUARTER FROM a)` int(2) DEFAULT NULL, - `EXTRACT(MONTH FROM a)` int(2) DEFAULT NULL, - `EXTRACT(WEEK FROM a)` int(2) DEFAULT NULL, + `EXTRACT(MONTH FROM a)` int(3) DEFAULT NULL, + `EXTRACT(WEEK FROM a)` int(3) DEFAULT NULL, `EXTRACT(DAY FROM a)` int(3) DEFAULT NULL, `EXTRACT(DAY_HOUR FROM a)` int(5) DEFAULT NULL, `EXTRACT(DAY_MINUTE FROM a)` int(7) DEFAULT NULL, @@ -3281,7 +3281,7 @@ Catalog Database Table Table_alias Column Column_alias Type Length Max length Is def test t1 t1 a a 11 17 17 Y 128 6 63 def EXTRACT(YEAR FROM a) 3 4 1 Y 32896 0 63 def EXTRACT(YEAR_MONTH FROM a) 3 6 1 Y 32896 0 63 -def EXTRACT(QUARTER FROM a) 3 2 1 Y 32896 0 63 +def EXTRACT(QUARTER FROM a) 3 1 1 Y 32896 0 63 def EXTRACT(MONTH FROM a) 3 2 1 Y 32896 0 63 def EXTRACT(WEEK FROM a) 3 2 9 Y 32896 0 63 def EXTRACT(DAY FROM a) 3 3 3 Y 32896 0 63 @@ -3411,11 +3411,11 @@ SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `a` time(6) DEFAULT NULL, - `EXTRACT(YEAR FROM a)` int(4) DEFAULT NULL, - `EXTRACT(YEAR_MONTH FROM a)` int(6) DEFAULT NULL, + `EXTRACT(YEAR FROM a)` int(5) DEFAULT NULL, + `EXTRACT(YEAR_MONTH FROM a)` int(7) DEFAULT NULL, `EXTRACT(QUARTER FROM a)` int(2) DEFAULT NULL, - `EXTRACT(MONTH FROM a)` int(2) DEFAULT NULL, - `EXTRACT(WEEK FROM a)` int(2) DEFAULT NULL, + `EXTRACT(MONTH FROM a)` int(3) DEFAULT NULL, + `EXTRACT(WEEK FROM a)` int(3) DEFAULT NULL, `EXTRACT(DAY FROM a)` int(3) DEFAULT NULL, `EXTRACT(DAY_HOUR FROM a)` int(5) DEFAULT NULL, `EXTRACT(DAY_MINUTE FROM a)` int(7) DEFAULT NULL, diff --git a/mysql-test/main/ps_2myisam.result b/mysql-test/main/ps_2myisam.result index 256665ce4cb..ec365498833 100644 --- a/mysql-test/main/ps_2myisam.result +++ b/mysql-test/main/ps_2myisam.result @@ -1798,7 +1798,7 @@ t5 CREATE TABLE `t5` ( `param09` longtext DEFAULT NULL, `const10` bigint(17) DEFAULT NULL, `param10` bigint(20) DEFAULT NULL, - `const11` int(4) DEFAULT NULL, + `const11` int(5) DEFAULT NULL, `param11` bigint(20) DEFAULT NULL, `const12` binary(0) DEFAULT NULL, `param12` bigint(20) DEFAULT NULL, @@ -1828,7 +1828,7 @@ def test t5 t5 const09 const09 12 19 19 Y 128 0 63 def test t5 t5 param09 param09 252 4294967295 19 Y 16 0 8 def test t5 t5 const10 const10 8 17 9 Y 32768 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 -def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 +def test t5 t5 const11 const11 3 5 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 diff --git a/mysql-test/main/ps_3innodb.result b/mysql-test/main/ps_3innodb.result index 675587e020a..1c98a59cff5 100644 --- a/mysql-test/main/ps_3innodb.result +++ b/mysql-test/main/ps_3innodb.result @@ -1781,7 +1781,7 @@ t5 CREATE TABLE `t5` ( `param09` longtext DEFAULT NULL, `const10` bigint(17) DEFAULT NULL, `param10` bigint(20) DEFAULT NULL, - `const11` int(4) DEFAULT NULL, + `const11` int(5) DEFAULT NULL, `param11` bigint(20) DEFAULT NULL, `const12` binary(0) DEFAULT NULL, `param12` bigint(20) DEFAULT NULL, @@ -1811,7 +1811,7 @@ def test t5 t5 const09 const09 12 19 19 Y 128 0 63 def test t5 t5 param09 param09 252 4294967295 19 Y 16 0 8 def test t5 t5 const10 const10 8 17 9 Y 32768 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 -def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 +def test t5 t5 const11 const11 3 5 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 diff --git a/mysql-test/main/ps_4heap.result b/mysql-test/main/ps_4heap.result index dcde7613bfe..db182536e93 100644 --- a/mysql-test/main/ps_4heap.result +++ b/mysql-test/main/ps_4heap.result @@ -1782,7 +1782,7 @@ t5 CREATE TABLE `t5` ( `param09` longtext DEFAULT NULL, `const10` bigint(17) DEFAULT NULL, `param10` bigint(20) DEFAULT NULL, - `const11` int(4) DEFAULT NULL, + `const11` int(5) DEFAULT NULL, `param11` bigint(20) DEFAULT NULL, `const12` binary(0) DEFAULT NULL, `param12` bigint(20) DEFAULT NULL, @@ -1812,7 +1812,7 @@ def test t5 t5 const09 const09 12 19 19 Y 128 0 63 def test t5 t5 param09 param09 252 4294967295 19 Y 16 0 8 def test t5 t5 const10 const10 8 17 9 Y 32768 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 -def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 +def test t5 t5 const11 const11 3 5 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 diff --git a/mysql-test/main/ps_5merge.result b/mysql-test/main/ps_5merge.result index c9d33dbb1ae..963a3a60359 100644 --- a/mysql-test/main/ps_5merge.result +++ b/mysql-test/main/ps_5merge.result @@ -1719,7 +1719,7 @@ t5 CREATE TABLE `t5` ( `param09` longtext DEFAULT NULL, `const10` bigint(17) DEFAULT NULL, `param10` bigint(20) DEFAULT NULL, - `const11` int(4) DEFAULT NULL, + `const11` int(5) DEFAULT NULL, `param11` bigint(20) DEFAULT NULL, `const12` binary(0) DEFAULT NULL, `param12` bigint(20) DEFAULT NULL, @@ -1749,7 +1749,7 @@ def test t5 t5 const09 const09 12 19 19 Y 128 0 63 def test t5 t5 param09 param09 252 4294967295 19 Y 16 0 8 def test t5 t5 const10 const10 8 17 9 Y 32768 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 -def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 +def test t5 t5 const11 const11 3 5 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 @@ -5087,7 +5087,7 @@ t5 CREATE TABLE `t5` ( `param09` longtext DEFAULT NULL, `const10` bigint(17) DEFAULT NULL, `param10` bigint(20) DEFAULT NULL, - `const11` int(4) DEFAULT NULL, + `const11` int(5) DEFAULT NULL, `param11` bigint(20) DEFAULT NULL, `const12` binary(0) DEFAULT NULL, `param12` bigint(20) DEFAULT NULL, @@ -5117,7 +5117,7 @@ def test t5 t5 const09 const09 12 19 19 Y 128 0 63 def test t5 t5 param09 param09 252 4294967295 19 Y 16 0 8 def test t5 t5 const10 const10 8 17 9 Y 32768 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 -def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 +def test t5 t5 const11 const11 3 5 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 diff --git a/mysql-test/suite/maria/ps_maria.result b/mysql-test/suite/maria/ps_maria.result index 5c128a32dd1..3f806c43dbd 100644 --- a/mysql-test/suite/maria/ps_maria.result +++ b/mysql-test/suite/maria/ps_maria.result @@ -1798,7 +1798,7 @@ t5 CREATE TABLE `t5` ( `param09` longtext DEFAULT NULL, `const10` bigint(17) DEFAULT NULL, `param10` bigint(20) DEFAULT NULL, - `const11` int(4) DEFAULT NULL, + `const11` int(5) DEFAULT NULL, `param11` bigint(20) DEFAULT NULL, `const12` binary(0) DEFAULT NULL, `param12` bigint(20) DEFAULT NULL, @@ -1828,7 +1828,7 @@ def test t5 t5 const09 const09 12 19 19 Y 128 0 63 def test t5 t5 param09 param09 252 4294967295 19 Y 16 0 8 def test t5 t5 const10 const10 8 17 9 Y 32768 0 63 def test t5 t5 param10 param10 8 20 9 Y 32768 0 63 -def test t5 t5 const11 const11 3 4 4 Y 32768 0 63 +def test t5 t5 const11 const11 3 5 4 Y 32768 0 63 def test t5 t5 param11 param11 8 20 4 Y 32768 0 63 def test t5 t5 const12 const12 254 0 0 Y 128 0 63 def test t5 t5 param12 param12 8 20 0 Y 32768 0 63 diff --git a/sql/item_func.cc b/sql/item_func.cc index b3f12cec3af..f6fa613cba6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1918,6 +1918,18 @@ void Item_func_abs::fix_length_and_dec_int() set_handler(type_handler_long_or_longlong()); } +void Item_func_abs::fix_length_and_dec_sint_ge0() +{ + /* + We're converting slong_ge0 to slong/slonglong. + Add one character for the sign into max_length. + */ + max_length= args[0]->decimal_precision() + 1/*sign*/; + DBUG_ASSERT(!args[0]->unsigned_flag); + unsigned_flag= false; + set_handler(type_handler_long_or_longlong()); +} + void Item_func_abs::fix_length_and_dec_double() { @@ -2594,6 +2606,22 @@ void Item_func_round::fix_arg_int(const Type_handler *preferred, } +void Item_func_round::fix_arg_slong_ge0() +{ + DBUG_ASSERT(!args[0]->unsigned_flag); + DBUG_ASSERT(args[0]->decimals == 0); + Type_std_attributes::set(args[0]); + /* + We're converting the data type from slong_ge0 to slong/slonglong. + Add one character for the sign, + to change max_length notation from "max_length digits" to + "max_length-1 digits and the sign". + */ + max_length+= 1/*sign*/ + test_if_length_can_increase(); + set_handler(type_handler_long_or_longlong()); +} + + void Item_func_round::fix_arg_hex_hybrid() { DBUG_ASSERT(args[0]->decimals == 0); @@ -4801,7 +4829,9 @@ Item_func_set_user_var::fix_length_and_dec() if (args[0]->collation.derivation == DERIVATION_NUMERIC) { collation.set(DERIVATION_NUMERIC); - fix_length_and_charset(args[0]->max_char_length(), &my_charset_numeric); + uint sign_length= args[0]->type_handler() == &type_handler_slong_ge0 ? 1: 0; + fix_length_and_charset(args[0]->max_char_length() + sign_length, + &my_charset_numeric); } else { diff --git a/sql/item_func.h b/sql/item_func.h index b205d457f1d..0f4f8928847 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1239,6 +1239,24 @@ public: }; +class Item_long_ge0_func: public Item_int_func +{ +public: + Item_long_ge0_func(THD *thd): Item_int_func(thd) { } + Item_long_ge0_func(THD *thd, Item *a): Item_int_func(thd, a) {} + Item_long_ge0_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {} + Item_long_ge0_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {} + Item_long_ge0_func(THD *thd, List &list): Item_int_func(thd, list) { } + Item_long_ge0_func(THD *thd, Item_long_ge0_func *item) :Item_int_func(thd, item) {} + const Type_handler *type_handler() const + { + DBUG_ASSERT(!unsigned_flag); + return &type_handler_slong_ge0; + } + bool fix_length_and_dec() { max_length= 10; return FALSE; } +}; + + class Item_func_hash: public Item_int_func { public: @@ -1362,6 +1380,13 @@ public: { fix_char_length(MAX_BIGINT_WIDTH); } + void fix_length_and_dec_sint_ge0() + { + uint32 digits= args[0]->decimal_precision(); + DBUG_ASSERT(digits > 0); + DBUG_ASSERT(digits <= MY_INT64_NUM_DECIMAL_DIGITS); + fix_char_length(digits + (unsigned_flag ? 0 : 1/*sign*/)); + } void fix_length_and_dec_generic() { uint32 char_length= MY_MIN(args[0]->max_char_length(), @@ -1723,6 +1748,7 @@ public: my_decimal *decimal_op(my_decimal *); const char *func_name() const { return "abs"; } void fix_length_and_dec_int(); + void fix_length_and_dec_sint_ge0(); void fix_length_and_dec_double(); void fix_length_and_dec_decimal(); bool fix_length_and_dec(); @@ -1981,6 +2007,7 @@ public: void fix_arg_int(const Type_handler *preferred, const Type_std_attributes *preferred_attributes, bool use_decimal_on_length_increase); + void fix_arg_slong_ge0(); void fix_arg_hex_hybrid(); void fix_arg_double(); void fix_arg_time(); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index c3ff95ccf33..99e1d622bf8 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1205,6 +1205,21 @@ bool Item_sum_hybrid::fix_length_and_dec_numeric(const Type_handler *handler) } +bool Item_sum_hybrid::fix_length_and_dec_sint_ge0() +{ + // We don't have Item_field's of "ge0" type handlers. + DBUG_ASSERT(args[0]->real_item()->type() != FIELD_ITEM); + Type_std_attributes::set(args[0]); + /* + We're converting from e.g. slong_ge0 to slonglong + and need to add one extra character for the sign. + */ + max_length++; + set_handler(&type_handler_slonglong); + return false; +} + + /** MAX(str_field) converts ENUM/SET to CHAR, and preserve all other types for Fields. diff --git a/sql/item_sum.h b/sql/item_sum.h index 9f858725598..847407c6c0c 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1115,6 +1115,7 @@ public: { return Type_handler_hybrid_field_type::type_handler(); } bool fix_length_and_dec_generic(); bool fix_length_and_dec_numeric(const Type_handler *h); + bool fix_length_and_dec_sint_ge0(); bool fix_length_and_dec_string(); }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 1672eee3443..a58f3593463 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2142,7 +2142,7 @@ bool Item_extract::fix_length_and_dec() switch (int_type) { case INTERVAL_YEAR: set_date_length(4); break; // YYYY case INTERVAL_YEAR_MONTH: set_date_length(6); break; // YYYYMM - case INTERVAL_QUARTER: set_date_length(2); break; // 1..4 + case INTERVAL_QUARTER: set_date_length(1); break; // 1..4 case INTERVAL_MONTH: set_date_length(2); break; // MM case INTERVAL_WEEK: set_date_length(2); break; // 0..52 case INTERVAL_DAY: set_day_length(daylen); break; // DD diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index a910b2cb723..d8012c74e05 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -30,23 +30,23 @@ bool get_interval_value(THD *thd, Item *args, interval_type int_type, INTERVAL *interval); -class Item_long_func_date_field: public Item_long_func +class Item_long_func_date_field: public Item_long_ge0_func { bool check_arguments() const { return args[0]->check_type_can_return_date(func_name()); } public: Item_long_func_date_field(THD *thd, Item *a) - :Item_long_func(thd, a) { } + :Item_long_ge0_func(thd, a) { } }; -class Item_long_func_time_field: public Item_long_func +class Item_long_func_time_field: public Item_long_ge0_func { bool check_arguments() const { return args[0]->check_type_can_return_time(func_name()); } public: Item_long_func_time_field(THD *thd, Item *a) - :Item_long_func(thd, a) { } + :Item_long_ge0_func(thd, a) { } }; @@ -166,10 +166,10 @@ public: }; -class Item_func_month :public Item_long_func +class Item_func_month :public Item_long_ge0_func { public: - Item_func_month(THD *thd, Item *a): Item_long_func(thd, a) + Item_func_month(THD *thd, Item *a): Item_long_ge0_func(thd, a) { } longlong val_int(); const char *func_name() const { return "month"; } @@ -333,7 +333,7 @@ public: }; -class Item_func_week :public Item_long_func +class Item_func_week :public Item_long_ge0_func { bool check_arguments() const { @@ -341,8 +341,8 @@ class Item_func_week :public Item_long_func (arg_count > 1 && args[1]->check_type_can_return_int(func_name())); } public: - Item_func_week(THD *thd, Item *a): Item_long_func(thd, a) {} - Item_func_week(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {} + Item_func_week(THD *thd, Item *a): Item_long_ge0_func(thd, a) {} + Item_func_week(THD *thd, Item *a, Item *b): Item_long_ge0_func(thd, a, b) {} longlong val_int(); const char *func_name() const { return "week"; } bool fix_length_and_dec() @@ -969,12 +969,17 @@ class Item_extract :public Item_int_func, void set_date_length(uint32 length) { /* - Although DATE components (e.g. YEAR, YEAR_MONTH, QUARTER, MONTH, WEEK) - cannot have a sign, we should probably still add +1, - because all around the code we assume that max_length is sign inclusive. - Another options is to set unsigned_flag to "true". + DATE components (e.g. YEAR, YEAR_MONTH, QUARTER, MONTH, WEEK) + return non-negative values but historically EXTRACT for date + components always returned the signed int data type. + So do equivalent functions YEAR(), QUARTER(), MONTH(), WEEK(). + Let's set the data type to "signed int, but not negative", + so "this" produces better data types in VARCHAR and DECIMAL context + by using the fact that all of the max_length characters are spent + for digits (non of them are spent for the sign). */ - set_handler(handler_by_length(max_length= length, 10)); // QQ: see above + set_handler(&type_handler_slong_ge0); + fix_char_length(length); m_date_mode= date_mode_t(0); } void set_day_length(uint32 length) diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 77931b6cf16..9ede9e2582d 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -41,6 +41,7 @@ Named_type_handler type_handler_bool("boolean"); Named_type_handler type_handler_stiny("tinyint"); Named_type_handler type_handler_sshort("smallint"); Named_type_handler type_handler_slong("int"); +Named_type_handler type_handler_slong_ge0("int"); Named_type_handler type_handler_sint24("mediumint"); Named_type_handler type_handler_slonglong("bigint"); Named_type_handler type_handler_utiny("tiny unsigned"); @@ -4629,6 +4630,10 @@ bool Type_handler_general_purpose_int:: bool unsigned_flag= items[0]->unsigned_flag; for (uint i= 1; i < nitems; i++) { + /* + TODO: avoid creating DECIMAL for a mix of ulong and slong_ge0. + It's too late for 10.5. Let's do it in a higher version. + */ if (unsigned_flag != items[i]->unsigned_flag) { // Convert a mixture of signed and unsigned int to decimal @@ -4638,6 +4643,21 @@ bool Type_handler_general_purpose_int:: } } func->aggregate_attributes_int(items, nitems); + for (uint i= 0; i < nitems; i++) + { + if (items[i]->type_handler() == &type_handler_slong_ge0) + { + /* + A slong_ge0 argument found. + We need to add an extra character for the sign. + TODO: rewrite aggregate_attributes_int() to find + the maximum decimal_precision() instead of the maximum max_length. + This change is too late for 10.5, so let's do it in a higher version. + */ + uint digits_and_sign= items[i]->decimal_precision() + 1; + set_if_bigger(func->max_length, digits_and_sign); + } + } handler->set_handler(func->unsigned_flag ? handler->type_handler()->type_handler_unsigned() : handler->type_handler()->type_handler_signed()); @@ -4931,6 +4951,13 @@ bool Type_handler_real_result:: /*************************************************************************/ +bool Type_handler_long_ge0:: + Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const +{ + return func->fix_length_and_dec_sint_ge0(); +} + + bool Type_handler_int_result:: Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const { @@ -6373,6 +6400,14 @@ bool Type_handler_int_result:: } +bool Type_handler_long_ge0:: + Item_func_round_fix_length_and_dec(Item_func_round *item) const +{ + item->fix_arg_slong_ge0(); + return false; +} + + bool Type_handler_year:: Item_func_round_fix_length_and_dec(Item_func_round *item) const { @@ -6594,6 +6629,14 @@ bool Type_handler_int_result:: } +bool Type_handler_long_ge0:: + Item_func_abs_fix_length_and_dec(Item_func_abs *item) const +{ + item->fix_length_and_dec_sint_ge0(); + return false; +} + + bool Type_handler_real_result:: Item_func_abs_fix_length_and_dec(Item_func_abs *item) const { @@ -6704,6 +6747,22 @@ bool Type_handler:: } +bool Type_handler_long_ge0:: + Item_func_signed_fix_length_and_dec(Item_func_signed *item) const +{ + item->fix_length_and_dec_sint_ge0(); + return false; +} + + +bool Type_handler_long_ge0:: + Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) const +{ + item->fix_length_and_dec_sint_ge0(); + return false; +} + + bool Type_handler_string_result:: Item_func_signed_fix_length_and_dec(Item_func_signed *item) const { @@ -7189,6 +7248,18 @@ uint Type_handler_int_result::Item_decimal_precision(const Item *item) const return MY_MIN(prec, DECIMAL_MAX_PRECISION); } +uint Type_handler_long_ge0::Item_decimal_precision(const Item *item) const +{ + DBUG_ASSERT(item->max_length); + DBUG_ASSERT(!item->decimals); + /* + Unlinke in Type_handler_long, Type_handler_long_ge does + not reserve one character for the sign. All max_length + characters are digits. + */ + return MY_MIN(item->max_length, DECIMAL_MAX_PRECISION); +} + uint Type_handler_time_common::Item_decimal_precision(const Item *item) const { return 7 + MY_MIN(item->decimals, TIME_SECOND_PART_DIGITS); @@ -8190,6 +8261,26 @@ Field *Type_handler_long:: } +Field *Type_handler_long_ge0:: + make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &rec, const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const +{ + /* + We're converting signed long_ge0 to signed long. + So add one character for the sign. + */ + return new (mem_root) + Field_long(rec.ptr(), (uint32) attr->length + 1/*sign*/, + rec.null_ptr(), rec.null_bit(), + attr->unireg_check, name, + f_is_zerofill(attr->pack_flag) != 0, + f_is_dec(attr->pack_flag) == 0); +} + + Field *Type_handler_longlong:: make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root, const LEX_CSTRING *name, diff --git a/sql/sql_type.h b/sql/sql_type.h index c8c92e56253..62bb8945b5b 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -5758,6 +5758,38 @@ public: }; +/* + The expression of this type reports itself as signed, + however it's known not to return negative values. + Items of this data type count only digits in Item::max_length, + without adding +1 for the sign. This allows expressions + of this type convert nicely to VARCHAR and DECIMAL. + For example, YEAR(now()) is: + - VARCHAR(4) in a string context + - DECIMAL(4,0) in a decimal context + - but INT(5) in an integer context +*/ +class Type_handler_long_ge0: public Type_handler_long +{ +public: + uint Item_decimal_precision(const Item *item) const override; + bool Item_func_signed_fix_length_and_dec(Item_func_signed *item) + const override; + bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *item) + const override; + bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const override; + bool Item_func_round_fix_length_and_dec(Item_func_round *) const override; + bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const override; + Field *make_table_field_from_def(TABLE_SHARE *share, + MEM_ROOT *mem_root, + const LEX_CSTRING *name, + const Record_addr &addr, + const Bit_addr &bit, + const Column_definition_attributes *attr, + uint32 flags) const override; +}; + + class Type_handler_ulong: public Type_handler_long { public: @@ -7598,6 +7630,7 @@ extern MYSQL_PLUGIN_IMPORT Named_type_handler type_han extern MYSQL_PLUGIN_IMPORT Named_type_handler type_handler_sshort; extern MYSQL_PLUGIN_IMPORT Named_type_handler type_handler_sint24; extern MYSQL_PLUGIN_IMPORT Named_type_handler type_handler_slong; +extern MYSQL_PLUGIN_IMPORT Named_type_handler type_handler_slong_ge0; extern MYSQL_PLUGIN_IMPORT Named_type_handler type_handler_slonglong; extern Named_type_handler type_handler_utiny; From 1b37cb71f44549c94acf8914cf93d43a4293a449 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 26 Jan 2024 13:12:03 +0400 Subject: [PATCH 021/106] MDEV-32975 Default charset doesn't work with PHP MySQLi extension When sending the server default collation ID to the client in the handshake packet, translate a 2-byte collation ID to the ID of the default collation for the character set. --- sql/sql_acl.cc | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index c0593b2d19b..634403bfc45 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -12831,8 +12831,27 @@ static bool send_server_handshake_packet(MPVIO_EXT *mpvio, *end++= 0; int2store(end, thd->client_capabilities); + + CHARSET_INFO *handshake_cs= default_charset_info; + if (handshake_cs->number > 0xFF) + { + /* + A workaround for a 2-byte collation ID: translate it into + the ID of the primary collation of this character set. + */ + CHARSET_INFO *cs= get_charset_by_csname(handshake_cs->csname, + MY_CS_PRIMARY, MYF(MY_WME)); + /* + cs should not normally be NULL, however it may be possible + with a dynamic character set incorrectly defined in Index.xml. + For safety let's fallback to latin1 in case cs is NULL. + */ + handshake_cs= cs ? cs : &my_charset_latin1; + } + /* write server characteristics: up to 16 bytes allowed */ - end[2]= (char) default_charset_info->number; + end[2]= (char) handshake_cs->number; + int2store(end+3, mpvio->auth_info.thd->server_status); int2store(end+5, thd->client_capabilities >> 16); end[7]= data_len; From 2c5f3bbe78c45cb2cc6151acd2621956e2351d08 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 26 Feb 2024 18:59:21 +0530 Subject: [PATCH 022/106] MDEV-14193 innodb.log_file_name failed in buildbot with exception Problem: ======= - innodb.log_file_name fails if it executes after innodb.lock_insert_into_empty in few cases. innodb.lock_insert_into_empty test case failed to cleanup the table t2. Rollback of create..select fails to remove the table when it fails to acquire the innodb statistics table. This leads to rename table in log_file_name test case fails. Solution: ======== - Cleanup the table t2 explictly after resetting innodb_lock_wait_timeout variable in innodb.lock_insert_into_empty test case. --- mysql-test/suite/innodb/r/lock_insert_into_empty.result | 5 +++++ mysql-test/suite/innodb/t/lock_insert_into_empty.test | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/innodb/r/lock_insert_into_empty.result b/mysql-test/suite/innodb/r/lock_insert_into_empty.result index c1dea2fc9af..97369b58aef 100644 --- a/mysql-test/suite/innodb/r/lock_insert_into_empty.result +++ b/mysql-test/suite/innodb/r/lock_insert_into_empty.result @@ -47,6 +47,9 @@ CREATE TABLE t1 (k INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 SET k=1; START TRANSACTION; INSERT INTO t1 SET k=2; +SELECT count(*) > 0 FROM mysql.innodb_index_stats lock in share mode; +count(*) > 0 +1 connect con1,localhost,root,,test; SET innodb_lock_wait_timeout=0; CREATE TABLE t2 (pk INT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB @@ -54,4 +57,6 @@ AS SELECT k FROM t1; ERROR HY000: Lock wait timeout exceeded; try restarting transaction disconnect con1; connection default; +SET innodb_lock_wait_timeout=default; DROP TABLE t1; +DROP TABLE IF EXISTS t2; diff --git a/mysql-test/suite/innodb/t/lock_insert_into_empty.test b/mysql-test/suite/innodb/t/lock_insert_into_empty.test index 91d2bcdd3ba..42409e8cf35 100644 --- a/mysql-test/suite/innodb/t/lock_insert_into_empty.test +++ b/mysql-test/suite/innodb/t/lock_insert_into_empty.test @@ -51,6 +51,7 @@ CREATE TABLE t1 (k INT PRIMARY KEY) ENGINE=InnoDB; INSERT INTO t1 SET k=1; START TRANSACTION; INSERT INTO t1 SET k=2; +SELECT count(*) > 0 FROM mysql.innodb_index_stats lock in share mode; --connect (con1,localhost,root,,test) SET innodb_lock_wait_timeout=0; @@ -59,5 +60,6 @@ CREATE TABLE t2 (pk INT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB AS SELECT k FROM t1; --disconnect con1 --connection default - +SET innodb_lock_wait_timeout=default; DROP TABLE t1; +DROP TABLE IF EXISTS t2; From 8778a83eee9472fe15da185a188543595f262cda Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 22 Feb 2024 22:58:52 -0800 Subject: [PATCH 023/106] MDEV-31276 Wrong warnings on 2-nd execution of PS for query with GROUP_CONCAT If a query with GROUP_CONCAT is executed then the server reports a warning every time when the length of the result of this function exceeds the set value of the system variable group_concat_max_len. This bug led to the set of warnings from the second execution of the prepared statement that did not coincide with the one from the first execution if the executed query was a grouping query over a join of tables using GROUP_CONCAT function and join cache was not allowed to be employed. The descrepancy of the sets of warnings was due to lack of cleanup for Item_func_group_concat::row_count after execution of the query. Approved by Oleksandr Byelkin --- mysql-test/main/func_gconcat.result | 75 +++++++++++++++++++++++++++ mysql-test/main/func_gconcat.test | 40 ++++++++++++++ mysql-test/main/join_outer.test | 6 --- mysql-test/main/subselect_sj_mat.test | 9 ---- sql/item_sum.cc | 1 + 5 files changed, 116 insertions(+), 15 deletions(-) diff --git a/mysql-test/main/func_gconcat.result b/mysql-test/main/func_gconcat.result index fea25124941..7bc6441661b 100644 --- a/mysql-test/main/func_gconcat.result +++ b/mysql-test/main/func_gconcat.result @@ -1443,3 +1443,78 @@ drop table t1; # # End of 10.3 tests # +# +# MDEV-31276: Execution of PS from grouping query with join +# and GROUP_CONCAT set function +# +create table t1 (a int, b varchar(20)) engine=myisam; +create table t2 (a int, c varchar(20)) engine=myisam; +insert into t1 values (1,"aaaaaaaaaa"),(2,"bbbbbbbbbb"); +insert into t2 values (1,"cccccccccc"),(2,"dddddddddd"); +insert into t2 values (1,"eeeeeee"),(2,"fffffff"); +set group_concat_max_len=5; +select count(*), group_concat(t1.b,t2.c) +from t1 join t2 on t1.a=t2.a group by t1.a; +count(*) group_concat(t1.b,t2.c) +2 aaaaa +2 bbbbb +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +explain select count(*), group_concat(t1.b,t2.c) +from t1 join t2 on t1.a=t2.a group by t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join) +prepare stmt from "select count(*), group_concat(t1.b,t2.c) +from t1 join t2 on t1.a=t2.a group by t1.a"; +execute stmt; +count(*) group_concat(t1.b,t2.c) +2 aaaaa +2 bbbbb +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +execute stmt; +count(*) group_concat(t1.b,t2.c) +2 aaaaa +2 bbbbb +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +deallocate prepare stmt; +set join_cache_level=0; +select count(*), group_concat(t1.b,t2.c) +from t1 join t2 on t1.a=t2.a group by t1.a; +count(*) group_concat(t1.b,t2.c) +2 aaaaa +2 bbbbb +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +explain select count(*), group_concat(t1.b,t2.c) +from t1 join t2 on t1.a=t2.a group by t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using filesort +1 SIMPLE t2 ALL NULL NULL NULL NULL 4 Using where +prepare stmt from "select count(*), group_concat(t1.b,t2.c) +from t1 join t2 on t1.a=t2.a group by t1.a"; +execute stmt; +count(*) group_concat(t1.b,t2.c) +2 aaaaa +2 bbbbb +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +execute stmt; +count(*) group_concat(t1.b,t2.c) +2 aaaaa +2 bbbbb +Warnings: +Warning 1260 Row 1 was cut by GROUP_CONCAT() +Warning 1260 Row 2 was cut by GROUP_CONCAT() +deallocate prepare stmt; +set join_cache_level=default; +set group_concat_max_len=default; +drop table t1,t2; +# End of 10.5 tests diff --git a/mysql-test/main/func_gconcat.test b/mysql-test/main/func_gconcat.test index cc5236a18be..2e09bddbb8b 100644 --- a/mysql-test/main/func_gconcat.test +++ b/mysql-test/main/func_gconcat.test @@ -1066,3 +1066,43 @@ drop table t1; --echo # --echo # End of 10.3 tests --echo # + +--echo # +--echo # MDEV-31276: Execution of PS from grouping query with join +--echo # and GROUP_CONCAT set function +--echo # + +create table t1 (a int, b varchar(20)) engine=myisam; +create table t2 (a int, c varchar(20)) engine=myisam; +insert into t1 values (1,"aaaaaaaaaa"),(2,"bbbbbbbbbb"); +insert into t2 values (1,"cccccccccc"),(2,"dddddddddd"); +insert into t2 values (1,"eeeeeee"),(2,"fffffff"); + +let $q= +select count(*), group_concat(t1.b,t2.c) + from t1 join t2 on t1.a=t2.a group by t1.a; + +set group_concat_max_len=5; + +eval $q; +eval explain $q; +eval prepare stmt from "$q"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +set join_cache_level=0; + +eval $q; +eval explain $q; +eval prepare stmt from "$q"; +execute stmt; +execute stmt; +deallocate prepare stmt; + +set join_cache_level=default; +set group_concat_max_len=default; + +drop table t1,t2; + +--echo # End of 10.5 tests diff --git a/mysql-test/main/join_outer.test b/mysql-test/main/join_outer.test index da3c82109d8..83bb7fdeef3 100644 --- a/mysql-test/main/join_outer.test +++ b/mysql-test/main/join_outer.test @@ -685,15 +685,9 @@ create table t1 (a int, b varchar(20)); create table t2 (a int, c varchar(20)); insert into t1 values (1,"aaaaaaaaaa"),(2,"bbbbbbbbbb"); insert into t2 values (1,"cccccccccc"),(2,"dddddddddd"); -#Enable after fix MDEV-31276 ---disable_ps2_protocol select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by t1.a; ---enable_ps2_protocol select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by t1.a; -#Enable after fix MDEV-31276 ---disable_ps2_protocol select group_concat(t1.b,t2.c) from t1 left join t2 using(a) group by a; ---enable_ps2_protocol select group_concat(t1.b,t2.c) from t1 inner join t2 using(a) group by a; drop table t1, t2; set group_concat_max_len=default; diff --git a/mysql-test/main/subselect_sj_mat.test b/mysql-test/main/subselect_sj_mat.test index 000581d5758..6b343900dca 100644 --- a/mysql-test/main/subselect_sj_mat.test +++ b/mysql-test/main/subselect_sj_mat.test @@ -523,8 +523,6 @@ where a1 in (select substring(b1,1,512) from t2_512 where b1 > '0'); # group_concat with a blob argument - depends on # the variable group_concat_max_len, and # convert_blob_length == max_len*collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB -#Check after fix MDEV-31276 ---disable_ps2_protocol explain extended select left(a1,7), left(a2,7) from t1_512 where a1 in (select group_concat(b1) from t2_512 group by b2); @@ -542,7 +540,6 @@ where a1 in (select group_concat(b1) from t2_512 group by b2); select left(a1,7), left(a2,7) from t1_512 where a1 in (select group_concat(b1) from t2_512 group by b2); ---enable_ps2_protocol drop table t1_512, t2_512, t3_512; @@ -608,8 +605,6 @@ where a1 in (select substring(b1,1,1024) from t2_1024 where b1 > '0'); # group_concat with a blob argument - depends on # the variable group_concat_max_len, and # convert_blob_length == max_len*collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB -#Check after fix MDEV-31276 ---disable_ps2_protocol explain extended select left(a1,7), left(a2,7) from t1_1024 where a1 in (select group_concat(b1) from t2_1024 group by b2); @@ -627,7 +622,6 @@ where a1 in (select group_concat(b1) from t2_1024 group by b2); select left(a1,7), left(a2,7) from t1_1024 where a1 in (select group_concat(b1) from t2_1024 group by b2); ---enable_ps2_protocol drop table t1_1024, t2_1024, t3_1024; @@ -693,8 +687,6 @@ where a1 in (select substring(b1,1,1025) from t2_1025 where b1 > '0'); # group_concat with a blob argument - depends on # the variable group_concat_max_len, and # convert_blob_length == max_len*collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB -#Check after fix MDEV-31276 ---disable_ps2_protocol explain extended select left(a1,7), left(a2,7) from t1_1025 where a1 in (select group_concat(b1) from t2_1025 group by b2); @@ -712,7 +704,6 @@ where a1 in (select group_concat(b1) from t2_1025 group by b2); select left(a1,7), left(a2,7) from t1_1025 where a1 in (select group_concat(b1) from t2_1025 group by b2); ---enable_ps2_protocol drop table t1_1025, t2_1025, t3_1025; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 99e1d622bf8..7f39efe6c9a 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -4056,6 +4056,7 @@ void Item_func_group_concat::cleanup() unique_filter= NULL; } } + row_count= 0; DBUG_ASSERT(tree == 0); } /* From 57cc8605ebc1529d88d73ab3569cc9962ca17fab Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 26 Feb 2024 12:40:14 +0530 Subject: [PATCH 024/106] MDEV-19044 Alter table corrupts while applying the modification log Problem: ======== - InnoDB reads the length of the variable length field wrongly while applying the modification log of instant table. Solution: ======== rec_init_offsets_comp_ordinary(): For the temporary instant file record, InnoDB should read the length of the variable length field from the record itself. --- .../suite/innodb/r/instant_alter_crash.result | 25 +------- .../r/instant_alter_debug,dynamic.rdiff | 9 ++- .../suite/innodb/r/instant_alter_debug.result | 55 +++++++++++++++++- .../suite/innodb/t/instant_alter_crash.test | 28 +-------- .../suite/innodb/t/instant_alter_debug.test | 57 ++++++++++++++++++- storage/innobase/rem/rem0rec.cc | 2 +- 6 files changed, 115 insertions(+), 61 deletions(-) diff --git a/mysql-test/suite/innodb/r/instant_alter_crash.result b/mysql-test/suite/innodb/r/instant_alter_crash.result index c16d5951c07..d46495a3d83 100644 --- a/mysql-test/suite/innodb/r/instant_alter_crash.result +++ b/mysql-test/suite/innodb/r/instant_alter_crash.result @@ -180,28 +180,5 @@ t3 CREATE TABLE `t3` ( UNIQUE KEY `v2` (`v2`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci DROP TABLE t1,t2,t3; -db.opt -# -# MDEV-26198 Assertion `0' failed in row_log_table_apply_op during -# ADD PRIMARY KEY or OPTIMIZE TABLE -# -CREATE TABLE t1(f1 year default null, f2 year default null, -f3 text, f4 year default null, f5 year default null, -f6 year default null, f7 year default null, -f8 year default null)ENGINE=InnoDB ROW_FORMAT=REDUNDANT; -INSERT INTO t1 VALUES(1, 1, 1, 1, 1, 1, 1, 1); -ALTER TABLE t1 ADD COLUMN f9 year default null, ALGORITHM=INPLACE; -set DEBUG_SYNC="row_log_table_apply1_before SIGNAL con1_insert WAIT_FOR con1_finish"; -ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ADD COLUMN f10 YEAR DEFAULT NULL, ALGORITHM=INPLACE; -connect con1,localhost,root,,,; -SET DEBUG_SYNC="now WAIT_FOR con1_insert"; -INSERT IGNORE INTO t1 (f3) VALUES ( 'b' ); -INSERT IGNORE INTO t1 (f3) VALUES ( 'l' ); -SET DEBUG_SYNC="now SIGNAL con1_finish"; -connection default; -disconnect con1; SET DEBUG_SYNC=RESET; -CHECK TABLE t1; -Table Op Msg_type Msg_text -test.t1 check status OK -DROP TABLE t1; +db.opt diff --git a/mysql-test/suite/innodb/r/instant_alter_debug,dynamic.rdiff b/mysql-test/suite/innodb/r/instant_alter_debug,dynamic.rdiff index 379514edad9..6e0e0d752e4 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug,dynamic.rdiff +++ b/mysql-test/suite/innodb/r/instant_alter_debug,dynamic.rdiff @@ -1,6 +1,9 @@ -@@ -470,4 +470,4 @@ +--- mysql-test/suite/innodb/r/instant_alter_debug.result 2024-02-27 12:22:59.612941388 +0530 ++++ mysql-test/suite/innodb/r/instant_alter_debug,dynamic.reject 2024-02-27 12:23:09.924938462 +0530 +@@ -537,5 +537,5 @@ FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants --33 -+32 +-35 ++34 + SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 5b9cee57389..9b83cd91851 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -479,14 +479,63 @@ SET DEBUG_SYNC="now WAIT_FOR try_insert"; INSERT INTO t1 VALUES(1, 2); ERROR HY000: Lock wait timeout exceeded; try restarting transaction SET DEBUG_SYNC="now SIGNAL alter_progress"; -disconnect con1; connection default; DROP TABLE t1; +# +# MDEV-26198 Assertion `0' failed in row_log_table_apply_op during +# ADD PRIMARY KEY or OPTIMIZE TABLE +# +CREATE TABLE t1(f1 year default null, f2 year default null, +f3 text, f4 year default null, f5 year default null, +f6 year default null, f7 year default null, +f8 year default null)ENGINE=InnoDB; +INSERT INTO t1 VALUES(1, 1, 1, 1, 1, 1, 1, 1); +ALTER TABLE t1 ADD COLUMN f9 year default null, ALGORITHM=INPLACE; +set DEBUG_SYNC="row_log_table_apply1_before SIGNAL con1_insert WAIT_FOR con1_finish"; +ALTER TABLE t1 ADD COLUMN f10 YEAR DEFAULT NULL, FORCE, ALGORITHM=INPLACE; +connection con1; +SET DEBUG_SYNC="now WAIT_FOR con1_insert"; +INSERT IGNORE INTO t1 (f3) VALUES ( 'b' ); +INSERT IGNORE INTO t1 (f3) VALUES ( 'l' ); +SET DEBUG_SYNC="now SIGNAL con1_finish"; +connection default; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +# +# MDEV-19044 Alter table corrupts while applying the +# modification log +# +CREATE TABLE t1 ( +f1 INT, +f2 INT, +f3 char(19) CHARACTER SET utf8mb3, +f4 VARCHAR(500), +f5 TEXT)ENGINE=InnoDB; +INSERT INTO t1 VALUES(3, 1, REPEAT('a', 2), REPEAT("b", 20),'a'); +ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL, ALGORITHM=INSTANT; +INSERT INTO t1 VALUES(1, 2, REPEAT('InnoDB', 2), +REPEAT("MariaDB", 20), REPEAT('a', 8000), 12); +INSERT INTO t1 VALUES(1, 2, REPEAT('MYSQL', 2), +REPEAT("MariaDB", 20), REPEAT('a', 8000), 12); +SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL con1_begin WAIT_FOR con1_update'; +ALTER TABLE t1 MODIFY COLUMN f2 INT NOT NULL, FORCE, ALGORITHM=INPLACE; +connection con1; +SET DEBUG_SYNC='now WAIT_FOR con1_begin'; +UPDATE t1 SET f2=204 order by f1 limit 2; +SET DEBUG_SYNC='now SIGNAL con1_update'; +connection default; +disconnect con1; SET DEBUG_SYNC=reset; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; # End of 10.4 tests -SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; SELECT variable_value-@old_instant instants FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; instants -33 +35 +SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/mysql-test/suite/innodb/t/instant_alter_crash.test b/mysql-test/suite/innodb/t/instant_alter_crash.test index 292de8a802b..6d4403d5807 100644 --- a/mysql-test/suite/innodb/t/instant_alter_crash.test +++ b/mysql-test/suite/innodb/t/instant_alter_crash.test @@ -202,32 +202,6 @@ SHOW CREATE TABLE t1; SHOW CREATE TABLE t2; SHOW CREATE TABLE t3; DROP TABLE t1,t2,t3; - +SET DEBUG_SYNC=RESET; --remove_files_wildcard $MYSQLD_DATADIR/test #sql*.frm --list_files $MYSQLD_DATADIR/test - ---echo # ---echo # MDEV-26198 Assertion `0' failed in row_log_table_apply_op during ---echo # ADD PRIMARY KEY or OPTIMIZE TABLE ---echo # -CREATE TABLE t1(f1 year default null, f2 year default null, - f3 text, f4 year default null, f5 year default null, - f6 year default null, f7 year default null, - f8 year default null)ENGINE=InnoDB ROW_FORMAT=REDUNDANT; -INSERT INTO t1 VALUES(1, 1, 1, 1, 1, 1, 1, 1); -ALTER TABLE t1 ADD COLUMN f9 year default null, ALGORITHM=INPLACE; -set DEBUG_SYNC="row_log_table_apply1_before SIGNAL con1_insert WAIT_FOR con1_finish"; -send ALTER TABLE t1 ROW_FORMAT=REDUNDANT, ADD COLUMN f10 YEAR DEFAULT NULL, ALGORITHM=INPLACE; - -connect(con1,localhost,root,,,); -SET DEBUG_SYNC="now WAIT_FOR con1_insert"; -INSERT IGNORE INTO t1 (f3) VALUES ( 'b' ); -INSERT IGNORE INTO t1 (f3) VALUES ( 'l' ); -SET DEBUG_SYNC="now SIGNAL con1_finish"; - -connection default; -reap; -disconnect con1; -SET DEBUG_SYNC=RESET; -CHECK TABLE t1; -DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index e31b378ff10..3c47cdb3248 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -549,16 +549,67 @@ SET DEBUG_SYNC="now WAIT_FOR try_insert"; --error ER_LOCK_WAIT_TIMEOUT INSERT INTO t1 VALUES(1, 2); SET DEBUG_SYNC="now SIGNAL alter_progress"; -disconnect con1; connection default; reap; DROP TABLE t1; + +--echo # +--echo # MDEV-26198 Assertion `0' failed in row_log_table_apply_op during +--echo # ADD PRIMARY KEY or OPTIMIZE TABLE +--echo # +CREATE TABLE t1(f1 year default null, f2 year default null, + f3 text, f4 year default null, f5 year default null, + f6 year default null, f7 year default null, + f8 year default null)ENGINE=InnoDB; +INSERT INTO t1 VALUES(1, 1, 1, 1, 1, 1, 1, 1); +ALTER TABLE t1 ADD COLUMN f9 year default null, ALGORITHM=INPLACE; +set DEBUG_SYNC="row_log_table_apply1_before SIGNAL con1_insert WAIT_FOR con1_finish"; +send ALTER TABLE t1 ADD COLUMN f10 YEAR DEFAULT NULL, FORCE, ALGORITHM=INPLACE; + +connection con1; +SET DEBUG_SYNC="now WAIT_FOR con1_insert"; +INSERT IGNORE INTO t1 (f3) VALUES ( 'b' ); +INSERT IGNORE INTO t1 (f3) VALUES ( 'l' ); +SET DEBUG_SYNC="now SIGNAL con1_finish"; + +connection default; +reap; +CHECK TABLE t1; +DROP TABLE t1; + +--echo # +--echo # MDEV-19044 Alter table corrupts while applying the +--echo # modification log +--echo # +CREATE TABLE t1 ( + f1 INT, + f2 INT, + f3 char(19) CHARACTER SET utf8mb3, + f4 VARCHAR(500), + f5 TEXT)ENGINE=InnoDB; +INSERT INTO t1 VALUES(3, 1, REPEAT('a', 2), REPEAT("b", 20),'a'); +ALTER TABLE t1 ADD COLUMN f6 INT NOT NULL, ALGORITHM=INSTANT; +INSERT INTO t1 VALUES(1, 2, REPEAT('InnoDB', 2), + REPEAT("MariaDB", 20), REPEAT('a', 8000), 12); +INSERT INTO t1 VALUES(1, 2, REPEAT('MYSQL', 2), + REPEAT("MariaDB", 20), REPEAT('a', 8000), 12); +SET DEBUG_SYNC='innodb_inplace_alter_table_enter SIGNAL con1_begin WAIT_FOR con1_update'; +send ALTER TABLE t1 MODIFY COLUMN f2 INT NOT NULL, FORCE, ALGORITHM=INPLACE; +connection con1; +SET DEBUG_SYNC='now WAIT_FOR con1_begin'; +UPDATE t1 SET f2=204 order by f1 limit 2; +SET DEBUG_SYNC='now SIGNAL con1_update'; +connection default; +reap; +disconnect con1; SET DEBUG_SYNC=reset; +CHECK TABLE t1; +DROP TABLE t1; --echo # End of 10.4 tests -SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; - SELECT variable_value-@old_instant instants FROM information_schema.global_status WHERE variable_name = 'innodb_instant_alter_column'; + +SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency; diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index 3bb417eedff..0744ee42da4 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -421,7 +421,7 @@ start: } if (!field->fixed_len - || (format == REC_LEAF_TEMP + || (format <= REC_LEAF_TEMP_INSTANT && !dict_col_get_fixed_size(col, true))) { /* Variable-length field: read the length */ len = *lens--; From 87abae46010b9b2847b6fac420d1450522813ad1 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Tue, 27 Feb 2024 09:48:14 +0100 Subject: [PATCH 025/106] galera: wsrep-lib submodule update --- wsrep-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsrep-lib b/wsrep-lib index a5d95f0175f..6a17207b7f4 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit a5d95f0175f10b6127ea039c542725f6c4aa5cb9 +Subproject commit 6a17207b7f44379cdcd73d69203c1a37b901c9d3 From c9b0c006e0491c9f7a1dae07090db3cdb87da446 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Mon, 19 Feb 2024 18:17:36 +0100 Subject: [PATCH 026/106] galera: correction after wsrep-lib update Correction to ensure compatibility with the updated wsrep-lib library. --- sql/wsrep_client_service.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sql/wsrep_client_service.h b/sql/wsrep_client_service.h index 253d2f43ac3..b74c52b038f 100644 --- a/sql/wsrep_client_service.h +++ b/sql/wsrep_client_service.h @@ -57,6 +57,10 @@ public: { return false; } + bool is_prepared_xa() + { + return false; + } bool is_xa_rollback() { return false; From 71834ccb6c303a2115a66becbdc8a831e6f631c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 27 Feb 2024 11:14:28 +0200 Subject: [PATCH 027/106] MDEV-24671 fixup: Remove srv_max_n_threads The variable srv_max_n_threads lost its usefulness in commit db006a9a43b6e68c4b92d2762043fa76b313623c (MDEV-21452) and commit e71e6133535da8d5eab86e504f0b116a03680780 (MDEV-24671). --- extra/mariabackup/backup_copy.cc | 4 ---- extra/mariabackup/xtrabackup.cc | 17 ----------------- storage/innobase/include/srv0srv.h | 4 ---- storage/innobase/srv/srv0start.cc | 10 ---------- 4 files changed, 35 deletions(-) diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index 04154be0538..7b3336f67b7 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -1893,8 +1893,6 @@ copy_back() return(false); } - srv_max_n_threads = 1000; - /* copy undo tablespaces */ Copy_back_dst_dir dst_dir_buf; @@ -2172,8 +2170,6 @@ decrypt_decompress() bool ret; datadir_iter_t *it = NULL; - srv_max_n_threads = 1000; - /* cd to backup directory */ if (my_setwd(xtrabackup_target_dir, MYF(MY_WME))) { diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 5b0a61f686e..b9d58517b9b 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -4714,22 +4714,6 @@ fail: return(false); } - if (srv_buf_pool_size >= 1000 * 1024 * 1024) { - /* Here we still have srv_pool_size counted - in kilobytes (in 4.0 this was in bytes) - srv_boot() converts the value to - pages; if buffer pool is less than 1000 MB, - assume fewer threads. */ - srv_max_n_threads = 50000; - - } else if (srv_buf_pool_size >= 8 * 1024 * 1024) { - - srv_max_n_threads = 10000; - } else { - srv_max_n_threads = 1000; /* saves several MB of memory, - especially in 64-bit - computers */ - } srv_thread_pool_init(); /* Reset the system variables in the recovery module. */ trx_pool_init(); @@ -6166,7 +6150,6 @@ static bool xtrabackup_prepare_func(char** argv) return(false); } - srv_max_n_threads = 1000; srv_n_purge_threads = 1; xb_filters_init(); diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index a45aa0d14dd..ffed1090a44 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -174,10 +174,6 @@ struct srv_stats_t ulint_ctr_n_t n_temp_blocks_decrypted; }; -/** We are prepared for a situation that we have this many threads waiting for -a transactional lock inside InnoDB. srv_start() sets the value. */ -extern ulint srv_max_n_threads; - extern const char* srv_main_thread_op_info; /** Prefix used by MySQL to indicate pre-5.1 table name encoding */ diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 01623c8c27a..fb2590df137 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -92,10 +92,6 @@ Created 2/16/1996 Heikki Tuuri #include "ut0crc32.h" #include "log.h" -/** We are prepared for a situation that we have this many threads waiting for -a transactional lock inside InnoDB. srv_start() sets the value. */ -ulint srv_max_n_threads; - /** Log sequence number at shutdown */ lsn_t srv_shutdown_lsn; @@ -1127,12 +1123,6 @@ dberr_t srv_start(bool create_new_db) mysql_stage_register("innodb", srv_stages, static_cast(UT_ARR_SIZE(srv_stages))); - srv_max_n_threads = - 1 /* dict_stats_thread */ - + 1 /* fts_optimize_thread */ - + 128 /* safety margin */ - + max_connections; - srv_boot(); ib::info() << my_crc32c_implementation(); From a8f6b86c9053a929e455b8339e2068651faf5084 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 18 Feb 2024 16:02:40 +0200 Subject: [PATCH 028/106] Have ha_partition ignore HA_EXTRA..CHILDREN extra() calls if no myisamrg MDEV-33502 Slowdown when running nested statement with many partitions Optimization for tables with a lot of partitions --- sql/ha_partition.cc | 13 ++++++++++++- sql/ha_partition.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index e174ef8d219..f2b3ab3aff9 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -398,6 +398,7 @@ void ha_partition::init_handler_variables() m_start_key.length= 0; m_myisam= FALSE; m_innodb= FALSE; + m_myisammrg= FALSE; m_extra_cache= FALSE; m_extra_cache_size= 0; m_extra_prepare_for_update= FALSE; @@ -3030,6 +3031,10 @@ bool ha_partition::create_handlers(MEM_ROOT *mem_root) DBUG_PRINT("info", ("InnoDB")); m_innodb= TRUE; } + else if (ha_legacy_type(hton0) == DB_TYPE_MRG_MYISAM) + { + m_myisammrg= TRUE; + } DBUG_RETURN(FALSE); } @@ -9419,9 +9424,14 @@ int ha_partition::extra(enum ha_extra_function operation) } /* Category 9) Operations only used by MERGE */ case HA_EXTRA_ADD_CHILDREN_LIST: + if (!m_myisammrg) + DBUG_RETURN(0); DBUG_RETURN(loop_partitions(extra_cb, &operation)); case HA_EXTRA_ATTACH_CHILDREN: { + if (!m_myisammrg) + DBUG_RETURN(0); + int result; uint num_locks; handler **file; @@ -9440,8 +9450,9 @@ int ha_partition::extra(enum ha_extra_function operation) break; } case HA_EXTRA_IS_ATTACHED_CHILDREN: - DBUG_RETURN(loop_partitions(extra_cb, &operation)); case HA_EXTRA_DETACH_CHILDREN: + if (!m_myisammrg) + DBUG_RETURN(0); DBUG_RETURN(loop_partitions(extra_cb, &operation)); case HA_EXTRA_MARK_AS_LOG_TABLE: /* diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 0ac8f696fcf..b252b7304f0 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -399,6 +399,7 @@ private: */ bool m_innodb; // Are all underlying handlers // InnoDB + bool m_myisammrg; // Are any of the handlers of type MERGE /* When calling extra(HA_EXTRA_CACHE) we do not pass this to the underlying handlers immediately. Instead we cache it and call the underlying From d4e1731fbc5f8fb05648a8b3e9ecd8bef4cafd36 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 18 Feb 2024 16:05:42 +0200 Subject: [PATCH 029/106] Optimize handler_stats_disable() when handler_stats are already disabled MDEV-33502 Slowdown when running nested statement with many partitions --- sql/handler.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sql/handler.h b/sql/handler.h index 58e8bf64662..be0794a73a9 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -3456,6 +3456,7 @@ public: ("handler created F_UNLCK %d F_RDLCK %d F_WRLCK %d", F_UNLCK, F_RDLCK, F_WRLCK)); reset_statistics(); + active_handler_stats.active= 0; } virtual ~handler(void) { @@ -4877,9 +4878,12 @@ public: } inline void ha_handler_stats_disable() { - handler_stats= 0; - active_handler_stats.active= 0; - handler_stats_updated(); + if (handler_stats) + { + handler_stats= 0; + active_handler_stats.active= 0; + handler_stats_updated(); + } } private: From 969669767ba4f4dcfadbcc73d14d0904ad3c6aca Mon Sep 17 00:00:00 2001 From: mariadb-DebarunBanerjee Date: Tue, 27 Feb 2024 17:59:20 +0530 Subject: [PATCH 030/106] MDEV-33011 mariabackup --backup: FATAL ERROR: ... Can't open datafile cool_down/t3 The root cause is the WAL logging of file operation when the actual operation fails afterwards. It creates a situation with a log entry for a operation that would always fail. I could simulate both the backup scenario error and Innodb recovery failure exploiting the weakness. We are following WAL for file rename operation and once logged the operation must eventually complete successfully, or it is a major catastrophe. Right now, we fail for rename and handle it as normal error and it is the problem. I created a patch to address RENAME operation to a non existing schema where the destination schema directory is missing. The patch checks for the missing schema before logging in an attempt to avoid the failure after WAL log is written/flushed. I also checked that the schema cannot be dropped or there cannot be any race with other rename to the same file. This is protected by the MDL lock in SQL today. The patch should this be a good improvement over the current situation and solves the issue at hand. --- mysql-test/suite/innodb/r/rename_table.result | 10 ++++- mysql-test/suite/innodb/t/rename_table.test | 9 ++++- .../mariabackup/rename_during_backup.result | 12 ++++++ .../mariabackup/rename_during_backup.test | 27 +++++++++++++ storage/innobase/fil/fil0fil.cc | 27 +++++++++---- storage/innobase/include/fil0fil.h | 38 +++++++++++++++++-- 6 files changed, 107 insertions(+), 16 deletions(-) diff --git a/mysql-test/suite/innodb/r/rename_table.result b/mysql-test/suite/innodb/r/rename_table.result index 23bb8c52d4a..ead04a91df4 100644 --- a/mysql-test/suite/innodb/r/rename_table.result +++ b/mysql-test/suite/innodb/r/rename_table.result @@ -20,9 +20,15 @@ path DROP DATABASE abc_def; # restart DROP DATABASE abc_def2; -call mtr.add_suppression("InnoDB: (Operating system error|The error means|Cannot rename file)"); +call mtr.add_suppression("InnoDB: Cannot rename '.*t1.ibd' to '.*non_existing_db.*' because the target schema directory doesn't exist"); CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES(100); RENAME TABLE t1 TO non_existing_db.t1; ERROR HY000: Error on rename of './test/t1' to './non_existing_db/t1' (errno: 168 "Unknown (generic) error from engine") -FOUND 1 /\[ERROR\] InnoDB: Cannot rename file '.*t1\.ibd' to '.*non_existing_db/ in mysqld.1.err +FOUND 1 /\[ERROR\] InnoDB: Cannot rename '.*t1\.ibd' to '.*non_existing_db/ in mysqld.1.err +SET GLOBAL innodb_fast_shutdown=2; +# restart +SELECT * FROM t1; +a +100 DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/rename_table.test b/mysql-test/suite/innodb/t/rename_table.test index 0191a94def2..f81deea0169 100644 --- a/mysql-test/suite/innodb/t/rename_table.test +++ b/mysql-test/suite/innodb/t/rename_table.test @@ -30,16 +30,21 @@ DROP DATABASE abc_def; DROP DATABASE abc_def2; -call mtr.add_suppression("InnoDB: (Operating system error|The error means|Cannot rename file)"); +call mtr.add_suppression("InnoDB: Cannot rename '.*t1.ibd' to '.*non_existing_db.*' because the target schema directory doesn't exist"); CREATE TABLE t1 (a INT) ENGINE=InnoDB; +INSERT INTO t1 VALUES(100); --replace_result "\\" "/" --error ER_ERROR_ON_RENAME RENAME TABLE t1 TO non_existing_db.t1; ---let SEARCH_PATTERN= \[ERROR\] InnoDB: Cannot rename file '.*t1\.ibd' to '.*non_existing_db +--let SEARCH_PATTERN= \[ERROR\] InnoDB: Cannot rename '.*t1\.ibd' to '.*non_existing_db let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; --source include/search_pattern_in_file.inc +SET GLOBAL innodb_fast_shutdown=2; +--source include/restart_mysqld.inc + +SELECT * FROM t1; # Cleanup DROP TABLE t1; diff --git a/mysql-test/suite/mariabackup/rename_during_backup.result b/mysql-test/suite/mariabackup/rename_during_backup.result index ba1dbec0e1b..c25b9d3a1b4 100644 --- a/mysql-test/suite/mariabackup/rename_during_backup.result +++ b/mysql-test/suite/mariabackup/rename_during_backup.result @@ -60,3 +60,15 @@ SELECT * from t6; i 5 DROP TABLE t6; +# +# MDEV-33011 mariabackup --backup: FATAL ERROR: ... Can't open datafile cool_down/t3 +# +# Simulate zero initialized page to defer tablespace load after rename log is found +SET @save_dbug = @@SESSION.debug_dbug; +SET DEBUG_DBUG="+d,checkpoint_after_file_create"; +CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); +# RENAME that fails after redo log entry is written and flushed +RENAME TABLE t1 TO non_existing_db.t1; +ERROR HY000: Error on rename of './test/t1' to './non_existing_db/t1' (errno: 168 "Unknown (generic) error from engine") +DROP TABLE t1; diff --git a/mysql-test/suite/mariabackup/rename_during_backup.test b/mysql-test/suite/mariabackup/rename_during_backup.test index 238a8b1985c..ebebb3b2cf9 100644 --- a/mysql-test/suite/mariabackup/rename_during_backup.test +++ b/mysql-test/suite/mariabackup/rename_during_backup.test @@ -90,4 +90,31 @@ SELECT * from t6; DROP TABLE t6; rmdir $targetdir; +--echo # +--echo # MDEV-33011 mariabackup --backup: FATAL ERROR: ... Can't open datafile cool_down/t3 +--echo # +--disable_query_log +call mtr.add_suppression("InnoDB: Cannot rename '.*t1.ibd' to '.*non_existing_db.*' because the target schema directory doesn't exist"); +--enable_query_log + +mkdir $targetdir; + +--echo # Simulate zero initialized page to defer tablespace load after rename log is found +SET @save_dbug = @@SESSION.debug_dbug; +SET DEBUG_DBUG="+d,checkpoint_after_file_create"; +CREATE TABLE t1(f1 INT NOT NULL)ENGINE=InnoDB; +INSERT INTO t1 VALUES(1); + +--echo # RENAME that fails after redo log entry is written and flushed +--replace_result "\\" "/" +--error ER_ERROR_ON_RENAME +RENAME TABLE t1 TO non_existing_db.t1; + +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +exec $XTRABACKUP --prepare --target-dir=$targetdir; +--enable_result_log + +DROP TABLE t1; +rmdir $targetdir; diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 885b0a700ea..88c1115969a 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -1959,14 +1959,14 @@ Allocates and builds a file name from a path, a table or tablespace name and a suffix. The string must be freed by caller with ut_free(). @param[in] path NULL or the directory path or the full path and filename. @param[in] name NULL if path is full, or Table/Tablespace name -@param[in] suffix NULL or the file extention to use. +@param[in] extension NULL or the file extension to use. @param[in] trim_name true if the last name on the path should be trimmed. @return own: file name */ char* -fil_make_filepath( +fil_make_filepath_low( const char* path, const char* name, - ib_extention ext, + ib_extention extension, bool trim_name) { /* The path may contain the basename of the file, if so we do not @@ -1974,10 +1974,6 @@ fil_make_filepath( but there needs to be a name. */ ut_ad(path != NULL || name != NULL); - /* If we are going to strip a name off the path, there better be a - path and a new name to put back on. */ - ut_ad(!trim_name || (path != NULL && name != NULL)); - if (path == NULL) { path = fil_path_to_mysql_datadir; } @@ -1985,7 +1981,7 @@ fil_make_filepath( ulint len = 0; /* current length */ ulint path_len = strlen(path); ulint name_len = (name ? strlen(name) : 0); - const char* suffix = dot_ext[ext]; + const char* suffix = dot_ext[extension]; ulint suffix_len = strlen(suffix); ulint full_len = path_len + 1 + name_len + suffix_len + 1; @@ -2083,6 +2079,21 @@ fil_rename_tablespace_check( } exists = false; + auto schema_path= fil_make_dirpath(new_path, NULL, NO_EXT, true); + if (schema_path == NULL) { + return DB_ERROR; + } + + if (os_file_status(schema_path, &exists, &ftype) && !exists) { + sql_print_error("InnoDB: Cannot rename '%s' to '%s'" + " because the target schema directory doesn't exist.", + old_path, new_path); + ut_free(schema_path); + return DB_ERROR; + } + ut_free(schema_path); + exists = false; + if (os_file_status(new_path, &exists, &ftype) && !exists) { return DB_SUCCESS; } diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 10c084bbbf1..1f5589a4a20 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -1618,14 +1618,44 @@ Allocates and builds a file name from a path, a table or tablespace name and a suffix. The string must be freed by caller with ut_free(). @param[in] path NULL or the directory path or the full path and filename. @param[in] name NULL if path is full, or Table/Tablespace name -@param[in] suffix NULL or the file extention to use. +@param[in] extension NULL or the file extension to use. +@param[in] trim_name true if the last name on the path should be trimmed. @return own: file name */ char* -fil_make_filepath( +fil_make_filepath_low( const char* path, const char* name, - ib_extention suffix, - bool strip_name); + ib_extention extension, + bool trim_name); + +/** Wrapper function over fil_make_filepath_low to build file name. +@param path NULL or the directory path or the full path and filename. +@param name NULL if path is full, or Table/Tablespace name +@param extension NULL or the file extension to use. +@param trim_name true if the last name on the path should be trimmed. +@return own: file name */ +static inline char* +fil_make_filepath(const char* path, const char* name, ib_extention extension, + bool trim_name) +{ + /* If we are going to strip a name off the path, there better be a + path and a new name to put back on. */ + ut_ad(!trim_name || (path && name)); + return fil_make_filepath_low(path, name, extension, trim_name); +} + +/** Wrapper function over fil_make_filepath_low to build directory name. +@param path NULL or the directory path or the full path and filename. +@param name NULL if path is full, or Table/Tablespace name +@param extension NULL or the file extension to use. +@param trim_name true if the last name on the path should be trimmed. +@return own: directory name */ +static inline char* +fil_make_dirpath(const char* path, const char* name, ib_extention extension, + bool trim_name) +{ + return fil_make_filepath_low(path, name, extension, trim_name); +} /** Create a tablespace file. @param[in] space_id Tablespace ID From b5d65fc105b6efa07cbbafcf053f6ce46f02dbc0 Mon Sep 17 00:00:00 2001 From: Monty Date: Sun, 18 Feb 2024 17:30:01 +0200 Subject: [PATCH 031/106] Optimize performance of my_bitmap MDEV-33502 Slowdown when running nested statement with many partitions This change was triggered to help some MariaDB users with close to 10000 bits in their bitmaps. - Change underlaying storage to be 64 bit instead of 32bit. - This reduses number of loops to scan bitmaps. - This can cause some bitmaps to be 4 byte large. - Ensure that all not used top-bits are always 0 (simplifes code as the last 64 bit storage is not a special case anymore). - Use my_find_first_bit() to find the first set bit which is much faster than scanning trough things byte by byte and then bit by bit. Other things: - Added a bool to remember if my_bitmap_init() did allocate the bitmap array. my_bitmap_free() will only free arrays it did allocate. This allowed me to remove setting 'bitmap=0' before calling my_bitmap_free() for cases where the bitmap's where allocated externally. - my_bitmap_init() sets bitmap to 0 in case of failure. - Added 'universal' asserts to most bitmap functions. - Change all remaining calls to bitmap_init() to my_bitmap_init(). - To finish the change from 2014. - Changed all usage of uint32 in my_bitmap.h to my_bitmap_map. - Updated bitmap_copy() to handle bitmaps of different size. - Removed const from bitmap_exists_intersection() as this caused casts on all usage. - Removed not used function bitmap_set_above(). - Renamed create_last_word_mask() to create_last_bit_mask() (to match name changes in my_bitmap.cc) - Extended bitmap-t with test for more bitmap functions. --- include/my_bitmap.h | 50 ++- mysys/my_bitmap.c | 518 ++++++++++------------- sql/ha_partition.cc | 2 +- sql/item_subselect.cc | 5 +- sql/log_event.cc | 34 +- sql/log_event.h | 4 +- sql/log_event_old.cc | 26 +- sql/log_event_old.h | 4 +- sql/log_event_server.cc | 18 +- sql/opt_range.cc | 4 +- sql/sql_insert.cc | 4 +- sql/sql_partition.cc | 11 +- storage/mroonga/ha_mroonga.cpp | 7 +- storage/mroonga/lib/mrn_smart_bitmap.cpp | 2 +- storage/rocksdb/ha_rocksdb.cc | 2 +- storage/rocksdb/ha_rocksdb.h | 2 +- storage/rocksdb/rdb_datadic.cc | 22 +- unittest/mysys/bitmap-t.c | 134 +++++- 18 files changed, 452 insertions(+), 397 deletions(-) diff --git a/include/my_bitmap.h b/include/my_bitmap.h index f19254404c1..5f722d9fbec 100644 --- a/include/my_bitmap.h +++ b/include/my_bitmap.h @@ -22,7 +22,7 @@ #include #include -typedef uint32 my_bitmap_map; +typedef ulonglong my_bitmap_map; typedef struct st_bitmap { @@ -34,21 +34,19 @@ typedef struct st_bitmap acquiring the mutex */ mysql_mutex_t *mutex; - my_bitmap_map last_word_mask; + my_bitmap_map last_bit_mask; uint32 n_bits; /* number of bits occupied by the above */ + my_bool bitmap_allocated; } MY_BITMAP; #ifdef __cplusplus extern "C" { #endif -/* compatibility functions */ -#define bitmap_init(A,B,C,D) my_bitmap_init(A,B,C,D) -#define bitmap_free(A) my_bitmap_free(A) /* Reset memory. Faster then doing a full bzero */ #define my_bitmap_clear(A) ((A)->bitmap= 0) -extern void create_last_word_mask(MY_BITMAP *map); +extern void create_last_bit_mask(MY_BITMAP *map); extern my_bool my_bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, my_bool thread_safe); extern my_bool bitmap_is_clear_all(const MY_BITMAP *map); @@ -63,12 +61,12 @@ extern my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit); extern my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit); extern my_bool bitmap_union_is_set_all(const MY_BITMAP *map1, const MY_BITMAP *map2); -extern my_bool bitmap_exists_intersection(const MY_BITMAP **bitmap_array, +extern my_bool bitmap_exists_intersection(MY_BITMAP **bitmap_array, uint bitmap_count, uint start_bit, uint end_bit); extern uint bitmap_set_next(MY_BITMAP *map); -extern uint bitmap_get_first(const MY_BITMAP *map); +extern uint bitmap_get_first_clear(const MY_BITMAP *map); extern uint bitmap_get_first_set(const MY_BITMAP *map); extern uint bitmap_bits_set(const MY_BITMAP *map); extern uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit); @@ -84,12 +82,16 @@ extern void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2); extern uint bitmap_lock_set_next(MY_BITMAP *map); extern void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit); -/* Fast, not thread safe, bitmap functions */ -#define bitmap_buffer_size(bits) (((bits)+31)/32)*4 + +#define my_bitmap_map_bytes sizeof(my_bitmap_map) +#define my_bitmap_map_bits (my_bitmap_map_bytes*8) +#define bitmap_buffer_size(bits) (MY_ALIGN(bits, my_bitmap_map_bits)*my_bitmap_map_bytes) #define no_bytes_in_map(map) (((map)->n_bits + 7)/8) -#define no_words_in_map(map) (((map)->n_bits + 31)/32) -#define bytes_word_aligned(bytes) (4*((bytes + 3)/4)) -/* The following functions must be compatible with create_last_word_mask()! */ +#define no_words_in_map(map) (((map)->n_bits + (my_bitmap_map_bits-1))/my_bitmap_map_bits) +#define bytes_word_aligned(bytes) (8*((bytes + 7)/8)) + +/* Fast, not thread safe, bitmap functions */ +/* The following functions must be compatible with create_last_bit_mask()! */ static inline void bitmap_set_bit(MY_BITMAP *map,uint bit) { @@ -119,18 +121,26 @@ bitmap_is_set(const MY_BITMAP *map,uint bit) return !!(*b & (1U << (bit & 7))); } +/* Return true if bitmaps are equal */ static inline my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) { - if (memcmp(map1->bitmap, map2->bitmap, 4*(no_words_in_map(map1)-1)) != 0) - return FALSE; - return ((*map1->last_word_ptr | map1->last_word_mask) == - (*map2->last_word_ptr | map2->last_word_mask)); + DBUG_ASSERT(map1->n_bits == map2->n_bits); + return (memcmp(map1->bitmap, map2->bitmap, 8*(no_words_in_map(map1))) == 0); } #define bitmap_clear_all(MAP) \ - { memset((MAP)->bitmap, 0, 4*no_words_in_map((MAP))); } -#define bitmap_set_all(MAP) \ - (memset((MAP)->bitmap, 0xFF, 4*no_words_in_map((MAP)))) + { memset((MAP)->bitmap, 0, 8*no_words_in_map((MAP))); } + +static inline void +bitmap_set_all(const MY_BITMAP *map) +{ + if (map->n_bits) + { + memset(map->bitmap, 0xFF, 8*(no_words_in_map(map)-1)); + DBUG_ASSERT(map->bitmap + no_words_in_map(map)-1 == map->last_word_ptr); + *map->last_word_ptr= ~map->last_bit_mask; + } +} #ifdef __cplusplus } diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index bf2bacd213c..6a646a35fd1 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -13,7 +13,9 @@ 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 Street, Fifth Floor, Boston, MA 02110-1335 USA */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 + USA + */ /* Handling of uchar arrays as large bitmaps. @@ -21,9 +23,18 @@ API limitations (or, rather asserted safety assumptions, to encourage correct programming) - * the internal size is a set of 32 bit words + * the internal storage is a set of 64 bit words * the number of bits specified in creation can be any number > 0 + Implementation notes: + * MY_BITMAP includes a pointer, last_word_ptr, to the last word. + The implication is that if one copies bitmaps to another memory + location, one has to call create_last_bit_mask() on the bitmap to + fix the internal pointer. + * The not used part of a the last word should always be 0. + This avoids special handling of the last bitmap in several cases. + This is checked for most calls to bitmap functions. + TODO: Make assembler thread safe versions of these using test-and-set instructions @@ -31,95 +42,94 @@ New version written and test program added and some changes to the interface was made by Mikael Ronstrom 2005, with assistance of Tomas Ulin and Mats Kindahl. + Updated to 64 bits and use my_find_first_bit() to speed up + bitmap_get_next_set() by Monty in 2024 */ #include "mysys_priv.h" #include #include #include +#include + + +/* Defines to check bitmaps */ + +#define DBUG_ASSERT_BITMAP(M) \ + DBUG_ASSERT((M)->bitmap); \ + DBUG_ASSERT((M)->n_bits > 0); \ + DBUG_ASSERT((M)->last_word_ptr == (M)->bitmap + no_words_in_map(M)-1); \ + DBUG_ASSERT((*(M)->last_word_ptr & (M)->last_bit_mask) == 0); + +#define DBUG_ASSERT_BITMAP_AND_BIT(M,B) \ + DBUG_ASSERT_BITMAP(M); \ + DBUG_ASSERT((B) < (M)->n_bits); + +#define DBUG_ASSERT_DIFFERENT_BITMAPS(M,N) \ + DBUG_ASSERT_BITMAP(M); \ + DBUG_ASSERT_BITMAP(N); + +#define DBUG_ASSERT_IDENTICAL_BITMAPS(M,N) \ + DBUG_ASSERT_BITMAP(M); \ + DBUG_ASSERT_BITMAP(N); \ + DBUG_ASSERT((M)->n_bits == (N)->n_bits); /* - Create a mask with the upper 'unused' bits set and the lower 'used' - bits clear. The bits within each byte is stored in big-endian order. + Create a mask for the usable bits on the LAST my_bitmap_map position for + a bitmap with 'bits' number of bits. + + The lowest 'bits' bits are set to zero and the rest bits are set to 1. + For (bits & 63) == 0 , 0 is returned as in this case all bits in the + my_bitmap_position are significant. (This example assumes the + storage is ulonglong). + + For 'bits & 63' it will return values from the series + 0, 0xfffffffffffffffe,.... 0x8000000000000000 */ -static inline uchar invers_last_byte_mask(uint bits) +static inline my_bitmap_map last_bit_mask(uint bits) { - return last_byte_mask(bits) ^ 255; + uint bits_in_last_map= (bits & (my_bitmap_map_bits-1)); + return bits_in_last_map ? ~((1ULL << bits_in_last_map)-1) : 0ULL; } -void create_last_word_mask(MY_BITMAP *map) +/* + Get a mask of the bits that are to be considered as 'on' at location + starting with 'bits'. + This function has _inv in it's name as it's usage is invers compared + to last_bit_mask(). + + For (bits & 63) it will return values from the series + 0xffffffffffffffff, 0xfffffffffffffffe,.... 0x8000000000000000 +*/ + +static inline my_bitmap_map first_bit_mask_inv(uint bits) { - unsigned char const mask= invers_last_byte_mask(map->n_bits); - - /* - The first bytes are to be set to zero since they represent real bits - in the bitvector. The last bytes are set to 0xFF since they represent - bytes not used by the bitvector. Finally the last byte contains bits - as set by the mask above. - */ - unsigned char *ptr= (unsigned char*)&map->last_word_mask; - - map->last_word_ptr= map->bitmap + no_words_in_map(map)-1; - switch (no_bytes_in_map(map) & 3) { - case 1: - map->last_word_mask= ~0U; - ptr[0]= mask; - return; - case 2: - map->last_word_mask= ~0U; - ptr[0]= 0; - ptr[1]= mask; - return; - case 3: - map->last_word_mask= 0U; - ptr[2]= mask; - ptr[3]= 0xFFU; - return; - case 0: - map->last_word_mask= 0U; - ptr[3]= mask; - return; - } + uint bits_in_last_map= (bits & (my_bitmap_map_bits-1)); + return ~((1ULL << bits_in_last_map)-1); } -static inline my_bitmap_map last_word_mask(uint bit) +/* + Update the bitmap's last_word_ptr and last_bit_mask + Also ensure that the last world is all zero to make it + easy to find the next set bit. + + Note that if n_bits is 0, then last_word_ptr will point to + bitmap (safely). The bitmap will not be usable for almost any operation. +*/ + +void create_last_bit_mask(MY_BITMAP *map) { - my_bitmap_map last_word_mask; - uint n_bits= bit + 1; - unsigned char const mask= invers_last_byte_mask(n_bits); - - /* - The first bytes are to be set to zero since they represent real bits - in the bitvector. The last bytes are set to 0xFF since they represent - bytes not used by the bitvector. Finally the last byte contains bits - as set by the mask above. - */ - unsigned char *ptr= (unsigned char*)&last_word_mask; - - switch ((n_bits + 7)/8 & 3) { - case 1: - last_word_mask= ~0U; - ptr[0]= mask; - break; - case 2: - last_word_mask= ~0U; - ptr[0]= 0; - ptr[1]= mask; - break; - case 3: - last_word_mask= 0U; - ptr[2]= mask; - ptr[3]= 0xFFU; - break; - case 0: - last_word_mask= 0U; - ptr[3]= mask; - break; + my_bitmap_map mask= last_bit_mask(map->n_bits); + map->last_bit_mask= mask; + map->last_word_ptr= map->bitmap + MY_MAX(no_words_in_map(map),1) -1; + if (map->n_bits > 0) + { + *map->last_word_ptr&= ~mask; /* Set not used bits to 0 */ + DBUG_ASSERT_BITMAP(map); } - return last_word_mask; } @@ -136,25 +146,6 @@ static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused))) } -static inline uint get_first_set(my_bitmap_map value, uint word_pos) -{ - uchar *byte_ptr= (uchar*)&value; - uchar byte_value; - uint byte_pos, bit_pos; - - DBUG_ASSERT(value); - for (byte_pos=0; ; byte_pos++, byte_ptr++) - { - if ((byte_value= *byte_ptr)) - { - for (bit_pos=0; ; bit_pos++) - if (byte_value & (1 << bit_pos)) - return (word_pos*32) + (byte_pos*8) + bit_pos; - } - } - return MY_BIT_NONE; /* Impossible */ -} - /* Initialize a bitmap object. All bits will be set to zero */ @@ -164,6 +155,7 @@ my_bool my_bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, { DBUG_ENTER("my_bitmap_init"); map->mutex= 0; + if (!buf) { uint size_in_bytes= bitmap_buffer_size(n_bits); @@ -175,21 +167,26 @@ my_bool my_bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, } if (!(buf= (my_bitmap_map*) my_malloc(key_memory_MY_BITMAP_bitmap, size_in_bytes+extra, MYF(MY_WME)))) + { + map->bitmap= 0; DBUG_RETURN(1); + } if (thread_safe) { map->mutex= (mysql_mutex_t *) ((char*) buf + size_in_bytes); mysql_mutex_init(key_BITMAP_mutex, map->mutex, MY_MUTEX_INIT_FAST); } + map->bitmap_allocated= 1; } else { DBUG_ASSERT(thread_safe == 0); + map->bitmap_allocated= 0; } map->bitmap= buf; map->n_bits= n_bits; - create_last_word_mask(map); + create_last_bit_mask(map); bitmap_clear_all(map); DBUG_RETURN(0); } @@ -202,7 +199,8 @@ void my_bitmap_free(MY_BITMAP *map) { if (map->mutex) mysql_mutex_destroy(map->mutex); - my_free(map->bitmap); + if (map->bitmap_allocated) + my_free(map->bitmap); map->bitmap=0; } DBUG_VOID_RETURN; @@ -227,6 +225,7 @@ my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) uchar *value= ((uchar*) map->bitmap) + (bitmap_bit / 8); uchar bit= 1 << ((bitmap_bit) & 7); uchar res= (*value) & bit; + DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit); *value|= bit; return res; } @@ -248,8 +247,7 @@ my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit) { my_bool res; - DBUG_ASSERT(map->bitmap); - DBUG_ASSERT(bitmap_bit < map->n_bits); + DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit); bitmap_lock(map); res= bitmap_fast_test_and_set(map, bitmap_bit); bitmap_unlock(map); @@ -274,6 +272,8 @@ my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit) uchar *byte= (uchar*) map->bitmap + (bitmap_bit / 8); uchar bit= 1 << ((bitmap_bit) & 7); uchar res= (*byte) & bit; + DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit); + *byte&= ~bit; return res; } @@ -282,8 +282,8 @@ my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit) { my_bool res; - DBUG_ASSERT(map->bitmap); - DBUG_ASSERT(bitmap_bit < map->n_bits); + DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit); + bitmap_lock(map); res= bitmap_fast_test_and_clear(map, bitmap_bit); bitmap_unlock(map); @@ -294,8 +294,8 @@ my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit) uint bitmap_set_next(MY_BITMAP *map) { uint bit_found; - DBUG_ASSERT(map->bitmap); - if ((bit_found= bitmap_get_first(map)) != MY_BIT_NONE) + DBUG_ASSERT_BITMAP(map); + if ((bit_found= bitmap_get_first_clear(map)) != MY_BIT_NONE) bitmap_set_bit(map, bit_found); return bit_found; } @@ -305,15 +305,16 @@ uint bitmap_set_next(MY_BITMAP *map) Set the specified number of bits in the bitmap buffer. @param map [IN] Bitmap - @param prefix_size [IN] Number of bits to be set + @param prefix_size [IN] Number of bits to be set or (uint) ~0 for all */ + void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) { uint prefix_bytes, prefix_bits, d; uchar *m= (uchar *)map->bitmap; - - DBUG_ASSERT(map->bitmap); + DBUG_ASSERT_BITMAP(map); DBUG_ASSERT(prefix_size <= map->n_bits || prefix_size == (uint) ~0); + set_if_smaller(prefix_size, map->n_bits); if ((prefix_bytes= prefix_size / 8)) memset(m, 0xff, prefix_bytes); @@ -326,37 +327,45 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) } if ((d= no_bytes_in_map(map)-prefix_bytes)) memset(m, 0, d); + DBUG_ASSERT_BITMAP(map); } +/** + Check if bitmap is a bitmap of prefix bits set in the beginning + + @param map bitmap + @param prefix_size number of bits that should be set. 0 is allowed. + + @return 1 Yes, prefix bits where set or prefix_size == 0. + @return 0 No +*/ + my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) { uint prefix_mask= last_byte_mask(prefix_size); uchar *m= (uchar*) map->bitmap; uchar *end_prefix= m+(prefix_size-1)/8; uchar *end; - DBUG_ASSERT(m); - DBUG_ASSERT(prefix_size <= map->n_bits); /* Empty prefix is always true */ if (!prefix_size) return 1; + DBUG_ASSERT_BITMAP_AND_BIT(map, prefix_size-1); + while (m < end_prefix) if (*m++ != 0xff) return 0; - end= ((uchar*) map->bitmap) + no_bytes_in_map(map) - 1; - if (m == end) - return ((*m & last_byte_mask(map->n_bits)) == prefix_mask); - + end= ((uchar*) map->last_word_ptr) + sizeof(*map->last_word_ptr)-1; if (*m != prefix_mask) return 0; - while (++m < end) + while (++m <= end) if (*m != 0) return 0; - return ((*m & last_byte_mask(map->n_bits)) == 0); + return 1; } @@ -364,10 +373,12 @@ my_bool bitmap_is_set_all(const MY_BITMAP *map) { my_bitmap_map *data_ptr= map->bitmap; my_bitmap_map *end= map->last_word_ptr; + DBUG_ASSERT_BITMAP(map); + for (; data_ptr < end; data_ptr++) - if (*data_ptr != 0xFFFFFFFF) + if (*data_ptr != ~(my_bitmap_map)0) return FALSE; - return (*data_ptr | map->last_word_mask) == 0xFFFFFFFF; + return (*data_ptr | map->last_bit_mask) == ~(my_bitmap_map)0; } @@ -375,61 +386,58 @@ my_bool bitmap_is_clear_all(const MY_BITMAP *map) { my_bitmap_map *data_ptr= map->bitmap; my_bitmap_map *end= map->last_word_ptr; + DBUG_ASSERT_BITMAP(map); - DBUG_ASSERT(map->n_bits > 0); - for (; data_ptr < end; data_ptr++) + for (; data_ptr <= end; data_ptr++) if (*data_ptr) return FALSE; - return (*data_ptr & ~map->last_word_mask) == 0; + return TRUE; } + /* Return TRUE if map1 is a subset of map2 */ my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) { - my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; + my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end= map1->last_word_ptr; + DBUG_ASSERT_IDENTICAL_BITMAPS(map1,map2); - DBUG_ASSERT(map1->bitmap && map2->bitmap); - DBUG_ASSERT(map1->n_bits==map2->n_bits); - - end= map1->last_word_ptr; - while (m1 < end) + while (m1 <= end) { if ((*m1++) & ~(*m2++)) return 0; } - /* here both maps have the same number of bits - see assert above */ - return ((*m1 & ~*m2 & ~map1->last_word_mask) ? 0 : 1); + return 1; } /* True if bitmaps has any common bits */ my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2) { - my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; + my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end= map1->last_word_ptr; + DBUG_ASSERT_IDENTICAL_BITMAPS(map1,map2); - DBUG_ASSERT(map1->bitmap); - DBUG_ASSERT(map2->bitmap); - DBUG_ASSERT(map1->n_bits==map2->n_bits); - - end= map1->last_word_ptr; - while (m1 < end) + while (m1 <= end) { if ((*m1++) & (*m2++)) return 1; } - /* here both maps have the same number of bits - see assert above */ - return ((*m1 & *m2 & ~map1->last_word_mask) ? 1 : 0); + return 0; } +/* + Create intersection of two bitmaps + + @param map map1. Result is stored here + @param map2 map2 +*/ + void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; uint len= no_words_in_map(map), len2 = no_words_in_map(map2); - - DBUG_ASSERT(map->bitmap); - DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT_DIFFERENT_BITMAPS(map,map2); end= to+MY_MIN(len,len2); while (to < end) @@ -437,7 +445,7 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) if (len2 <= len) { - to[-1]&= ~map2->last_word_mask; /* Clear last not relevant bits */ + to[-1]&= ~map2->last_bit_mask; /* Clear last not relevant bits */ end+= len-len2; while (to < end) *to++= 0; @@ -447,50 +455,51 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) /* Check if there is some bit index between start_bit and end_bit, such that - this is bit is set for all bitmaps in bitmap_list. + this is at least on bit that set for all bitmaps in bitmap_list. SYNOPSIS bitmap_exists_intersection() bitmpap_array [in] a set of MY_BITMAPs - bitmap_count [in] number of elements in bitmpap_array + bitmap_count [in] number of elements in bitmap_array start_bit [in] beginning (inclusive) of the range of bits to search end_bit [in] end (inclusive) of the range of bits to search, must be no bigger than the bits of the shortest bitmap. - NOTES - This function assumes that for at least one of the bitmaps in bitmap_array all - bits outside the range [start_bit, end_bit] are 0. As a result is not - necessary to take care of the bits outside the range [start_bit, end_bit]. - RETURN TRUE if an intersecion exists FALSE no intersection */ -my_bool bitmap_exists_intersection(const MY_BITMAP **bitmap_array, +my_bool bitmap_exists_intersection(MY_BITMAP **bitmap_array, uint bitmap_count, uint start_bit, uint end_bit) { uint i, j, start_idx, end_idx; - my_bitmap_map cur_res; + my_bitmap_map cur_res, first_map; DBUG_ASSERT(bitmap_count); DBUG_ASSERT(end_bit >= start_bit); for (j= 0; j < bitmap_count; j++) - DBUG_ASSERT(end_bit < bitmap_array[j]->n_bits); + { + DBUG_ASSERT_BITMAP_AND_BIT(bitmap_array[j], end_bit); + } start_idx= start_bit/8/sizeof(my_bitmap_map); end_idx= end_bit/8/sizeof(my_bitmap_map); + first_map= first_bit_mask_inv(start_bit); + cur_res= first_map; for (i= start_idx; i < end_idx; i++) { - cur_res= ~0; for (j= 0; cur_res && j < bitmap_count; j++) cur_res &= bitmap_array[j]->bitmap[i]; if (cur_res) return TRUE; + cur_res= ~(my_bitmap_map) 0; } - cur_res= ~last_word_mask(end_bit); + cur_res= ~last_bit_mask(end_bit+1); + if (start_idx == end_idx) + cur_res&= first_map; for (j= 0; cur_res && j < bitmap_count; j++) cur_res &= bitmap_array[j]->bitmap[end_idx]; return cur_res != 0; @@ -501,60 +510,21 @@ my_bool bitmap_exists_intersection(const MY_BITMAP **bitmap_array, my_bool bitmap_union_is_set_all(const MY_BITMAP *map1, const MY_BITMAP *map2) { - my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; + my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end= map1->last_word_ptr; + DBUG_ASSERT_IDENTICAL_BITMAPS(map1,map2); - DBUG_ASSERT(map1->bitmap); - DBUG_ASSERT(map2->bitmap); - DBUG_ASSERT(map1->n_bits==map2->n_bits); - end= map1->last_word_ptr; while ( m1 < end) - if ((*m1++ | *m2++) != 0xFFFFFFFF) + if ((*m1++ | *m2++) != ~(my_bitmap_map)0) return FALSE; /* here both maps have the same number of bits - see assert above */ - return ((*m1 | *m2 | map1->last_word_mask) != 0xFFFFFFFF); -} - - - -/* - Set/clear all bits above a bit. - - SYNOPSIS - bitmap_set_above() - map RETURN The bitmap to change. - from_byte The bitmap buffer byte offset to start with. - use_bit The bit value (1/0) to use for all upper bits. - - NOTE - You can only set/clear full bytes. - The function is meant for the situation that you copy a smaller bitmap - to a bigger bitmap. Bitmap lengths are always multiple of eigth (the - size of a byte). Using 'from_byte' saves multiplication and division - by eight during parameter passing. - - RETURN - void -*/ - -void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit) -{ - uchar use_byte= use_bit ? 0xff : 0; - uchar *to= (uchar *)map->bitmap + from_byte; - uchar *end= (uchar *)map->bitmap + (map->n_bits+7)/8; - - while (to < end) - *to++= use_byte; + return ((*m1 | *m2 | map1->last_bit_mask) != ~(my_bitmap_map)0); } void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2) { - my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap); - DBUG_ASSERT(map2->bitmap); - DBUG_ASSERT(map->n_bits==map2->n_bits); - - end= map->last_word_ptr; + my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr; + DBUG_ASSERT_IDENTICAL_BITMAPS(map,map2); while (to <= end) *to++ &= ~(*from++); @@ -563,12 +533,8 @@ void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2) void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) { - my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - - DBUG_ASSERT(map->bitmap); - DBUG_ASSERT(map2->bitmap); - DBUG_ASSERT(map->n_bits == map2->n_bits); - end= map->last_word_ptr; + my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr; + DBUG_ASSERT_IDENTICAL_BITMAPS(map,map2); while (to <= end) *to++ |= *from++; @@ -578,9 +544,8 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr; - DBUG_ASSERT(map->bitmap); - DBUG_ASSERT(map2->bitmap); - DBUG_ASSERT(map->n_bits == map2->n_bits); + DBUG_ASSERT_IDENTICAL_BITMAPS(map,map2); + while (to <= end) *to++ ^= *from++; } @@ -588,13 +553,14 @@ void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2) void bitmap_invert(MY_BITMAP *map) { - my_bitmap_map *to= map->bitmap, *end; + my_bitmap_map *to= map->bitmap, *end= map->last_word_ptr; + DBUG_ASSERT_BITMAP(map); - DBUG_ASSERT(map->bitmap); - end= map->last_word_ptr; + while (to < end) + *to++ ^= ~(my_bitmap_map)0; - while (to <= end) - *to++ ^= 0xFFFFFFFF; + *to ^= (~(my_bitmap_map)0 & ~map->last_bit_mask); + DBUG_ASSERT_BITMAP(map); } @@ -603,45 +569,54 @@ uint bitmap_bits_set(const MY_BITMAP *map) my_bitmap_map *data_ptr= map->bitmap; my_bitmap_map *end= map->last_word_ptr; uint res= 0; - DBUG_ASSERT(map->bitmap); + DBUG_ASSERT_BITMAP(map); - for (; data_ptr < end; data_ptr++) - res+= my_count_bits_uint32(*data_ptr); + for (; data_ptr <= end; data_ptr++) + res+= my_count_bits(*data_ptr); - /*Reset last bits to zero*/ - res+= my_count_bits_uint32(*map->last_word_ptr & ~map->last_word_mask); return res; } -void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2) + +/** + Copy bitmaps + + @param map1 to-bitmap + @param map2 from-bitmap + + @notes + Code will work even of the bitmaps are of different size. + In this case, only up to to->n_bits will be copied. +*/ + +void bitmap_copy(MY_BITMAP *map1, const MY_BITMAP *map2) { - my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; + my_bitmap_map *to= map1->bitmap, *from= map2->bitmap; + uint map1_length= no_words_in_map(map1)*sizeof(my_bitmap_map); + uint map2_length= no_words_in_map(map2)*sizeof(my_bitmap_map); + uint length= MY_MIN(map1_length, map2_length); + DBUG_ASSERT_DIFFERENT_BITMAPS(map1,map2); - DBUG_ASSERT(map->bitmap); - DBUG_ASSERT(map2->bitmap); - DBUG_ASSERT(map->n_bits == map2->n_bits); - end= map->last_word_ptr; - - while (to <= end) - *to++ = *from++; + memcpy(to, from, length); + if (length < map1_length) + bzero(to + length, map1_length - length); + *map1->last_word_ptr&= ~map1->last_bit_mask; } +/* + Find first set bit in the bitmap +*/ + uint bitmap_get_first_set(const MY_BITMAP *map) { - uint i; my_bitmap_map *data_ptr= map->bitmap, *end= map->last_word_ptr; + DBUG_ASSERT_BITMAP(map); - DBUG_ASSERT(map->bitmap); - - for (i=0; data_ptr < end; data_ptr++, i++) + for (uint i=0; data_ptr <= end; data_ptr++, i++) if (*data_ptr) - goto found; - if (!(*data_ptr & ~map->last_word_mask)) - return MY_BIT_NONE; - -found: - return get_first_set(*data_ptr, i); + return my_find_first_bit(*data_ptr) + i * sizeof(my_bitmap_map)*8; + return MY_BIT_NONE; } @@ -656,82 +631,54 @@ found: uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit) { - uint word_pos, byte_to_mask, i; - union { my_bitmap_map bitmap ; uchar bitmap_buff[sizeof(my_bitmap_map)]; } - first_word; - uchar *ptr= &first_word.bitmap_buff[0]; - my_bitmap_map *data_ptr, *end= map->last_word_ptr; - - DBUG_ASSERT(map->bitmap); + uint word_pos; + my_bitmap_map first_word, *data_ptr, *end= map->last_word_ptr; + DBUG_ASSERT_BITMAP(map); /* Look for the next bit */ bitmap_bit++; if (bitmap_bit >= map->n_bits) return MY_BIT_NONE; - word_pos= bitmap_bit / 32; + + word_pos= bitmap_bit / 64; data_ptr= map->bitmap + word_pos; - first_word.bitmap= *data_ptr; - /* Mask out previous bits from first_word */ - byte_to_mask= (bitmap_bit % 32) / 8; - for (i= 0; i < byte_to_mask; i++) - ptr[i]= 0; - ptr[byte_to_mask]&= 0xFFU << (bitmap_bit & 7); + first_word= *data_ptr & first_bit_mask_inv(bitmap_bit); - if (data_ptr == end) + if (first_word) { - if (first_word.bitmap & ~map->last_word_mask) - return get_first_set(first_word.bitmap, word_pos); - else - return MY_BIT_NONE; + /* Optimize common case when most bits are set */ + if (first_word & (1ULL << ((bitmap_bit & (my_bitmap_map_bits-1))))) + return bitmap_bit; + return my_find_first_bit(first_word) + (bitmap_bit & ~(my_bitmap_map_bits-1)); } - - if (first_word.bitmap) - return get_first_set(first_word.bitmap, word_pos); - for (data_ptr++, word_pos++; data_ptr < end; data_ptr++, word_pos++) + for (data_ptr++; data_ptr <= end; data_ptr++) + { + bitmap_bit+= 64; if (*data_ptr) - return get_first_set(*data_ptr, word_pos); - - if (!(*end & ~map->last_word_mask)) - return MY_BIT_NONE; - return get_first_set(*end, word_pos); + return my_find_first_bit(*data_ptr) + (bitmap_bit & ~(my_bitmap_map_bits-1)); + } + return MY_BIT_NONE; } -/* Get first free bit */ +/* Get first clear bit */ -uint bitmap_get_first(const MY_BITMAP *map) +uint bitmap_get_first_clear(const MY_BITMAP *map) { - uchar *byte_ptr; - uint i,j,k; - my_bitmap_map *data_ptr, *end= map->last_word_ptr; + uint i; + my_bitmap_map *data_ptr= map->bitmap, *end= map->last_word_ptr; + DBUG_ASSERT_BITMAP(map); - DBUG_ASSERT(map->bitmap); - data_ptr= map->bitmap; - *map->last_word_ptr|= map->last_word_mask; - - for (i=0; data_ptr < end; data_ptr++, i++) - if (*data_ptr != 0xFFFFFFFF) + for (i= 0; data_ptr < end; data_ptr++, i++) + if (*data_ptr != ~(my_bitmap_map)0) goto found; - if ((*data_ptr | map->last_word_mask) == 0xFFFFFFFF) + if ((*data_ptr | map->last_bit_mask) == ~(my_bitmap_map)0) return MY_BIT_NONE; - found: - byte_ptr= (uchar*)data_ptr; - for (j=0; ; j++, byte_ptr++) - { - if (*byte_ptr != 0xFF) - { - for (k=0; ; k++) - { - if (!(*byte_ptr & (1 << k))) - return (i*32) + (j*8) + k; - } - } - } - DBUG_ASSERT(0); - return MY_BIT_NONE; /* Impossible */ + /* find first zero bit by reverting all bits and find first bit */ + return my_find_first_bit(~*data_ptr) + i * sizeof(my_bitmap_map)*8; } @@ -753,4 +700,3 @@ void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit) bitmap_clear_bit(map, bitmap_bit); bitmap_unlock(map); } - diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index f2b3ab3aff9..74805112823 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3731,7 +3731,7 @@ bool ha_partition::init_partition_bitmaps() if (my_bitmap_init(&m_key_not_found_partitions, NULL, m_tot_parts, FALSE)) DBUG_RETURN(true); - if (bitmap_init(&m_mrr_used_partitions, NULL, m_tot_parts, TRUE)) + if (my_bitmap_init(&m_mrr_used_partitions, NULL, m_tot_parts, TRUE)) DBUG_RETURN(true); if (my_bitmap_init(&m_opened_partitions, NULL, m_tot_parts, FALSE)) diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index cc49d6a3d5d..99b31530d7d 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -6706,9 +6706,10 @@ exists_complementing_null_row(MY_BITMAP *keys_to_complement) return FALSE; } - return bitmap_exists_intersection((const MY_BITMAP**) null_bitmaps, + return bitmap_exists_intersection(null_bitmaps, count_null_keys, - (uint)highest_min_row, (uint)lowest_max_row); + (uint)highest_min_row, + (uint)lowest_max_row); } diff --git a/sql/log_event.cc b/sql/log_event.cc index 2acb77a2dc5..5719296746a 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3387,22 +3387,18 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len, /* if my_bitmap_init fails, caught in is_valid() */ if (likely(!my_bitmap_init(&m_cols, - m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL, - m_width, - false))) + m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL, + m_width, + false))) { DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); memcpy(m_cols.bitmap, ptr_after_width, (m_width + 7) / 8); - create_last_word_mask(&m_cols); + create_last_bit_mask(&m_cols); // Needed to fix last part of bitmap ptr_after_width+= (m_width + 7) / 8; DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); } else - { - // Needed because my_bitmap_init() does not set it to null on failure - m_cols.bitmap= NULL; DBUG_VOID_RETURN; - } m_cols_ai.bitmap= m_cols.bitmap; /* See explanation in is_valid() */ @@ -3412,23 +3408,20 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len, /* if my_bitmap_init fails, caught in is_valid() */ if (likely(!my_bitmap_init(&m_cols_ai, - m_width <= sizeof(m_bitbuf_ai)*8 ? m_bitbuf_ai : NULL, - m_width, - false))) + m_width <= sizeof(m_bitbuf_ai)*8 ? m_bitbuf_ai : + NULL, + m_width, + false))) { DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); memcpy(m_cols_ai.bitmap, ptr_after_width, (m_width + 7) / 8); - create_last_word_mask(&m_cols_ai); + create_last_bit_mask(&m_cols_ai); // Needed to fix last part of bitmap ptr_after_width+= (m_width + 7) / 8; DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap, no_bytes_in_map(&m_cols_ai)); } else - { - // Needed because my_bitmap_init() does not set it to null on failure - m_cols_ai.bitmap= 0; DBUG_VOID_RETURN; - } } const uchar* const ptr_rows_data= (const uchar*) ptr_after_width; @@ -3491,8 +3484,6 @@ void Rows_log_event::uncompress_buf() Rows_log_event::~Rows_log_event() { - if (m_cols.bitmap == m_bitbuf) // no my_malloc happened - m_cols.bitmap= 0; // so no my_free in my_bitmap_free my_bitmap_free(&m_cols); // To pair with my_bitmap_init(). my_free(m_rows_buf); my_free(m_extra_row_data); @@ -4058,12 +4049,7 @@ Delete_rows_compressed_log_event::Delete_rows_compressed_log_event( Update_rows_log_event::~Update_rows_log_event() { - if (m_cols_ai.bitmap) - { - if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened - m_cols_ai.bitmap= 0; // so no my_free in my_bitmap_free - my_bitmap_free(&m_cols_ai); // To pair with my_bitmap_init(). - } + my_bitmap_free(&m_cols_ai); // To pair with my_bitmap_init(). } diff --git a/sql/log_event.h b/sql/log_event.h index 8be46ed30cb..fca4015a15d 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -5163,8 +5163,8 @@ protected: ulong m_master_reclength; /* Length of record on master side */ /* Bit buffers in the same memory as the class */ - uint32 m_bitbuf[128/(sizeof(uint32)*8)]; - uint32 m_bitbuf_ai[128/(sizeof(uint32)*8)]; + my_bitmap_map m_bitbuf[128/(sizeof(my_bitmap_map)*8)]; + my_bitmap_map m_bitbuf_ai[128/(sizeof(my_bitmap_map)*8)]; uchar *m_rows_buf; /* The rows in packed format */ uchar *m_rows_cur; /* One-after the end of the data */ diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index dff4ca29f6f..a7d5519276c 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1156,21 +1156,13 @@ Old_rows_log_event::Old_rows_log_event(THD *thd_arg, TABLE *tbl_arg, set_flags(RELAXED_UNIQUE_CHECKS_F); /* if my_bitmap_init fails, caught in is_valid() */ if (likely(!my_bitmap_init(&m_cols, - m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL, - m_width, - false))) + m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL, + m_width, + false))) { /* Cols can be zero if this is a dummy binrows event */ if (likely(cols != NULL)) - { - memcpy(m_cols.bitmap, cols->bitmap, no_bytes_in_map(cols)); - create_last_word_mask(&m_cols); - } - } - else - { - // Needed because my_bitmap_init() does not set it to null on failure - m_cols.bitmap= 0; + bitmap_copy(&m_cols, cols); } } #endif @@ -1232,13 +1224,13 @@ Old_rows_log_event::Old_rows_log_event(const uchar *buf, uint event_len, /* if my_bitmap_init fails, caught in is_valid() */ if (likely(!my_bitmap_init(&m_cols, - m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL, - m_width, - false))) + m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL, + m_width, + false))) { DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); memcpy(m_cols.bitmap, ptr_after_width, (m_width + 7) / 8); - create_last_word_mask(&m_cols); + create_last_bit_mask(&m_cols); // Needed to fix last part of bitmap ptr_after_width+= (m_width + 7) / 8; DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); } @@ -1274,8 +1266,6 @@ Old_rows_log_event::Old_rows_log_event(const uchar *buf, uint event_len, Old_rows_log_event::~Old_rows_log_event() { - if (m_cols.bitmap == m_bitbuf) // no my_malloc happened - m_cols.bitmap= 0; // so no my_free in my_bitmap_free my_bitmap_free(&m_cols); // To pair with my_bitmap_init(). my_free(m_rows_buf); } diff --git a/sql/log_event_old.h b/sql/log_event_old.h index 1afe9aba60c..1281cb952ae 100644 --- a/sql/log_event_old.h +++ b/sql/log_event_old.h @@ -183,8 +183,8 @@ protected: ulong m_master_reclength; /* Length of record on master side */ /* Bit buffers in the same memory as the class */ - uint32 m_bitbuf[128/(sizeof(uint32)*8)]; - uint32 m_bitbuf_ai[128/(sizeof(uint32)*8)]; + my_bitmap_map m_bitbuf[128/(sizeof(my_bitmap_map)*8)]; + my_bitmap_map m_bitbuf_ai[128/(sizeof(my_bitmap_map)*8)]; uchar *m_rows_buf; /* The rows in packed format */ uchar *m_rows_cur; /* One-after the end of the data */ diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 96e5866e0cc..744a41ca782 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -5289,21 +5289,13 @@ Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, set_flags(NO_CHECK_CONSTRAINT_CHECKS_F); /* if my_bitmap_init fails, caught in is_valid() */ if (likely(!my_bitmap_init(&m_cols, - m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL, - m_width, - false))) + m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL, + m_width, + false))) { /* Cols can be zero if this is a dummy binrows event */ if (likely(cols != NULL)) - { - memcpy(m_cols.bitmap, cols->bitmap, no_bytes_in_map(cols)); - create_last_word_mask(&m_cols); - } - } - else - { - // Needed because my_bitmap_init() does not set it to null on failure - m_cols.bitmap= 0; + bitmap_copy(&m_cols, cols); } } @@ -8401,7 +8393,7 @@ void Update_rows_log_event::init(MY_BITMAP const *cols) if (likely(cols != NULL)) { memcpy(m_cols_ai.bitmap, cols->bitmap, no_bytes_in_map(cols)); - create_last_word_mask(&m_cols_ai); + create_last_bit_mask(&m_cols_ai); // Needed to fix last part of bitmap } } } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 2eaf0dc3c32..7bf712cff2b 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3582,7 +3582,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) table->reginfo.impossible_range= 0; uint used_fields_buff_size= bitmap_buffer_size(table->s->fields); - uint32 *used_fields_buff= (uint32*)thd->alloc(used_fields_buff_size); + my_bitmap_map *used_fields_buff= (my_bitmap_map*)thd->alloc(used_fields_buff_size); MY_BITMAP cols_for_indexes; (void) my_bitmap_init(&cols_for_indexes, used_fields_buff, table->s->fields, 0); bitmap_clear_all(&cols_for_indexes); @@ -7439,7 +7439,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, (*scan)->used_fields_covered= bitmap_bits_set(&(*scan)->covered_fields); (*scan)->first_uncovered_field= - bitmap_get_first(&(*scan)->covered_fields); + bitmap_get_first_clear(&(*scan)->covered_fields); } my_qsort(ror_scan_mark, ror_scans_end-ror_scan_mark, sizeof(ROR_SCAN_INFO*), diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index ec44e47a5d1..53992654706 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1419,7 +1419,7 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view) *trans_end= trans_start + num; Field_translator *trans; uint used_fields_buff_size= bitmap_buffer_size(table->s->fields); - uint32 *used_fields_buff= (uint32*)thd->alloc(used_fields_buff_size); + my_bitmap_map *used_fields_buff= (my_bitmap_map*)thd->alloc(used_fields_buff_size); MY_BITMAP used_fields; enum_column_usage saved_column_usage= thd->column_usage; DBUG_ENTER("check_key_in_view"); @@ -2828,6 +2828,8 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) copy->def_read_set.bitmap= (my_bitmap_map*) bitmap; copy->def_write_set.bitmap= ((my_bitmap_map*) (bitmap + share->column_bitmap_size)); + create_last_bit_mask(©->def_read_set); + create_last_bit_mask(©->def_write_set); bitmaps_used= 2; if (share->default_fields || share->default_expressions) { diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 192e8c679d9..c8ffca03cff 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1085,7 +1085,7 @@ void check_range_capable_PF(TABLE *table) static bool set_up_partition_bitmaps(THD *thd, partition_info *part_info) { - uint32 *bitmap_buf; + my_bitmap_map *bitmap_buf; uint bitmap_bits= part_info->num_subparts? (part_info->num_subparts* part_info->num_parts): part_info->num_parts; @@ -1096,14 +1096,15 @@ static bool set_up_partition_bitmaps(THD *thd, partition_info *part_info) /* Allocate for both read and lock_partitions */ if (unlikely(!(bitmap_buf= - (uint32*) alloc_root(&part_info->table->mem_root, - bitmap_bytes * 2)))) + (my_bitmap_map*) alloc_root(&part_info->table->mem_root, + bitmap_bytes * 2)))) DBUG_RETURN(TRUE); my_bitmap_init(&part_info->read_partitions, bitmap_buf, bitmap_bits, FALSE); /* Use the second half of the allocated buffer for lock_partitions */ - my_bitmap_init(&part_info->lock_partitions, bitmap_buf + (bitmap_bytes / 4), - bitmap_bits, FALSE); + my_bitmap_init(&part_info->lock_partitions, + (my_bitmap_map*) (((char*) bitmap_buf) + bitmap_bytes), + bitmap_bits, FALSE); part_info->bitmaps_are_initialized= TRUE; part_info->set_partition_bitmaps(NULL); DBUG_RETURN(FALSE); diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp index 2b8b17d46e4..356a4a54280 100644 --- a/storage/mroonga/ha_mroonga.cpp +++ b/storage/mroonga/ha_mroonga.cpp @@ -4923,7 +4923,8 @@ int ha_mroonga::open(const char *name, DBUG_RETURN(error); thr_lock_data_init(&share->lock,&thr_lock_data,NULL); - if (bitmap_init(&multiple_column_key_bitmap, NULL, table->s->fields, false)) + if (my_bitmap_init(&multiple_column_key_bitmap, NULL, table->s->fields, + false)) { mrn_free_share(share); share = NULL; @@ -4939,7 +4940,7 @@ int ha_mroonga::open(const char *name, if (error) { - bitmap_free(&multiple_column_key_bitmap); + my_bitmap_free(&multiple_column_key_bitmap); mrn_free_share(share); share = NULL; } @@ -5017,7 +5018,7 @@ int ha_mroonga::close() { error = add_wrap_hton(share->table_name, share->hton); } - bitmap_free(&multiple_column_key_bitmap); + my_bitmap_free(&multiple_column_key_bitmap); if (share->use_count == 1) { mrn_free_long_term_share(share->long_term_share); } diff --git a/storage/mroonga/lib/mrn_smart_bitmap.cpp b/storage/mroonga/lib/mrn_smart_bitmap.cpp index f8fd4f727bb..cdedeb677cd 100644 --- a/storage/mroonga/lib/mrn_smart_bitmap.cpp +++ b/storage/mroonga/lib/mrn_smart_bitmap.cpp @@ -26,7 +26,7 @@ namespace mrn { SmartBitmap::~SmartBitmap() { if (bitmap_) { - bitmap_free(bitmap_); + my_bitmap_free(bitmap_); } } diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 8030a1e3453..f8fb05f16e5 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -10832,7 +10832,7 @@ int ha_rocksdb::index_end() { release_scan_iterator(); - bitmap_free(&m_lookup_bitmap); + my_bitmap_free(&m_lookup_bitmap); active_index = MAX_KEY; in_range_check_pushed_down = FALSE; diff --git a/storage/rocksdb/ha_rocksdb.h b/storage/rocksdb/ha_rocksdb.h index 8580dcbc2e5..ee330dfa82a 100644 --- a/storage/rocksdb/ha_rocksdb.h +++ b/storage/rocksdb/ha_rocksdb.h @@ -397,7 +397,7 @@ class ha_rocksdb : public my_core::handler { current lookup to be covered. If the bitmap field is null, that means this index does not cover the current lookup for any record. */ - MY_BITMAP m_lookup_bitmap = {nullptr, nullptr, nullptr, 0, 0}; + MY_BITMAP m_lookup_bitmap = {nullptr, nullptr, nullptr, 0, 0, 0}; int alloc_key_buffers(const TABLE *const table_arg, const Rdb_tbl_def *const tbl_def_arg, diff --git a/storage/rocksdb/rdb_datadic.cc b/storage/rocksdb/rdb_datadic.cc index 939fb085c4f..4fc6265953b 100644 --- a/storage/rocksdb/rdb_datadic.cc +++ b/storage/rocksdb/rdb_datadic.cc @@ -1102,12 +1102,12 @@ size_t Rdb_key_def::get_unpack_header_size(char tag) { */ void Rdb_key_def::get_lookup_bitmap(const TABLE *table, MY_BITMAP *map) const { DBUG_ASSERT(map->bitmap == nullptr); - bitmap_init(map, nullptr, MAX_REF_PARTS, false); + my_bitmap_init(map, nullptr, MAX_REF_PARTS, false); uint curr_bitmap_pos = 0; // Indicates which columns in the read set might be covered. MY_BITMAP maybe_covered_bitmap; - bitmap_init(&maybe_covered_bitmap, nullptr, table->read_set->n_bits, false); + my_bitmap_init(&maybe_covered_bitmap, nullptr, table->read_set->n_bits, false); for (uint i = 0; i < m_key_parts; i++) { if (table_has_hidden_pk(table) && i + 1 == m_key_parts) { @@ -1135,8 +1135,8 @@ void Rdb_key_def::get_lookup_bitmap(const TABLE *table, MY_BITMAP *map) const { } curr_bitmap_pos++; } else { - bitmap_free(&maybe_covered_bitmap); - bitmap_free(map); + my_bitmap_free(&maybe_covered_bitmap); + my_bitmap_free(map); return; } break; @@ -1144,8 +1144,8 @@ void Rdb_key_def::get_lookup_bitmap(const TABLE *table, MY_BITMAP *map) const { // know this lookup will never be covered. default: if (bitmap_is_set(table->read_set, field->field_index)) { - bitmap_free(&maybe_covered_bitmap); - bitmap_free(map); + my_bitmap_free(&maybe_covered_bitmap); + my_bitmap_free(map); return; } break; @@ -1155,9 +1155,9 @@ void Rdb_key_def::get_lookup_bitmap(const TABLE *table, MY_BITMAP *map) const { // If there are columns which are not covered in the read set, the lookup // can't be covered. if (!bitmap_cmp(table->read_set, &maybe_covered_bitmap)) { - bitmap_free(map); + my_bitmap_free(map); } - bitmap_free(&maybe_covered_bitmap); + my_bitmap_free(&maybe_covered_bitmap); } /* @@ -1187,7 +1187,7 @@ bool Rdb_key_def::covers_lookup(const rocksdb::Slice *const unpack_info, MY_BITMAP covered_bitmap; my_bitmap_map covered_bits; - bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false); + my_bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false); covered_bits = rdb_netbuf_to_uint16((const uchar *)unpack_header + sizeof(RDB_UNPACK_COVERED_DATA_TAG) + RDB_UNPACK_COVERED_DATA_LEN_SIZE); @@ -1356,7 +1356,7 @@ uint Rdb_key_def::pack_record(const TABLE *const tbl, uchar *const pack_buffer, MY_BITMAP covered_bitmap; my_bitmap_map covered_bits; uint curr_bitmap_pos = 0; - bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false); + my_bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false); for (uint i = 0; i < n_key_parts; i++) { // Fill hidden pk id into the last key part for secondary keys for tables @@ -1661,7 +1661,7 @@ int Rdb_key_def::unpack_record(TABLE *const table, uchar *const buf, bool has_covered_bitmap = has_unpack_info && (unpack_header[0] == RDB_UNPACK_COVERED_DATA_TAG); if (has_covered_bitmap) { - bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false); + my_bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false); covered_bits = rdb_netbuf_to_uint16((const uchar *)unpack_header + sizeof(RDB_UNPACK_COVERED_DATA_TAG) + RDB_UNPACK_COVERED_DATA_LEN_SIZE); diff --git a/unittest/mysys/bitmap-t.c b/unittest/mysys/bitmap-t.c index e8f41b32d2c..1f438dd67c5 100644 --- a/unittest/mysys/bitmap-t.c +++ b/unittest/mysys/bitmap-t.c @@ -29,6 +29,8 @@ uint get_rand_bit(uint bitsize) { + if (bitsize == 0) + return 0; return (rand() % bitsize); } @@ -266,7 +268,7 @@ my_bool test_get_first_bit(MY_BITMAP *map, uint bitsize) bitmap_clear_all(map); for (i=0; i < bitsize; i++) bitmap_set_bit(map, i); - if (bitmap_get_first(map) != MY_BIT_NONE) + if (bitmap_get_first_clear(map) != MY_BIT_NONE) goto error2; bitmap_clear_all(map); @@ -278,7 +280,7 @@ my_bool test_get_first_bit(MY_BITMAP *map, uint bitsize) goto error1; bitmap_set_all(map); bitmap_clear_bit(map, test_bit); - if (bitmap_get_first(map) != test_bit) + if (bitmap_get_first_clear(map) != test_bit) goto error2; bitmap_clear_all(map); } @@ -297,14 +299,45 @@ my_bool test_get_next_bit(MY_BITMAP *map, uint bitsize) uint no_loops= bitsize > 128 ? 128 : bitsize; for (i=0; i < no_loops; i++) { + uint count= 0, bits_set= 0; + bitmap_clear_all(map); test_bit=get_rand_bit(bitsize); for (j=0; j < test_bit; j++) bitmap_set_next(map); if (!bitmap_is_prefix(map, test_bit)) goto error1; + j= bitmap_get_first_set(map); + if (j == MY_BIT_NONE) + { + if (test_bit != 0) + goto error1; + continue; + } + count= 1; + while ((j= bitmap_get_next_set(map,j)) != MY_BIT_NONE) + count++; + if (count != test_bit) + goto error1; + + if (test_bit < 3) + continue; bitmap_clear_all(map); + for (j=1; j < test_bit; j+=2) + { + bits_set++; + bitmap_set_bit(map, j); + } + if ((j= bitmap_get_first_set(map)) == MY_BIT_NONE) + goto error1; + count= 1; + while ((j= bitmap_get_next_set(map,j)) != MY_BIT_NONE) + count++; + if (count != bits_set) + goto error1; } + return FALSE; + error1: diag("get_next error bitsize= %u, prefix_size= %u", bitsize,test_bit); return TRUE; @@ -371,7 +404,7 @@ error5: my_bool test_compare(MY_BITMAP *map, uint bitsize) { MY_BITMAP map2; - uint32 map2buf[MAX_TESTED_BITMAP_SIZE]; + my_bitmap_map map2buf[MAX_TESTED_BITMAP_SIZE]; uint i, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; if (my_bitmap_init(&map2, map2buf, bitsize, FALSE)) @@ -431,7 +464,7 @@ my_bool test_intersect(MY_BITMAP *map, uint bitsize) { uint bitsize2 = 1 + get_rand_bit(MAX_TESTED_BITMAP_SIZE - 1); MY_BITMAP map2; - uint32 map2buf[MAX_TESTED_BITMAP_SIZE]; + my_bitmap_map map2buf[MAX_TESTED_BITMAP_SIZE]; uint i, test_bit1, test_bit2, test_bit3; if (my_bitmap_init(&map2, map2buf, bitsize2, FALSE)) { @@ -477,6 +510,94 @@ error: return TRUE; } +my_bool test_copy(MY_BITMAP *map, uint bitsize) +{ + my_bitmap_map buff[16]; + MY_BITMAP map2; + my_bitmap_init(&map2, buff, sizeof(buff)*8, FALSE); + memset((void*) buff, 0xff, sizeof(buff)); + + bitsize= MY_MIN(bitsize, map2.n_bits); + bitmap_copy(map, &map2); + if (bitmap_bits_set(map) != bitsize) + { + diag("bitmap_copy failed on bitsize %d", bitsize); + return 1; + } + return 0; +} + +static my_bool exec_bitmap_exists_intersection(MY_BITMAP **maps, uint bitsize, + uint start, uint end, uint bit) +{ + bitmap_clear_all(maps[0]); + bitmap_clear_all(maps[1]); + bitmap_set_bit(maps[0], bit); + bitmap_set_bit(maps[1], bit); + return bitmap_exists_intersection(maps, 2, start, end); +} + +my_bool test_bitmap_exists_intersection(MY_BITMAP *map, uint bitsize) +{ + MY_BITMAP map2; + uint start_bit, end_bit, rnd_bit; + MY_BITMAP *maps[2]; + maps[0]= map; + maps[1]= &map2; + + my_bitmap_init(&map2, 0, bitsize, FALSE); + bitmap_clear_all(map); + bitmap_clear_all(&map2); + + start_bit= get_rand_bit(bitsize); + end_bit= get_rand_bit(bitsize); + if (start_bit > end_bit) + swap_variables(uint, start_bit, end_bit); + rnd_bit= start_bit+get_rand_bit(end_bit-start_bit); + + if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit, + rnd_bit)) + goto err; + + start_bit= end_bit= rnd_bit= 0; + if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit, + rnd_bit)) + goto err; + + start_bit= rnd_bit= 0 ; end_bit= bitsize-1; + if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit, + rnd_bit)) + goto err; + + start_bit= rnd_bit= end_bit= bitsize-1; + if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit, + rnd_bit)) + goto err; + + if (bitsize > 1) + { + start_bit= end_bit= 1 ; rnd_bit= 0; + if (exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit, + rnd_bit)) + goto err; + + start_bit= end_bit= bitsize-1 ; rnd_bit= bitsize-2; + if (exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit, + rnd_bit)) + goto err; + } + + my_bitmap_free(&map2); + return 0; +err: + diag("bitmap_exist_intersection failed on bitsize: %d start_bit: %d " + "end_bit: %d rnd_bit: %d", + bitsize, start_bit, end_bit, rnd_bit); + my_bitmap_free(&map2); + return 1; +} + + my_bool do_test(uint bitsize) { MY_BITMAP map; @@ -515,6 +636,11 @@ my_bool do_test(uint bitsize) bitmap_clear_all(&map); if (test_intersect(&map,bitsize)) goto error; + bitmap_clear_all(&map); + if (test_copy(&map,bitsize)) + goto error; + if (test_bitmap_exists_intersection(&map, bitsize)) + goto error; return FALSE; error: return TRUE; From 0c079f4f76db8d298e138cc7593f534963f0a7a1 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 20 Feb 2024 15:25:51 +0200 Subject: [PATCH 032/106] Updated test cases result for s3.parition MDEV-21472 ALTER TABLE ... ANALYZE PARTITION ... with EITS reads and locks all rows --- mysql-test/suite/s3/partition.result | 2 -- 1 file changed, 2 deletions(-) diff --git a/mysql-test/suite/s3/partition.result b/mysql-test/suite/s3/partition.result index 9face3ec947..20530bd399a 100644 --- a/mysql-test/suite/s3/partition.result +++ b/mysql-test/suite/s3/partition.result @@ -55,8 +55,6 @@ ERROR HY000: Table 't2' is read only ALTER TABLE t2 ANALYZE PARTITION p3; Table Op Msg_type Msg_text s3.t2 analyze status Table 's3.t2' is read only -s3.t2 analyze status Engine-independent statistics collected -s3.t2 analyze status OK SELECT count(*) FROM t2; count(*) 6 From 89aae15da2eec7276a26dd21484a7d478d1a4dc9 Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 26 Feb 2024 14:51:27 +0200 Subject: [PATCH 033/106] Fixed crash in connect.misc with embedded server The problem was that connect tried to recusiverly call emb_advanced_command(), which was not supported. Fixed by adding support for recursive calls. --- libmysqld/embedded_priv.h | 2 ++ libmysqld/lib_sql.cc | 24 +++++++++++++++++++++--- libmysqld/libmysqld.c | 4 +++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/libmysqld/embedded_priv.h b/libmysqld/embedded_priv.h index 2262706217e..345c3ebd2d5 100644 --- a/libmysqld/embedded_priv.h +++ b/libmysqld/embedded_priv.h @@ -23,6 +23,8 @@ void init_embedded_mysql(MYSQL *mysql, ulong client_flag); void *create_embedded_thd(ulong client_flag); int check_embedded_connection(MYSQL *mysql, const char *db); void free_old_query(MYSQL *mysql); +THD *embedded_get_current_thd(); +void embedded_set_current_thd(THD *thd); extern MYSQL_METHODS embedded_methods; /* This one is used by embedded library to gather returning data */ diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index fdd693279bb..8067ee5bd0c 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -111,7 +111,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, MYSQL_STMT *stmt) { my_bool result= 1; - THD *thd=(THD *) mysql->thd; + THD *thd=(THD *) mysql->thd, *old_current_thd= current_thd; NET *net= &mysql->net; my_bool stmt_skip= stmt ? stmt->state != MYSQL_STMT_INIT_DONE : FALSE; @@ -122,6 +122,8 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, else { free_embedded_thd(mysql); + if (old_current_thd == thd) + old_current_thd= 0; thd= 0; } } @@ -179,6 +181,8 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, end: thd->reset_globals(); + if (old_current_thd) + old_current_thd->store_globals(); return result; } @@ -432,12 +436,15 @@ int emb_unbuffered_fetch(MYSQL *mysql, char **row) static void free_embedded_thd(MYSQL *mysql) { - THD *thd= (THD*)mysql->thd; + THD *thd= (THD*)mysql->thd, *org_current_thd= current_thd; server_threads.erase(thd); thd->clear_data_list(); thd->store_globals(); delete thd; - set_current_thd(nullptr); + if (thd == org_current_thd) + set_current_thd(nullptr); + else + set_current_thd(org_current_thd); mysql->thd=0; } @@ -727,6 +734,17 @@ void *create_embedded_thd(ulong client_flag) } +THD *embedded_get_current_thd() +{ + return current_thd; +} + +void embedded_set_current_thd(THD *thd) +{ + set_current_thd(thd); +} + + #ifdef NO_EMBEDDED_ACCESS_CHECKS static void emb_transfer_connect_attrs(MYSQL *mysql) diff --git a/libmysqld/libmysqld.c b/libmysqld/libmysqld.c index 14cca6e073f..444c1cfbca3 100644 --- a/libmysqld/libmysqld.c +++ b/libmysqld/libmysqld.c @@ -78,7 +78,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, uint port, const char *unix_socket,ulong client_flag) { char name_buff[USERNAME_LENGTH]; - + THD *org_current_thd= embedded_get_current_thd(); DBUG_ENTER("mysql_real_connect"); DBUG_PRINT("enter",("host: %s db: %s user: %s (libmysqld)", host ? host : "(Null)", @@ -200,6 +200,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, } } } + embedded_set_current_thd(org_current_thd); DBUG_PRINT("exit",("Mysql handler: %p", mysql)); DBUG_RETURN(mysql); @@ -216,6 +217,7 @@ error: mysql_close(mysql); mysql->free_me=free_me; } + embedded_set_current_thd(org_current_thd); DBUG_RETURN(0); } From f1c615ec181e47c70207c88848a6b430da29047f Mon Sep 17 00:00:00 2001 From: Monty Date: Mon, 26 Feb 2024 14:52:38 +0200 Subject: [PATCH 034/106] Fixed failure in test connect.drop-open-error for embedded server --- storage/connect/mysql-test/connect/r/drop-open-error.result | 2 +- storage/connect/mysql-test/connect/t/drop-open-error.test | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/storage/connect/mysql-test/connect/r/drop-open-error.result b/storage/connect/mysql-test/connect/r/drop-open-error.result index 34f58a845dc..f9b9b7e87d2 100644 --- a/storage/connect/mysql-test/connect/r/drop-open-error.result +++ b/storage/connect/mysql-test/connect/r/drop-open-error.result @@ -3,7 +3,7 @@ create table tcon engine=connect table_type=mysql CONNECTION='mysql://root@local ERROR HY000: Too long value for 'SRCDEF' drop table mdev9949; Warnings: -Warning 1017 Can't find file: './test/mdev9949.dos' (errno: 2 "No such file or directory") +Warning 1017 Can't find file: 'DATADIR/test/mdev9949.dos' (errno: 2 "No such file or directory") drop table t1; select @@secure_file_priv 'must be NULL'; must be NULL diff --git a/storage/connect/mysql-test/connect/t/drop-open-error.test b/storage/connect/mysql-test/connect/t/drop-open-error.test index 0b73ac98779..dd286c96466 100644 --- a/storage/connect/mysql-test/connect/t/drop-open-error.test +++ b/storage/connect/mysql-test/connect/t/drop-open-error.test @@ -13,7 +13,9 @@ error ER_VALUE_TOO_LONG; create table tcon engine=connect table_type=mysql CONNECTION='mysql://root@localhost/test/t1' SRCDEF='select c from t1 where c in ("foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar")'; # copy the invalid frm (as created by the statement above before the MDEV-9949 fix) +let $MARIADB_DATADIR=`select @@datadir`; copy_file $MTR_SUITE_DIR/std_data/mdev9949.frm $datadir/test/mdev9949.frm; +--replace_result $MARIADB_DATADIR DATADIR/ './' 'DATADIR/' drop table mdev9949; drop table t1; From 0772ac1f1628ade34ae62827480d343e0d6791a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 28 Feb 2024 12:48:38 +0200 Subject: [PATCH 035/106] MDEV-33508 Performance regression due to frequent scan of full buf_pool.flush_list buf_flush_page_cleaner(): Remove a loop that had originally been added in commit 9d1466522ea92963ac6ca16b597392714280c9f1 (MDEV-32029) and made redundant by commit 5b53342a6a59ae1141b2a46467954fc3836f8e80 (MDEV-32588). Starting with commit d34479dc664d4cbd4e9dad6b0f92d7c8e55595d1 (MDEV-33053) this loop would cause a significant performance regression in workloads where buf_pool.need_LRU_eviction() constantly holds in buf_flush_page_cleaner(). Thanks to Steve Shaw of Intel for noticing this. Reviewed by: Debarun Banerjee Tested by: Matthias Leich --- storage/innobase/buf/buf0flu.cc | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 4f7fb316b88..696a09f60d4 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -2433,16 +2433,6 @@ static void buf_flush_page_cleaner() { buf_pool.page_cleaner_set_idle(false); buf_pool.n_flush_inc(); - /* Remove clean blocks from buf_pool.flush_list before the LRU scan. */ - for (buf_page_t *p= UT_LIST_GET_FIRST(buf_pool.flush_list); p; ) - { - const lsn_t lsn{p->oldest_modification()}; - ut_ad(lsn > 2 || lsn == 1); - buf_page_t *n= UT_LIST_GET_NEXT(list, p); - if (lsn <= 1) - buf_pool.delete_from_flush_list(p); - p= n; - } mysql_mutex_unlock(&buf_pool.flush_list_mutex); n= srv_max_io_capacity; mysql_mutex_lock(&buf_pool.mutex); From 31463f1164530464e97f30f6dad27a21842f3b19 Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 28 Feb 2024 16:01:48 +0300 Subject: [PATCH 036/106] MDEV-33502: part#4: Dont make redundant extra(HA_EXTRA_[NO]_KEYREAD) calls In most cases, ha_partition forwards calls to extra() to all locked_partitions. It doesn't make sense to forward some calls for partitions that were pruned away. This patch introduces ha_partition::loop_read_partitions and makes these calls use it: - ha_partition::extra_opt(HA_EXTRA_KEYREAD) - ha_partition::extra(HA_EXTRA_KEYREAD) - ha_partition::extra(HA_EXTRA_NO_KEYREAD) Reviewed-by: Monty --- sql/ha_partition.cc | 52 +++++++++++++++++++++++++++++++++++++++------ sql/ha_partition.h | 4 ++++ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 74805112823..5eebd94c268 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -9314,8 +9314,9 @@ int ha_partition::extra(enum ha_extra_function operation) switch (operation) { /* Category 1), used by most handlers */ case HA_EXTRA_NO_KEYREAD: - DBUG_RETURN(loop_partitions(end_keyread_cb, NULL)); + DBUG_RETURN(loop_read_partitions(end_keyread_cb, NULL)); case HA_EXTRA_KEYREAD: + DBUG_RETURN(loop_read_partitions(extra_cb, &operation)); case HA_EXTRA_FLUSH: case HA_EXTRA_PREPARE_FOR_FORCED_CLOSE: DBUG_RETURN(loop_partitions(extra_cb, &operation)); @@ -9537,7 +9538,7 @@ int ha_partition::extra_opt(enum ha_extra_function operation, ulong arg) switch (operation) { case HA_EXTRA_KEYREAD: - DBUG_RETURN(loop_partitions(start_keyread_cb, &arg)); + DBUG_RETURN(loop_read_partitions(start_keyread_cb, &arg)); case HA_EXTRA_CACHE: prepare_extra_cache(arg); DBUG_RETURN(0); @@ -9625,14 +9626,53 @@ int ha_partition::loop_extra_alter(enum ha_extra_function operation) */ int ha_partition::loop_partitions(handler_callback callback, void *param) +{ + int result= loop_partitions_over_map(&m_part_info->lock_partitions, + callback, param); + /* Add all used partitions to be called in reset(). */ + bitmap_union(&m_partitions_to_reset, &m_part_info->lock_partitions); + return result; +} + + +/* + Call callback(part, param) on read_partitions (the ones used by the query) +*/ + +int ha_partition::loop_read_partitions(handler_callback callback, void *param) +{ + /* + There is no need to record partitions on m_partitions_to_reset as + read_partitions were opened, etc - they will be reset anyway. + */ + return loop_partitions_over_map(&m_part_info->read_partitions, callback, + param); +} + + +/** + Call callback(part, param) on specified set of partitions + + @part_map The set of partitions to call callback for + @param callback a callback to call for each partition + @param param a void*-parameter passed to callback + + @return Operation status + @retval >0 Error code + @retval 0 Success +*/ + +int ha_partition::loop_partitions_over_map(const MY_BITMAP *part_map, + handler_callback callback, + void *param) { int result= 0, tmp; uint i; - DBUG_ENTER("ha_partition::loop_partitions"); + DBUG_ENTER("ha_partition::loop_partitions_over_map"); - for (i= bitmap_get_first_set(&m_part_info->lock_partitions); + for (i= bitmap_get_first_set(part_map); i < m_tot_parts; - i= bitmap_get_next_set(&m_part_info->lock_partitions, i)) + i= bitmap_get_next_set(part_map, i)) { /* This can be called after an error in ha_open. @@ -9642,8 +9682,6 @@ int ha_partition::loop_partitions(handler_callback callback, void *param) (tmp= callback(m_file[i], param))) result= tmp; } - /* Add all used partitions to be called in reset(). */ - bitmap_union(&m_partitions_to_reset, &m_part_info->lock_partitions); DBUG_RETURN(result); } diff --git a/sql/ha_partition.h b/sql/ha_partition.h index b252b7304f0..1757a20d5b7 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -989,6 +989,10 @@ private: handler *file, uint *n); static const uint NO_CURRENT_PART_ID= NOT_A_PARTITION_ID; int loop_partitions(handler_callback callback, void *param); + int loop_partitions_over_map(const MY_BITMAP *map, + handler_callback callback, + void *param); + int loop_read_partitions(handler_callback callback, void *param); int loop_extra_alter(enum ha_extra_function operations); void late_extra_cache(uint partition_id); void late_extra_no_cache(uint partition_id); From bd604add766743d91463a757aa64dd620561f515 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Mon, 26 Feb 2024 12:11:34 -0700 Subject: [PATCH 037/106] MDEV-33546: Rpl_semi_sync_slave_status is ON When Replication Is Not Configured If a server has a default configuration (e.g. in a my.cnf file) with rpl_semi_sync_slave_enabled set, on server start, the corresponding rpl_semi_sync_slave_status variable will also be ON initially, even if the slave was never configured/started. This is because the Repl_semi_sync_slave initialization logic (function init_object()) sets the running status to the enabled value during init_server_components(). This patch fixes this by removing the statement which sets the semi-sync slave running status from the initialization logic. An additional change needed from this is to semi-sync recovery: this status variable was used as a condition to determine binlog truncation during server recovery. This patch also switches this condition to reference the global rpl_semi_sync_slave_enabled variable. Though note, the semi-sync recovery condition is to be changed entirely with the MDEV-33424 agenda. Reviewed By: ============ Andrei Elkin --- .../suite/rpl/r/rpl_semi_sync_fail_over.result | 6 ++++++ mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc | 14 ++++++++++++++ sql/log.cc | 2 +- sql/semisync_slave.cc | 1 - 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result b/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result index 1c94c239fc6..ca7c802bfbe 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_fail_over.result @@ -50,6 +50,8 @@ SELECT @@GLOBAL.gtid_current_pos; 0-1-4 # restart: --skip-slave-start=1 --rpl-semi-sync-slave-enabled=1 connection server_1; +# Ensuring variable rpl_semi_sync_slave_enabled is ON.. +# Ensuring status rpl_semi_sync_slave_status is OFF.. include/assert.inc [Table t1 should have 1 rows.] FOUND 1 /truncated binlog file:.*master.*000001/ in mysqld.1.err disconnect conn_client; @@ -128,6 +130,8 @@ SELECT @@GLOBAL.gtid_current_pos; 0-2-7 # restart: --skip-slave-start=1 --rpl-semi-sync-slave-enabled=1 connection server_2; +# Ensuring variable rpl_semi_sync_slave_enabled is ON.. +# Ensuring status rpl_semi_sync_slave_status is OFF.. include/assert.inc [Table t1 should have 3 rows.] FOUND 1 /truncated binlog file:.*slave.*000002.* to remove transactions starting from GTID 0-1-6/ in mysqld.2.err disconnect conn_client; @@ -207,6 +211,8 @@ SELECT @@GLOBAL.gtid_current_pos; 0-1-9 # restart: --skip-slave-start=1 --rpl-semi-sync-slave-enabled=1 connection server_1; +# Ensuring variable rpl_semi_sync_slave_enabled is ON.. +# Ensuring status rpl_semi_sync_slave_status is OFF.. include/assert.inc [Table t1 should have 6 rows.] FOUND 1 /truncated binlog file:.*master.*000002.* to remove transactions starting from GTID 0-1-9/ in mysqld.1.err disconnect conn_client; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc b/mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc index 01b0d0e5050..b092d0018b0 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_crash.inc @@ -81,6 +81,20 @@ SELECT @@GLOBAL.gtid_current_pos; --enable_reconnect --source include/wait_until_connected_again.inc +--let $slave_semi_sync_enabled= query_get_value(SHOW VARIABLES LIKE 'Rpl_semi_sync_slave_enabled', Value, 1) +--echo # Ensuring variable rpl_semi_sync_slave_enabled is ON.. +if (`SELECT strcmp("ON", "$slave_semi_sync_enabled") != 0`) +{ + --die Slave started with rpl_semi_sync_slave_enabled=1 yet it is OFF in the variable output +} + +--let $slave_semi_sync_status= query_get_value(SHOW STATUS LIKE 'Rpl_semi_sync_slave_status', Value, 1) +--echo # Ensuring status rpl_semi_sync_slave_status is OFF.. +if (`SELECT strcmp("OFF", "$slave_semi_sync_status") != 0`) +{ + --die Slave started with skip-slave-start yet started with rpl_semi_sync_slave_status=ON +} + --let $assert_cond= COUNT(*) = $expected_rows_on_master FROM t1 --let $assert_text= Table t1 should have $expected_rows_on_master rows. --source include/assert.inc diff --git a/sql/log.cc b/sql/log.cc index ce5970b6a03..c91f82211d3 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -11007,7 +11007,7 @@ Recovery_context::Recovery_context() : prev_event_pos(0), last_gtid_standalone(false), last_gtid_valid(false), last_gtid_no2pc(false), last_gtid_engines(0), - do_truncate(repl_semisync_slave.get_slave_enabled()), + do_truncate(global_rpl_semi_sync_slave_enabled), truncate_validated(false), truncate_reset_done(false), truncate_set_in_1st(false), id_binlog(MAX_binlog_id), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF), gtid_maybe_to_truncate(NULL) diff --git a/sql/semisync_slave.cc b/sql/semisync_slave.cc index 6ad19a304d3..9ddd4c5c8d7 100644 --- a/sql/semisync_slave.cc +++ b/sql/semisync_slave.cc @@ -34,7 +34,6 @@ int Repl_semi_sync_slave::init_object() m_init_done = true; /* References to the parameter works after set_options(). */ - set_slave_enabled(global_rpl_semi_sync_slave_enabled); set_trace_level(rpl_semi_sync_slave_trace_level); set_delay_master(rpl_semi_sync_slave_delay_master); set_kill_conn_timeout(rpl_semi_sync_slave_kill_conn_timeout); From 32546877cd75617d33114b85e4a37526ab9ef4bf Mon Sep 17 00:00:00 2001 From: Tony Chen Date: Tue, 12 Dec 2023 05:21:10 +0000 Subject: [PATCH 038/106] MDEV-26923 Check all invalid config options Previously, the behavior was to error out on the first invalid option encountered. With this change, a best effort approach is made so that all invalid options processed will be printed before exiting. There is a caveat. The options are processed many times at varying stages of server startup because the server is not aware of all valid options immediately (e.g. plugins have to be loaded first before the server knows what are the available plugin options). So, there are some options that the server can determine are invalid "early" on, and there are some options that the server cannot determine are invalid until "later" on. For example, the server can determine an option such as `--a` is an ambiguous option very early on but an option such as `--this-does-not-match-any-option` cannot be labelled as invalid until the server is aware of all available options. Thus, it is possible that the server will still fail before printing out all "invalid" options. You can see this by passing `--a --obvious-invalid-option`. Test cases were added to `mysqld_option_err.test` to validate that multiple invalid options will be displayed in the error message. All new code of the whole pull request, including one or several files that are either new files or modified ones, are contributed under the BSD-new license. I am contributing on behalf of my employer Amazon Web Services. --- mysql-test/main/mysqld_option_err.result | 8 ++++ mysql-test/main/mysqld_option_err.test | 12 ++++++ mysys/my_getopt.c | 50 +++++++++++++----------- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/mysql-test/main/mysqld_option_err.result b/mysql-test/main/mysqld_option_err.result index 4afcc5e0cb1..e2c7b0bd213 100644 --- a/mysql-test/main/mysqld_option_err.result +++ b/mysql-test/main/mysqld_option_err.result @@ -3,6 +3,14 @@ Test bad binlog format. Test bad default storage engine. Test non-numeric value passed to number option. Test that bad value for plugin enum option is rejected correctly. +Test to see if multiple unknown options will be displayed in the error output +unknown option '--nonexistentoption' +unknown option '--alsononexistent' +unknown variable 'nonexistentvariable=1' +Test to see if multiple ambiguous options and invalid arguments will be displayed in the error output +Error while setting value 'invalid_value' to 'sql_mode' +ambiguous option '--character' (character-set-client-handshake, character_sets_dir) +option '--bootstrap' cannot take an argument Test that --help --verbose works Test that --not-known-option --help --verbose gives error Done. diff --git a/mysql-test/main/mysqld_option_err.test b/mysql-test/main/mysqld_option_err.test index e9655fd4bfe..ad4df61b0f8 100644 --- a/mysql-test/main/mysqld_option_err.test +++ b/mysql-test/main/mysqld_option_err.test @@ -46,6 +46,18 @@ mkdir $MYSQLTEST_VARDIR/tmp/mysqld_option_err; --error 7 --exec $MYSQLD_BOOTSTRAP_CMD --skip-networking --datadir=$MYSQLTEST_VARDIR/tmp/mysqld_option_err --skip-grant-tables --plugin-dir=$MYSQLTEST_VARDIR/plugins --plugin-load=example=ha_example.so --plugin-example-enum-var=noexist >>$MYSQLTEST_VARDIR/tmp/mysqld_option_err/mysqltest.log 2>&1 +--echo Test to see if multiple unknown options will be displayed in the error output +# Remove the noise to make the test robust +--replace_regex /^((?!nonexistent).)*$// /.*unknown/unknown/ +--error 7 +--exec $MYSQLD_BOOTSTRAP_CMD --skip-networking --datadir=$MYSQLTEST_VARDIR/tmp/mysqld_option_err --skip-grant-tables --nonexistentoption --alsononexistent --nonexistentvariable=1 2>&1 + +--echo Test to see if multiple ambiguous options and invalid arguments will be displayed in the error output +# Remove the noise to make the test robust +--replace_regex /^((?!('sql_mode'|'--character'|'--bootstrap')).)*$// /.*Error while setting value/Error while setting value/ /.*ambiguous option/ambiguous option/ /.*option '--bootstrap'/option '--bootstrap'/ +--error 1 +--exec $MYSQLD_BOOTSTRAP_CMD --skip-networking --datadir=$MYSQLTEST_VARDIR/tmp/mysqld_option_err --skip-grant-tables --getopt-prefix-matching --sql-mode=invalid_value --character --bootstrap=partstoob 2>&1 + # # Test that an wrong option with --help --verbose gives an error # diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index cb0e0e61240..be8a89d2b08 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -133,6 +133,8 @@ double getopt_ulonglong2double(ulonglong v) return u.dbl; } +#define SET_HO_ERROR_AND_CONTINUE(e) { ho_error= (e); continue; } + /** Handle command line options. Sort options. @@ -202,7 +204,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, const char *UNINIT_VAR(prev_found); const struct my_option *optp; void *value; - int error, i; + int ho_error= 0, error, i; my_bool is_cmdline_arg= 1; DBUG_ENTER("handle_options"); @@ -216,7 +218,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, is_cmdline_arg= !is_file_marker(**argv); - for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) + for (pos= *argv, pos_end=pos+ *argc; pos < pos_end ; pos++) { char **first= pos; char *cur_arg= *pos; @@ -305,7 +307,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_progname, special_opt_prefix[i], opt_str, special_opt_prefix[i], prev_found); - DBUG_RETURN(EXIT_AMBIGUOUS_OPTION); + SET_HO_ERROR_AND_CONTINUE(EXIT_AMBIGUOUS_OPTION) } switch (i) { case OPT_SKIP: @@ -350,7 +352,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, "%s: unknown variable '%s'", my_progname, cur_arg); if (!option_is_loose) - DBUG_RETURN(EXIT_UNKNOWN_VARIABLE); + SET_HO_ERROR_AND_CONTINUE(EXIT_UNKNOWN_VARIABLE) } else { @@ -360,7 +362,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, "%s: unknown option '--%s'", my_progname, cur_arg); if (!option_is_loose) - DBUG_RETURN(EXIT_UNKNOWN_OPTION); + SET_HO_ERROR_AND_CONTINUE(EXIT_UNKNOWN_OPTION) } if (option_is_loose) { @@ -377,7 +379,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_getopt_error_reporter(ERROR_LEVEL, "%s: variable prefix '%s' is not unique", my_progname, opt_str); - DBUG_RETURN(EXIT_VAR_PREFIX_NOT_UNIQUE); + SET_HO_ERROR_AND_CONTINUE(EXIT_VAR_PREFIX_NOT_UNIQUE) } else { @@ -386,7 +388,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, "%s: ambiguous option '--%s' (%s, %s)", my_progname, opt_str, prev_found, optp->name); - DBUG_RETURN(EXIT_AMBIGUOUS_OPTION); + SET_HO_ERROR_AND_CONTINUE(EXIT_AMBIGUOUS_OPTION) } } if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED) @@ -400,14 +402,14 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, (*argc)--; continue; } - DBUG_RETURN(EXIT_OPTION_DISABLED); + SET_HO_ERROR_AND_CONTINUE(EXIT_OPTION_DISABLED) } error= 0; value= optp->var_type & GET_ASK_ADDR ? (*my_getopt_get_addr)(key_name, (uint)strlen(key_name), optp, &error) : optp->value; if (error) - DBUG_RETURN(error); + SET_HO_ERROR_AND_CONTINUE(error) if (optp->arg_type == NO_ARG) { @@ -422,7 +424,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_getopt_error_reporter(ERROR_LEVEL, "%s: option '--%s' cannot take an argument", my_progname, optp->name); - DBUG_RETURN(EXIT_NO_ARGUMENT_ALLOWED); + SET_HO_ERROR_AND_CONTINUE(EXIT_NO_ARGUMENT_ALLOWED) } if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL) { @@ -451,7 +453,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, if (get_one_option(optp, *((my_bool*) value) ? enabled_my_option : disabled_my_option, filename)) - DBUG_RETURN(EXIT_ARGUMENT_INVALID); + SET_HO_ERROR_AND_CONTINUE(EXIT_ARGUMENT_INVALID) continue; } argument= optend; @@ -465,7 +467,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, "option '--%s' cannot take an argument", my_progname, optp->name); - DBUG_RETURN(EXIT_NO_ARGUMENT_ALLOWED); + SET_HO_ERROR_AND_CONTINUE(EXIT_NO_ARGUMENT_ALLOWED) } if (!(optp->var_type & GET_AUTO)) { @@ -475,7 +477,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, "unsupported by option '--%s'", my_progname, optp->name); if (!option_is_loose) - DBUG_RETURN(EXIT_ARGUMENT_INVALID); + SET_HO_ERROR_AND_CONTINUE(EXIT_ARGUMENT_INVALID) continue; } else @@ -494,7 +496,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_getopt_error_reporter(ERROR_LEVEL, "%s: option '--%s' requires an argument", my_progname, optp->name); - DBUG_RETURN(EXIT_ARGUMENT_REQUIRED); + SET_HO_ERROR_AND_CONTINUE(EXIT_ARGUMENT_REQUIRED) } argument= *pos; (*argc)--; @@ -519,14 +521,14 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, fprintf(stderr, "%s: ERROR: Option '-%c' used, but is disabled\n", my_progname, optp->id); - DBUG_RETURN(EXIT_OPTION_DISABLED); + SET_HO_ERROR_AND_CONTINUE(EXIT_OPTION_DISABLED) } if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL && optp->arg_type == NO_ARG) { *((my_bool*) optp->value)= (my_bool) 1; if (get_one_option(optp, argument, filename)) - DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); + SET_HO_ERROR_AND_CONTINUE(EXIT_UNSPECIFIED_ERROR) continue; } else if (optp->arg_type == REQUIRED_ARG || @@ -546,7 +548,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, if (optp->var_type == GET_BOOL) *((my_bool*) optp->value)= (my_bool) 1; if (get_one_option(optp, argument, filename)) - DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); + SET_HO_ERROR_AND_CONTINUE(EXIT_UNSPECIFIED_ERROR) continue; } /* Check if there are more arguments after this one */ @@ -556,7 +558,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_getopt_error_reporter(ERROR_LEVEL, "%s: option '-%c' requires an argument", my_progname, optp->id); - DBUG_RETURN(EXIT_ARGUMENT_REQUIRED); + SET_HO_ERROR_AND_CONTINUE(EXIT_ARGUMENT_REQUIRED) } argument= *++pos; (*argc)--; @@ -565,9 +567,9 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, } if ((error= setval(optp, optp->value, argument, set_maximum_value))) - DBUG_RETURN(error); + SET_HO_ERROR_AND_CONTINUE(error) if (get_one_option(optp, argument, filename)) - DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); + SET_HO_ERROR_AND_CONTINUE(EXIT_UNSPECIFIED_ERROR) break; } } @@ -601,7 +603,7 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_getopt_error_reporter(ERROR_LEVEL, "%s: unknown option '-%c'", my_progname, *optend); - DBUG_RETURN(EXIT_UNKNOWN_OPTION); + SET_HO_ERROR_AND_CONTINUE(EXIT_UNKNOWN_OPTION) } } } @@ -612,15 +614,17 @@ int handle_options(int *argc, char ***argv, const struct my_option *longopts, if ((!option_is_autoset) && ((error= setval(optp, value, argument, set_maximum_value))) && !option_is_loose) - DBUG_RETURN(error); + SET_HO_ERROR_AND_CONTINUE(error) if (get_one_option(optp, argument, filename)) - DBUG_RETURN(EXIT_UNSPECIFIED_ERROR); + SET_HO_ERROR_AND_CONTINUE(EXIT_UNSPECIFIED_ERROR) (*argc)--; /* option handled (long), decrease argument count */ } else /* non-option found */ (*argv)[argvpos++]= cur_arg; } + if (ho_error) + DBUG_RETURN(ho_error); /* Destroy the first, already handled option, so that programs that look for arguments in 'argv', without checking 'argc', know when to stop. From 33dcf8155b4a215c9f24ab92f5274bc51503b6f2 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 29 Feb 2024 16:51:17 +0200 Subject: [PATCH 039/106] Fixed memory leaks in embedded server and mysqltest This commit fixes the following issues: - memory leak checking enabled for mysqltest. This cover all cases except calls to 'die()' that only happens in case of internal failures in mysqltest. die() is not called anymore in the result files differs. - One can now run mtr --embedded without failures (this crashed or hang before) - cleanup_and_exit() has a new parameter that indicates that it is called from die(), in which case we should not do memory leak checks. We now always call cleanup_and_exit() instead of exit() to be able to free up memory and discover memory leaks. - Lots of new assert to catch error conditions - More DBUG statements. - Fixed that all results are freed in mysqltest (Fixed a memory leak in mysqltest when using prepared statements). - Fixed race condition in do_stmt_close() that caused embedded server to not free memory. (Memory leak in mysqltest with embedded server). - Fixed two memory leaks in embedded server when using prepared statements. These memory leaks caused timeout hangs in mtr when server was compiled with safemalloc. This issue was not noticed (except as timeouts) as memory report checking was done but output of it was disabled. --- client/mysqltest.cc | 130 ++++++++++++++++++++++++++----------------- libmysqld/lib_sql.cc | 2 + 2 files changed, 80 insertions(+), 52 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 545c2c9da1e..8623013bb02 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -615,7 +615,7 @@ void replace_strings_append(struct st_replace *rep, DYNAMIC_STRING* ds, const char *from); ATTRIBUTE_NORETURN -static void cleanup_and_exit(int exit_code); +static void cleanup_and_exit(int exit_code, bool called_from_die); ATTRIBUTE_NORETURN static void really_die(const char *msg); @@ -932,6 +932,7 @@ pthread_attr_t cn_thd_attrib; pthread_handler_t connection_thread(void *arg) { struct st_connection *cn= (struct st_connection*)arg; + DBUG_ENTER("connection_thread"); mysql_thread_init(); while (cn->command != EMB_END_CONNECTION) @@ -943,6 +944,7 @@ pthread_handler_t connection_thread(void *arg) pthread_cond_wait(&cn->query_cond, &cn->query_mutex); pthread_mutex_unlock(&cn->query_mutex); } + DBUG_PRINT("info", ("executing command: %d", cn->command)); switch (cn->command) { case EMB_END_CONNECTION: @@ -963,24 +965,26 @@ pthread_handler_t connection_thread(void *arg) break; case EMB_CLOSE_STMT: cn->result= mysql_stmt_close(cn->stmt); + cn->stmt= 0; break; default: DBUG_ASSERT(0); } - cn->command= 0; pthread_mutex_lock(&cn->result_mutex); cn->query_done= 1; + cn->command= 0; pthread_cond_signal(&cn->result_cond); pthread_mutex_unlock(&cn->result_mutex); } end_thread: - cn->query_done= 1; + DBUG_ASSERT(cn->stmt == 0); mysql_close(cn->mysql); cn->mysql= 0; + cn->query_done= 1; mysql_thread_end(); pthread_exit(0); - return 0; + DBUG_RETURN(0); } static void wait_query_thread_done(struct st_connection *con) @@ -998,12 +1002,16 @@ static void wait_query_thread_done(struct st_connection *con) static void signal_connection_thd(struct st_connection *cn, int command) { + DBUG_ENTER("signal_connection_thd"); + DBUG_PRINT("enter", ("command: %d", command)); + DBUG_ASSERT(cn->has_thread); cn->query_done= 0; - cn->command= command; pthread_mutex_lock(&cn->query_mutex); + cn->command= command; pthread_cond_signal(&cn->query_cond); pthread_mutex_unlock(&cn->query_mutex); + DBUG_VOID_RETURN; } @@ -1068,27 +1076,37 @@ static int do_stmt_execute(struct st_connection *cn) static int do_stmt_close(struct st_connection *cn) { DBUG_ENTER("do_stmt_close"); - /* The cn->stmt is already set. */ if (!cn->has_thread) - DBUG_RETURN(mysql_stmt_close(cn->stmt)); + { + /* The cn->stmt is already set. */ + int res= mysql_stmt_close(cn->stmt); + cn->stmt= 0; + DBUG_RETURN(res); + } + wait_query_thread_done(cn); signal_connection_thd(cn, EMB_CLOSE_STMT); wait_query_thread_done(cn); + DBUG_ASSERT(cn->stmt == 0); DBUG_RETURN(cn->result); } static void emb_close_connection(struct st_connection *cn) { + DBUG_ENTER("emb_close_connection"); if (!cn->has_thread) - return; + DBUG_VOID_RETURN; wait_query_thread_done(cn); signal_connection_thd(cn, EMB_END_CONNECTION); pthread_join(cn->tid, NULL); cn->has_thread= FALSE; + DBUG_ASSERT(cn->mysql == 0); + DBUG_ASSERT(cn->stmt == 0); pthread_mutex_destroy(&cn->query_mutex); pthread_cond_destroy(&cn->query_cond); pthread_mutex_destroy(&cn->result_mutex); pthread_cond_destroy(&cn->result_cond); + DBUG_VOID_RETURN; } @@ -1112,7 +1130,13 @@ static void init_connection_thd(struct st_connection *cn) #define do_read_query_result(cn) mysql_read_query_result(cn->mysql) #define do_stmt_prepare(cn, q, q_len) mysql_stmt_prepare(cn->stmt, q, (ulong)q_len) #define do_stmt_execute(cn) mysql_stmt_execute(cn->stmt) -#define do_stmt_close(cn) mysql_stmt_close(cn->stmt) + +static int do_stmt_close(struct st_connection *cn) +{ + int res= mysql_stmt_close(cn->stmt); + cn->stmt= 0; + return res; +} #endif /*EMBEDDED_LIBRARY*/ @@ -1440,7 +1464,6 @@ void close_statements() { if (con->stmt) do_stmt_close(con); - con->stmt= 0; } DBUG_VOID_RETURN; } @@ -1512,7 +1535,8 @@ void ha_pre_shutdown(); #endif -ATTRIBUTE_NORETURN static void cleanup_and_exit(int exit_code) +ATTRIBUTE_NORETURN static void cleanup_and_exit(int exit_code, + bool called_from_die) { #ifdef EMBEDDED_LIBRARY if (server_initialized) @@ -1525,16 +1549,6 @@ ATTRIBUTE_NORETURN static void cleanup_and_exit(int exit_code) if (server_initialized) mysql_server_end(); - /* - mysqltest is fundamentally written in a way that makes impossible - to free all memory before exit (consider memory allocated - for frame local DYNAMIC_STRING's and die() invoked down the stack. - - We close stderr here to stop unavoidable safemalloc reports - from polluting the output. - */ - fclose(stderr); - my_end(my_end_arg); if (!silent) { @@ -1554,6 +1568,11 @@ ATTRIBUTE_NORETURN static void cleanup_and_exit(int exit_code) } } + /* + Report memory leaks, if not called from 'die()', as die() will not release + all memory. + */ + sf_leaking_memory= called_from_die; exit(exit_code); } @@ -1620,7 +1639,7 @@ static void really_die(const char *msg) second time, just exit */ if (dying) - cleanup_and_exit(1); + cleanup_and_exit(1, 1); dying= 1; log_file.show_tail(opt_tail_lines); @@ -1632,7 +1651,7 @@ static void really_die(const char *msg) if (cur_con && !cur_con->pending) show_warnings_before_error(cur_con->mysql); - cleanup_and_exit(1); + cleanup_and_exit(1, 1); } void report_or_die(const char *fmt, ...) @@ -1686,7 +1705,7 @@ void abort_not_supported_test(const char *fmt, ...) } va_end(args); - cleanup_and_exit(62); + cleanup_and_exit(62, 0); } @@ -2233,14 +2252,14 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) check_result RETURN VALUES - error - the function will not return - + 0 ok + 1 error */ -void check_result() +int check_result() { const char *mess= 0; - + int error= 1; DBUG_ENTER("check_result"); DBUG_ASSERT(result_file_name); DBUG_PRINT("enter", ("result_file_name: %s", result_file_name)); @@ -2248,7 +2267,10 @@ void check_result() switch (compare_files(log_file.file_name(), result_file_name)) { case RESULT_OK: if (!error_count) + { + error= 0; break; /* ok */ + } mess= "Got errors while running test"; /* Fallthrough */ case RESULT_LENGTH_MISMATCH: @@ -2287,14 +2309,13 @@ void check_result() log_file.file_name(), reject_file, errno); show_diff(NULL, result_file_name, reject_file); - die("%s", mess); + fprintf(stderr, "%s", mess); break; } default: /* impossible */ die("Unknown error code from dyn_string_cmp()"); } - - DBUG_VOID_RETURN; + DBUG_RETURN(error); } @@ -5643,7 +5664,6 @@ void do_close_connection(struct st_command *command) #endif /*!EMBEDDED_LIBRARY*/ if (con->stmt) do_stmt_close(con); - con->stmt= 0; #ifdef EMBEDDED_LIBRARY /* As query could be still executed in a separate thread @@ -7318,17 +7338,17 @@ get_one_option(const struct my_option *opt, const char *argument, const char *) break; case 'V': print_version(); - exit(0); + cleanup_and_exit(0,0); case OPT_MYSQL_PROTOCOL: #ifndef EMBEDDED_LIBRARY if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib, opt->name)) <= 0) - exit(1); + cleanup_and_exit(1,0); #endif break; case '?': usage(); - exit(0); + cleanup_and_exit(0,0); } return 0; } @@ -7340,12 +7360,12 @@ int parse_args(int argc, char **argv) default_argv= argv; if ((handle_options(&argc, &argv, my_long_options, get_one_option))) - exit(1); + cleanup_and_exit(1, 0); if (argc > 1) { usage(); - exit(1); + cleanup_and_exit(1, 0); } if (argc == 1) opt_db= *argv; @@ -8466,7 +8486,7 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, my_bool ds_res_1st_execution_init = FALSE; my_bool compare_2nd_execution = TRUE; int query_match_ps2_re; - + MYSQL_RES *res; DBUG_ENTER("run_query_stmt"); DBUG_PRINT("query", ("'%-.60s'", query)); DBUG_PRINT("info", @@ -8672,10 +8692,13 @@ void run_query_stmt(struct st_connection *cn, struct st_command *command, The --enable_prepare_warnings command can be used to change this so that warnings from both the prepare and execute phase are shown. */ - if ((mysql_stmt_result_metadata(stmt) != NULL) && - !disable_warnings && - !prepare_warnings_enabled) - dynstr_set(&ds_prepare_warnings, NULL); + if ((res= mysql_stmt_result_metadata(stmt))) + { + if (!disable_warnings && + !prepare_warnings_enabled) + dynstr_set(&ds_prepare_warnings, NULL); + mysql_free_result(res); + } /* Fetch info before fetching warnings, since it will be reset @@ -9802,6 +9825,7 @@ static sig_handler signal_handler(int sig) fflush(stderr); my_write_core(sig); #ifndef _WIN32 + sf_leaking_memory= 1; exit(1); // Shouldn't get here but just in case #endif } @@ -9875,12 +9899,10 @@ int main(int argc, char **argv) uint command_executed= 0, last_command_executed= 0; char save_file[FN_REFLEN]; bool empty_result= FALSE; + int error= 0; MY_INIT(argv[0]); DBUG_ENTER("main"); - /* mysqltest has no way to free all its memory correctly */ - sf_leaking_memory= 1; - save_file[0]= 0; TMPDIR[0]= 0; @@ -10577,7 +10599,7 @@ int main(int argc, char **argv) die("Test ended with parsing disabled"); /* - The whole test has been executed _successfully_. + The whole test has been executed successfully. Time to compare result or save it to record file. The entire output from test is in the log file */ @@ -10600,7 +10622,7 @@ int main(int argc, char **argv) else { /* Check that the output from test is equal to result file */ - check_result(); + error= check_result(); } } } @@ -10610,7 +10632,8 @@ int main(int argc, char **argv) if (! result_file_name || record || compare_files (log_file.file_name(), result_file_name)) { - die("The test didn't produce any output"); + fprintf(stderr, "mysqltest: The test didn't produce any output\n"); + error= 1; } else { @@ -10619,12 +10642,15 @@ int main(int argc, char **argv) } if (!command_executed && result_file_name && !empty_result) - die("No queries executed but non-empty result file found!"); + { + fprintf(stderr, "mysqltest: No queries executed but non-empty result file found!\n"); + error= 1; + } - verbose_msg("Test has succeeded!"); + if (!error) + verbose_msg("Test has succeeded!"); timer_output(); - /* Yes, if we got this far the test has succeeded! Sakila smiles */ - cleanup_and_exit(0); + cleanup_and_exit(error, 0); return 0; /* Keep compiler happy too */ } diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 8067ee5bd0c..bbc08d26b89 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -269,6 +269,7 @@ static my_bool emb_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) mysql->server_status|= SERVER_STATUS_IN_TRANS; stmt->fields= mysql->fields; + free_root(&stmt->mem_root, MYF(0)); stmt->mem_root= res->alloc; mysql->fields= NULL; my_free(res); @@ -378,6 +379,7 @@ int emb_read_binary_rows(MYSQL_STMT *stmt) set_stmt_errmsg(stmt, &stmt->mysql->net); return 1; } + free_root(&stmt->result.alloc, MYF(0)); stmt->result= *data; my_free(data); set_stmt_errmsg(stmt, &stmt->mysql->net); From 8b3f470c0bdf183b26cb2b06a9ae416aa7f16b04 Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 1 Mar 2024 11:21:50 +0200 Subject: [PATCH 040/106] Fixed random failure in main.kill_processlist-6619 The problem was that SHOW PROCESSLIST was done before the command of the default connection was cleared. Reviewer: Sergei Golubchik --- mysql-test/main/kill_processlist-6619.result | 6 ++++++ mysql-test/main/kill_processlist-6619.test | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/mysql-test/main/kill_processlist-6619.result b/mysql-test/main/kill_processlist-6619.result index 7dd42790cc7..25831a1f63b 100644 --- a/mysql-test/main/kill_processlist-6619.result +++ b/mysql-test/main/kill_processlist-6619.result @@ -1,4 +1,8 @@ +SET DEBUG_SYNC='dispatch_command_end SIGNAL ready WAIT_FOR go'; +select 1; connect con1,localhost,root,,; +SET DEBUG_SYNC='now wait_for ready'; +SET DEBUG_SYNC='now signal go'; SHOW PROCESSLIST; Id User Host db Command Time State Info Progress # root # test Sleep # # NULL 0.000 @@ -6,6 +10,8 @@ Id User Host db Command Time State Info Progress SET DEBUG_SYNC='before_execute_sql_command SIGNAL ready WAIT_FOR go'; SHOW PROCESSLIST; connection default; +1 +1 SET DEBUG_SYNC='now WAIT_FOR ready'; KILL QUERY con_id; SET DEBUG_SYNC='now SIGNAL go'; diff --git a/mysql-test/main/kill_processlist-6619.test b/mysql-test/main/kill_processlist-6619.test index c272e68a877..7330c79acd8 100644 --- a/mysql-test/main/kill_processlist-6619.test +++ b/mysql-test/main/kill_processlist-6619.test @@ -4,7 +4,14 @@ --source include/not_embedded.inc --source include/have_debug_sync.inc +# This is to ensure that the following SHOW PROCESSLIST does not show the query +SET DEBUG_SYNC='dispatch_command_end SIGNAL ready WAIT_FOR go'; +--send select 1 + --connect (con1,localhost,root,,) +SET DEBUG_SYNC='now wait_for ready'; +SET DEBUG_SYNC='now signal go'; + --let $con_id = `SELECT CONNECTION_ID()` --replace_result Execute Query --replace_column 1 # 3 # 6 # 7 # @@ -12,6 +19,8 @@ SHOW PROCESSLIST; SET DEBUG_SYNC='before_execute_sql_command SIGNAL ready WAIT_FOR go'; send SHOW PROCESSLIST; --connection default +--reap + # We must wait for the SHOW PROCESSLIST query to have started before sending # the kill. Otherwise, the KILL may be lost since it is reset at the start of # query execution. From b93252a3036aec8fa6ce0ac0c7c9c19abc4b0942 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Fri, 15 Dec 2023 00:48:48 +0400 Subject: [PATCH 041/106] MDEV-32454 JSON test has problem in view protocol. Few Item_func_json_xxx::fix_length_and_dec() functions fixed. --- mysql-test/main/func_json.result | 2 +- mysql-test/main/func_json.test | 19 --------- mysql-test/suite/json/r/json_no_table.result | 2 +- sql/item_jsonfunc.cc | 41 ++++++++++++++++++-- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/mysql-test/main/func_json.result b/mysql-test/main/func_json.result index 5d80ad2a7fc..da8875b06b5 100644 --- a/mysql-test/main/func_json.result +++ b/mysql-test/main/func_json.result @@ -272,7 +272,7 @@ create table t1 as select json_object('id', 87, 'name', 'carrot') as f; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `f` varchar(32) DEFAULT NULL + `f` varchar(46) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci select * from t1; f diff --git a/mysql-test/main/func_json.test b/mysql-test/main/func_json.test index a271dac3dca..8d06b786ba9 100644 --- a/mysql-test/main/func_json.test +++ b/mysql-test/main/func_json.test @@ -87,15 +87,12 @@ select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]') as exp; select json_extract('[10, 20, [30, 40], 1, 10]', '$[1]', '$[25]') as exp; select json_extract( '[{"a": [3, 4]}, {"b": 2}]', '$[0].a', '$[1].a') as exp; -#enable after MDEV-32454 fix ---disable_view_protocol select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.k1', 'word') as exp; select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.d[3]', 3) as exp; select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.a[2]', 2) as exp; select json_insert('{"a":1, "b":{"c":1}, "d":[1, 2]}', '$.b.c', 'word') as exp; select json_set('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]') as exp; ---enable_view_protocol select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.c', '[true, false]') as exp; select json_replace('{ "a": 1, "b": [2, 3]}', '$.a', 10, '$.b', '[true, false]') as exp; @@ -137,14 +134,11 @@ select json_merge('a','b'); select json_merge('{"a":"b"}','{"c":"d"}'); SELECT JSON_MERGE('[1, 2]', '{"id": 47}'); -#enable after MDEV-32454 fix ---disable_view_protocol select json_type('{"k1":123, "k2":345}'); select json_type('[123, "k2", 345]'); select json_type("true"); select json_type('123'); select json_type('123.12'); ---enable_view_protocol select json_keys('{"a":{"c":1, "d":2}, "b":2}'); select json_keys('{"a":{"c":1, "d":2}, "b":2}', "$.a"); @@ -173,11 +167,8 @@ select json_search( json_col, 'all', 'foot' ) as ex from t1; drop table t1; -#enable after MDEV-32454 fix ---disable_view_protocol select json_unquote('"abc"'); select json_unquote('abc'); ---enable_view_protocol # # MDEV-13703 Illegal mix of collations for operation 'json_object' on using JSON_UNQUOTE as an argument. # @@ -188,13 +179,9 @@ select json_object('foo', json_unquote(json_object('bar', c)),'qux', c) as fld f drop table t1; -#enable after MDEV-32454 fix ---disable_view_protocol select json_object("a", json_object("b", "abcd")); select json_object("a", '{"b": "abcd"}'); select json_object("a", json_compact('{"b": "abcd"}')); ---enable_view_protocol - select json_compact(NULL); select json_depth(json_compact(NULL)); @@ -270,11 +257,8 @@ select json_merge('{"a":{"u":12, "x":"b"}}', '{"a":{"x":"c"}}') as ex ; select json_merge('{"a":{"u":12, "x":"b", "r":1}}', '{"a":{"x":"c", "r":2}}') as ex ; select json_compact('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') as ex; -#enable after MDEV-32454 fix ---disable_view_protocol select json_loose('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') as ex; select json_detailed('{"a":1, "b":[1,2,3], "c":{"aa":"v1", "bb": "v2"}}') as ex; ---enable_view_protocol # # MDEV-11856 json_search doesn't search for values with double quotes character (") @@ -466,12 +450,9 @@ drop table t1; --echo # MDEV-16750 JSON_SET mishandles unicode every second pair of arguments. --echo # -#enable after MDEV-32454 fix ---disable_view_protocol SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6) as exp; SELECT JSON_SET('{}', '$.a', _utf8 0xC3B6, '$.b', _utf8 0xC3B6) as exp; SELECT JSON_SET('{}', '$.a', _utf8 X'C3B6', '$.x', 1, '$.b', _utf8 X'C3B6') as exp; ---enable_view_protocol --echo # --echo # MDEV-17121 JSON_ARRAY_APPEND diff --git a/mysql-test/suite/json/r/json_no_table.result b/mysql-test/suite/json/r/json_no_table.result index 6a33e3cf83b..bb3b9d2ab1e 100644 --- a/mysql-test/suite/json/r/json_no_table.result +++ b/mysql-test/suite/json/r/json_no_table.result @@ -3338,7 +3338,7 @@ OBJECT CREATE VIEW v1 AS SELECT JSON_TYPE(JSON_OBJECT()); SELECT * FROM v1; JSON_TYPE(JSON_OBJECT()) -OBJE +OBJECT drop view v1; # # Bug#21198333 SIG 6 IN ITEM_CACHE_JSON::CACHE_VALUE AT SQL/ITEM.CC:9470 diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 6b96f46e082..b0a792e94b9 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -761,7 +761,7 @@ bool Item_func_json_unquote::fix_length_and_dec() { collation.set(&my_charset_utf8_general_ci, DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); - max_length= args[0]->max_length; + max_length= args[0]->max_char_length() * collation.collation->mbmaxlen; maybe_null= 1; return FALSE; } @@ -1730,7 +1730,22 @@ bool Item_func_json_array::fix_length_and_dec() return TRUE; for (n_arg=0 ; n_arg < arg_count ; n_arg++) - char_length+= args[n_arg]->max_char_length() + 4; + { + ulonglong arg_length; + Item *arg= args[n_arg]; + + if (!arg->is_json_type() && arg->result_type() == STRING_RESULT) + arg_length= arg->max_char_length() * 2; /*escaping possible */ + else if (arg->type_handler()->is_bool_type()) + arg_length= 5; + else + arg_length= arg->max_char_length(); + + if (arg_length < 4) + arg_length= 4; /* can be 'null' */ + + char_length+= arg_length + 4; + } fix_char_length_ulonglong(char_length); tmp_val.set_charset(collation.collation); @@ -2874,7 +2889,7 @@ longlong Item_func_json_depth::val_int() bool Item_func_json_type::fix_length_and_dec() { collation.set(&my_charset_utf8_general_ci); - max_length= 12; + max_length= 12 * collation.collation->mbmaxlen; maybe_null= 1; return FALSE; } @@ -2940,6 +2955,11 @@ bool Item_func_json_insert::fix_length_and_dec() for (n_arg= 1; n_arg < arg_count; n_arg+= 2) { paths[n_arg/2].set_constant_flag(args[n_arg]->const_item()); + /* + In the resulting JSON we can insert the property + name from the path, and the value itself. + */ + char_length+= args[n_arg/2]->max_char_length() + 6; char_length+= args[n_arg/2+1]->max_char_length() + 4; } @@ -3749,7 +3769,20 @@ bool Item_func_json_format::fix_length_and_dec() { decimals= 0; collation.set(args[0]->collation); - max_length= args[0]->max_length; + switch (fmt) + { + case COMPACT: + max_length= args[0]->max_length; + break; + case LOOSE: + max_length= args[0]->max_length * 2; + break; + case DETAILED: + max_length= MAX_BLOB_WIDTH; + break; + default: + DBUG_ASSERT(0); + }; maybe_null= 1; return FALSE; } From d37c51b8053344b52fd9c539c3964070a9c0b307 Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Tue, 20 Feb 2024 11:20:21 +1100 Subject: [PATCH 042/106] MDEV-33494 fix spider init with no_zero_date global sql mode Like the fix for MDEV-32753 and MDEV-33242, spider init queries creates new connections that use the global sql_mode of the existing connection. --- .../mysql-test/spider/bugfix/r/mdev_33494.result | 4 ++++ .../spider/mysql-test/spider/bugfix/t/mdev_33494.test | 11 +++++++++++ storage/spider/spd_init_query.h | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 storage/spider/mysql-test/spider/bugfix/r/mdev_33494.result create mode 100644 storage/spider/mysql-test/spider/bugfix/t/mdev_33494.test diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_33494.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_33494.result new file mode 100644 index 00000000000..3db28c0f08e --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_33494.result @@ -0,0 +1,4 @@ +set @old_sql_mode=@@global.sql_mode; +set global sql_mode=(SELECT CONCAT (@@sql_mode,',no_zero_date')); +install soname 'ha_spider'; +set global sql_mode=@old_sql_mode; diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_33494.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_33494.test new file mode 100644 index 00000000000..30beca77f35 --- /dev/null +++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_33494.test @@ -0,0 +1,11 @@ +# This test tests spider init with global no_zero_date sql mode +set @old_sql_mode=@@global.sql_mode; +set global sql_mode=(SELECT CONCAT (@@sql_mode,',no_zero_date')); +install soname 'ha_spider'; +set global sql_mode=@old_sql_mode; + +--disable_query_log +--disable_result_log +--source ../../include/clean_up_spider.inc +--enable_result_log +--enable_query_log diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h index cf41e47f890..83f1968f8b2 100644 --- a/storage/spider/spd_init_query.h +++ b/storage/spider/spd_init_query.h @@ -21,7 +21,7 @@ static LEX_STRING spider_init_queries[] = { {C_STRING_WITH_LEN( - "SET @@SQL_MODE = REPLACE(@@SQL_MODE, 'ORACLE', '');" + "SET @@SQL_MODE = REGEXP_REPLACE(@@SQL_MODE, '(ORACLE|NO_ZERO_DATE)', '');" )}, {C_STRING_WITH_LEN( "create table if not exists mysql.spider_xa(" From 1b568fb917e98e5bb2e1387fcfb63de2d10c652b Mon Sep 17 00:00:00 2001 From: Yuchen Pei Date: Mon, 26 Feb 2024 15:00:54 +1100 Subject: [PATCH 043/106] MDEV-33539 spider: remove some unused code in self reference checks --- storage/spider/spd_db_conn.cc | 8 --- storage/spider/spd_db_include.cc | 16 ----- storage/spider/spd_db_include.h | 4 -- storage/spider/spd_db_mysql.cc | 109 ------------------------------- storage/spider/spd_db_mysql.h | 5 -- storage/spider/spd_include.h | 1 - 6 files changed, 143 deletions(-) diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index 6bfc63a3813..37dbfb75aaa 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -378,7 +378,6 @@ int spider_db_conn_queue_action( ) || ( conn->loop_check_queue.records && - conn->db_conn->set_loop_check_in_bulk_sql() && (error_num = spider_dbton[conn->dbton_id].db_util-> append_loop_check(&sql_str, conn)) ) || @@ -477,13 +476,6 @@ int spider_db_conn_queue_action( ) { DBUG_RETURN(error_num); } - if ( - conn->loop_check_queue.records && - !conn->db_conn->set_loop_check_in_bulk_sql() && - (error_num = conn->db_conn->set_loop_check((int *) conn->need_mon)) - ) { - DBUG_RETURN(error_num); - } if ( conn->queued_trx_isolation && !conn->queued_semi_trx_isolation && diff --git a/storage/spider/spd_db_include.cc b/storage/spider/spd_db_include.cc index b9a0532d1b9..d74ad444179 100644 --- a/storage/spider/spd_db_include.cc +++ b/storage/spider/spd_db_include.cc @@ -71,22 +71,6 @@ spider_db_conn::spider_db_conn( DBUG_VOID_RETURN; } -bool spider_db_conn::set_loop_check_in_bulk_sql() -{ - DBUG_ENTER("spider_db_conn::set_loop_check_in_bulk_sql"); - DBUG_PRINT("info",("spider this=%p", this)); - DBUG_RETURN(FALSE); -} - -int spider_db_conn::set_loop_check( - int *need_mon -) { - DBUG_ENTER("spider_db_conn::set_loop_check"); - DBUG_PRINT("info",("spider this=%p", this)); - /* nothing to do */ - DBUG_RETURN(0); -} - int spider_db_conn::fin_loop_check() { st_spider_conn_loop_check *lcptr; diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h index 4fecad86063..8ecdb4ff425 100644 --- a/storage/spider/spd_db_include.h +++ b/storage/spider/spd_db_include.h @@ -1170,10 +1170,6 @@ public: Time_zone *time_zone, int *need_mon ) = 0; - virtual bool set_loop_check_in_bulk_sql(); - virtual int set_loop_check( - int *need_mon - ); virtual int fin_loop_check(); virtual int show_master_status( SPIDER_TRX *trx, diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index e184040c69f..cd88e187dfd 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -3352,115 +3352,6 @@ int spider_db_mbase::set_time_zone( DBUG_RETURN(0); } -bool spider_db_mbase::set_loop_check_in_bulk_sql() -{ - DBUG_ENTER("spider_db_mbase::set_loop_check_in_bulk_sql"); - DBUG_PRINT("info",("spider this=%p", this)); - DBUG_RETURN(TRUE); -} - -int spider_db_mbase::set_loop_check( - int *need_mon -) { - SPIDER_CONN_LOOP_CHECK *lcptr; - char sql_buf[MAX_FIELD_WIDTH]; - spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin); - DBUG_ENTER("spider_db_mbase::set_loop_check"); - DBUG_PRINT("info",("spider this=%p", this)); - sql_str.init_calc_mem(SPD_MID_DB_MBASE_SET_LOOP_CHECK_1); - while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( - &conn->loop_check_queue, 0))) - { - sql_str.length(0); - if (sql_str.reserve(SPIDER_SQL_SET_USER_VAL_LEN + - SPIDER_SQL_LOP_CHK_PRM_PRF_LEN + lcptr->to_name.length + - SPIDER_SQL_NAME_QUOTE_LEN + SPIDER_SQL_EQUAL_LEN + - SPIDER_SQL_VALUE_QUOTE_LEN + - lcptr->merged_value.length + SPIDER_SQL_VALUE_QUOTE_LEN)) - { - DBUG_RETURN(HA_ERR_OUT_OF_MEM); - } - sql_str.q_append(SPIDER_SQL_SET_USER_VAL_STR, SPIDER_SQL_SET_USER_VAL_LEN); - sql_str.q_append(SPIDER_SQL_LOP_CHK_PRM_PRF_STR, - SPIDER_SQL_LOP_CHK_PRM_PRF_LEN); - sql_str.q_append(lcptr->to_name.str, lcptr->to_name.length); - sql_str.q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN); - sql_str.q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN); - sql_str.q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); - sql_str.q_append(lcptr->merged_value.str, lcptr->merged_value.length); - sql_str.q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN); - - pthread_mutex_assert_not_owner(&conn->mta_conn_mutex); - pthread_mutex_lock(&conn->mta_conn_mutex); - SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos); - conn->need_mon = need_mon; - DBUG_ASSERT(!conn->mta_conn_mutex_lock_already); - DBUG_ASSERT(!conn->mta_conn_mutex_unlock_later); - conn->mta_conn_mutex_lock_already = TRUE; - conn->mta_conn_mutex_unlock_later = TRUE; - if (spider_db_query( - conn, - sql_str.ptr(), - sql_str.length(), - -1, - need_mon) - ) { - DBUG_ASSERT(conn->mta_conn_mutex_lock_already); - DBUG_ASSERT(conn->mta_conn_mutex_unlock_later); - conn->mta_conn_mutex_lock_already = FALSE; - conn->mta_conn_mutex_unlock_later = FALSE; - DBUG_RETURN(spider_db_errorno(conn)); - } - DBUG_ASSERT(conn->mta_conn_mutex_lock_already); - DBUG_ASSERT(conn->mta_conn_mutex_unlock_later); - conn->mta_conn_mutex_lock_already = FALSE; - conn->mta_conn_mutex_unlock_later = FALSE; - SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos); - pthread_mutex_unlock(&conn->mta_conn_mutex); - -#ifdef HASH_UPDATE_WITH_HASH_VALUE - my_hash_delete_with_hash_value(&conn->loop_check_queue, - lcptr->hash_value, (uchar *) lcptr); -#else - my_hash_delete(&conn->loop_check_queue, (uchar*) lcptr); -#endif - } - DBUG_RETURN(0); -} - -int spider_db_mbase::fin_loop_check() -{ - st_spider_conn_loop_check *lcptr; - DBUG_ENTER("spider_db_mbase::fin_loop_check"); - DBUG_PRINT("info",("spider this=%p", this)); - if (conn->loop_check_queue.records) - { - uint l = 0; - while ((lcptr = (SPIDER_CONN_LOOP_CHECK *) my_hash_element( - &conn->loop_check_queue, l))) - { - lcptr->flag = 0; - ++l; - } - my_hash_reset(&conn->loop_check_queue); - } - lcptr = conn->loop_check_ignored_first; - while (lcptr) - { - lcptr->flag = 0; - lcptr = lcptr->next; - } - conn->loop_check_ignored_first = NULL; - lcptr = conn->loop_check_meraged_first; - while (lcptr) - { - lcptr->flag = 0; - lcptr = lcptr->next; - } - conn->loop_check_meraged_first = NULL; - DBUG_RETURN(0); -} - int spider_db_mbase::exec_simple_sql_with_result( SPIDER_TRX *trx, SPIDER_SHARE *share, diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h index 67d6fabcc2f..9e4d0e8f261 100644 --- a/storage/spider/spd_db_mysql.h +++ b/storage/spider/spd_db_mysql.h @@ -527,11 +527,6 @@ public: Time_zone *time_zone, int *need_mon ); - bool set_loop_check_in_bulk_sql(); - int set_loop_check( - int *need_mon - ); - int fin_loop_check(); int exec_simple_sql_with_result( SPIDER_TRX *trx, SPIDER_SHARE *share, diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h index e2ee47884e3..519ae03a5b6 100644 --- a/storage/spider/spd_include.h +++ b/storage/spider/spd_include.h @@ -377,7 +377,6 @@ enum spider_malloc_id { SPD_MID_DB_MBASE_RESULT_FETCH_ROW_FROM_TMP_TABLE_3, SPD_MID_DB_MBASE_ROW_APPEND_ESCAPED_TO_STR_1, SPD_MID_DB_MBASE_ROW_CLONE_1, - SPD_MID_DB_MBASE_SET_LOOP_CHECK_1, SPD_MID_DB_MBASE_SET_SQL_MODE_1, SPD_MID_DB_MBASE_SET_TIME_ZONE_1, SPD_MID_DB_MBASE_SET_WAIT_TIMEOUT_1, From 48f42ab2e59a045c394e19238067c5e938008d3e Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 28 Feb 2024 12:37:20 +0300 Subject: [PATCH 044/106] Fix comment. --- sql/sql_class.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_class.h b/sql/sql_class.h index 4c6005416e1..6fa72b231d2 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -714,7 +714,7 @@ typedef struct system_variables ulonglong max_mem_used; /* A bitmap of OPTIMIZER_ADJ_* flags (defined in sql_priv.h). - See sql_vars.cc:adjust_secondary_key_cost for symbolic names. + See sys_vars.cc:adjust_secondary_key_cost for symbolic names. */ ulonglong optimizer_adjust_secondary_key_costs; From 567c0973591eb66797bb0f982f312b516f8fe82c Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 1 Mar 2024 18:16:33 +0200 Subject: [PATCH 045/106] MDEV-33582 Add more warnings to be able to better diagnose network issues Warnings are added to net_server.cc when global_system_variables.log_warnings >= 4. When the above condition holds then: - All communication errors from net_serv.cc is also written to the error log. - In case of a of not being able to read or write a packet, a more detailed error is given. Other things: - Added detection of slaves that has hangup to Ack_receiver::run() - vio_close() is now first marking the socket closed before closing it. The reason for this is to ensure that the connection that gets a read error can check if the reason was that the socket was closed. - Add a new state to vio to be able to detect if vio is acive, shutdown or closed. This is used to detect if socket is closed by another thread. - Testing of the new warnings is done in rpl_get_lock.test - Suppress some of the new warnings in mtr to allow one to run some of the tests with -mysqld=--log-warnings=4. All test in the 'rpl' suite can now be run with this option. - Ensure that global.log_warnings are restored at test end in a way that allows one to use mtr --mysqld=--log-warnings=4. Reviewed-by: , --- include/my_global.h | 2 + include/violite.h | 8 +++ mysql-test/mariadb-test-run.pl | 7 ++ .../suite/binlog_encryption/rpl_packet.result | 2 + .../rpl/include/rpl_extra_col_master.test | 4 ++ ...l_binlog_dump_slave_gtid_state_info.result | 3 +- .../rpl_domain_id_filter_master_crash.result | 3 - mysql-test/suite/rpl/r/rpl_get_lock.result | 3 +- mysql-test/suite/rpl/r/rpl_gtid_crash.result | 1 + .../suite/rpl/r/rpl_gtid_grouping.result | 1 - .../suite/rpl/r/rpl_heartbeat_debug.result | 2 - mysql-test/suite/rpl/r/rpl_packet.result | 2 + .../rpl/r/rpl_parallel_optimistic.result | 3 +- .../rpl/r/rpl_parallel_optimistic_xa.result | 1 - .../rpl_parallel_optimistic_xa_lsu_off.result | 1 - .../suite/rpl/r/rpl_row_find_row_debug.result | 1 - ..._semi_sync_slave_enabled_consistent.result | 2 + .../r/show_status_stop_slave_race-7126.result | 1 - ...rpl_binlog_dump_slave_gtid_state_info.test | 3 +- .../t/rpl_domain_id_filter_master_crash.test | 3 + .../rpl/t/rpl_dump_request_retry_warning.test | 4 ++ mysql-test/suite/rpl/t/rpl_get_lock.test | 14 ++++ mysql-test/suite/rpl/t/rpl_gtid_crash.test | 1 + .../suite/rpl/t/rpl_gtid_crash_myisam.test | 4 ++ mysql-test/suite/rpl/t/rpl_gtid_grouping.test | 1 - .../suite/rpl/t/rpl_heartbeat_debug.test | 11 ++- mysql-test/suite/rpl/t/rpl_packet.test | 3 + .../suite/rpl/t/rpl_parallel_optimistic.test | 3 +- .../rpl/t/rpl_parallel_optimistic_xa.test | 1 - .../suite/rpl/t/rpl_row_find_row_debug.test | 2 + .../suite/rpl/t/rpl_semi_sync_fail_over.test | 5 ++ .../t/rpl_semi_sync_shutdown_await_ack.cnf | 6 +- ...pl_semi_sync_slave_enabled_consistent.test | 3 +- .../t/show_status_stop_slave_race-7126.test | 3 + sql/net_serv.cc | 51 ++++++++++--- sql/semisync_master_ack_receiver.cc | 13 +++- sql/semisync_master_ack_receiver.h | 10 +++ sql/slave.cc | 2 + vio/vio.c | 2 + vio/viosocket.c | 72 +++++++++++++------ 40 files changed, 211 insertions(+), 53 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index e89249ec890..d6af6e8b938 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -962,6 +962,7 @@ typedef struct st_mysql_lex_string LEX_STRING; #define SOCKET_ECONNRESET WSAECONNRESET #define SOCKET_ENFILE ENFILE #define SOCKET_EMFILE EMFILE +#define SOCKET_CLOSED EIO #else /* Unix */ #define socket_errno errno #define closesocket(A) close(A) @@ -971,6 +972,7 @@ typedef struct st_mysql_lex_string LEX_STRING; #define SOCKET_EADDRINUSE EADDRINUSE #define SOCKET_ETIMEDOUT ETIMEDOUT #define SOCKET_ECONNRESET ECONNRESET +#define SOCKET_CLOSED EIO #define SOCKET_ENFILE ENFILE #define SOCKET_EMFILE EMFILE #endif diff --git a/include/violite.h b/include/violite.h index b823e62b2e1..f1e5c95a648 100644 --- a/include/violite.h +++ b/include/violite.h @@ -41,6 +41,13 @@ enum enum_vio_type VIO_TYPE_SSL /* see also vio_type_names[] */ }; + +enum enum_vio_state +{ + VIO_STATE_NOT_INITIALIZED, VIO_STATE_ACTIVE, VIO_STATE_SHUTDOWN, + VIO_STATE_CLOSED +}; + #define FIRST_VIO_TYPE VIO_CLOSED #define LAST_VIO_TYPE VIO_TYPE_SSL @@ -244,6 +251,7 @@ struct st_vio struct sockaddr_storage local; /* Local internet address */ struct sockaddr_storage remote; /* Remote internet address */ enum enum_vio_type type; /* Type of connection */ + enum enum_vio_state state; /* State of the connection */ const char *desc; /* String description */ char *read_buffer; /* buffer for vio_read_buff */ char *read_pos; /* start of unfetched data in the diff --git a/mysql-test/mariadb-test-run.pl b/mysql-test/mariadb-test-run.pl index 4b3d323760d..d1124724e73 100755 --- a/mysql-test/mariadb-test-run.pl +++ b/mysql-test/mariadb-test-run.pl @@ -4486,6 +4486,13 @@ sub extract_warning_lines ($$) { qr/Slave I\/0: Master command COM_BINLOG_DUMP failed/, qr/Error reading packet/, qr/Lost connection to MariaDB server at 'reading initial communication packet'/, + qr/Could not read packet:.* state: [2-3] /, + qr/Could not read packet:.* errno: 104 /, + qr/Could not read packet:.* errno: 0 .* length: 0/, + qr/Could not write packet:.* errno: 32 /, + qr/Could not write packet:.* errno: 104 /, + qr/Semisync ack receiver got error 1158/, + qr/Connection was killed/, qr/Failed on request_dump/, qr/Slave: Can't drop database.* database doesn't exist/, qr/Slave: Operation DROP USER failed for 'create_rout_db'/, diff --git a/mysql-test/suite/binlog_encryption/rpl_packet.result b/mysql-test/suite/binlog_encryption/rpl_packet.result index 4a2a5d70d39..bb6269607fe 100644 --- a/mysql-test/suite/binlog_encryption/rpl_packet.result +++ b/mysql-test/suite/binlog_encryption/rpl_packet.result @@ -2,6 +2,8 @@ include/master-slave.inc [connection master] call mtr.add_suppression("Slave I/O: Got a packet bigger than 'slave_max_allowed_packet' bytes, .*error.* 1153"); call mtr.add_suppression("Log entry on master is longer than slave_max_allowed_packet"); +call mtr.add_suppression("Could not write packet:"); +call mtr.add_suppression("Got a packet bigger than 'max_allowed_packet' bytes"); drop database if exists DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; create database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; connection master; diff --git a/mysql-test/suite/rpl/include/rpl_extra_col_master.test b/mysql-test/suite/rpl/include/rpl_extra_col_master.test index 02645a577f5..512118f91cd 100644 --- a/mysql-test/suite/rpl/include/rpl_extra_col_master.test +++ b/mysql-test/suite/rpl/include/rpl_extra_col_master.test @@ -59,6 +59,10 @@ #VARCHAR(M) # +--disable_query_log +call mtr.add_suppression("Could not read packet:.* errno: 11"); +--enable_query_log + --let $_saved_conn= $CURRENT_CONNECTION let $binformat = `SHOW VARIABLES LIKE '%binlog_format%'`; diff --git a/mysql-test/suite/rpl/r/rpl_binlog_dump_slave_gtid_state_info.result b/mysql-test/suite/rpl/r/rpl_binlog_dump_slave_gtid_state_info.result index 38a9afd4d02..a8c70ef4953 100644 --- a/mysql-test/suite/rpl/r/rpl_binlog_dump_slave_gtid_state_info.result +++ b/mysql-test/suite/rpl/r/rpl_binlog_dump_slave_gtid_state_info.result @@ -1,6 +1,7 @@ include/master-slave.inc [connection master] connection master; +SET @org_log_warnings=@@GLOBAL.LOG_WARNINGS; SET GLOBAL LOG_WARNINGS=2; connection slave; include/stop_slave.inc @@ -41,11 +42,11 @@ connection master; include/wait_for_pattern_in_file.inc FOUND 1 /using_gtid\(1\), gtid\(\'0-1-2,10-1-1\'\).*/ in mysqld.1.err "===== Clean up =====" +SET GLOBAL LOG_WARNINGS=@org_log_warnings; connection slave; include/stop_slave.inc CHANGE MASTER TO MASTER_USE_GTID=no; include/start_slave.inc connection master; DROP TABLE t; -SET GLOBAL LOG_WARNINGS=default; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result b/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result index a54ff99b591..cd13590b61f 100644 --- a/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result +++ b/mysql-test/suite/rpl/r/rpl_domain_id_filter_master_crash.result @@ -1,9 +1,6 @@ include/master-slave.inc [connection master] connection master; -call mtr.add_suppression("mysqld: Table '.*gtid_slave_pos' is marked as crashed and should be repaired"); -call mtr.add_suppression("Checking table: './mysql/gtid_slave_pos'"); -call mtr.add_suppression("mysql.gtid_slave_pos: 1 client is using or hasn't closed the table properly"); SET @@session.gtid_domain_id= 0; create table ti (a int auto_increment primary key) engine=innodb; create table tm (a int auto_increment primary key) engine=myisam; diff --git a/mysql-test/suite/rpl/r/rpl_get_lock.result b/mysql-test/suite/rpl/r/rpl_get_lock.result index b852546e1bf..cbb02a32648 100644 --- a/mysql-test/suite/rpl/r/rpl_get_lock.result +++ b/mysql-test/suite/rpl/r/rpl_get_lock.result @@ -1,6 +1,6 @@ include/master-slave.inc [connection master] -CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +SET GLOBAL LOG_WARNINGS=4; create table t1(n int); insert into t1 values(get_lock("lock",2)); disconnect master; @@ -35,4 +35,5 @@ NULL connection master1; drop table t1; connection slave; +connection default; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_gtid_crash.result b/mysql-test/suite/rpl/r/rpl_gtid_crash.result index 4e74a3b25ac..36b0452bc50 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_crash.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_crash.result @@ -4,6 +4,7 @@ connection server_1; call mtr.add_suppression("Checking table:"); call mtr.add_suppression("client is using or hasn't closed the table properly"); call mtr.add_suppression("Table .* is marked as crashed and should be repaired"); +call mtr.add_suppression("Could not read packet:.* errno: 11"); flush tables; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB; diff --git a/mysql-test/suite/rpl/r/rpl_gtid_grouping.result b/mysql-test/suite/rpl/r/rpl_gtid_grouping.result index ad7d6116c49..1b4d86dd8e2 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_grouping.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_grouping.result @@ -50,5 +50,4 @@ CHANGE MASTER TO MASTER_USE_GTID=no; include/start_slave.inc connection master; DROP TABLE t; -SET GLOBAL LOG_WARNINGS=default; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_heartbeat_debug.result b/mysql-test/suite/rpl/r/rpl_heartbeat_debug.result index dc45c0b9ab3..a89010cd432 100644 --- a/mysql-test/suite/rpl/r/rpl_heartbeat_debug.result +++ b/mysql-test/suite/rpl/r/rpl_heartbeat_debug.result @@ -9,8 +9,6 @@ Variable_name Slave_heartbeat_period Value 60.000 SET @saved_dbug= @@GLOBAL.debug_dbug; SET GLOBAL debug_dbug="+d,simulate_slave_heartbeat_network_error"; -CALL mtr.add_suppression('SET @master_heartbeat_period to master failed with error'); -CALL mtr.add_suppression('Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again'); include/start_slave.inc connection master; drop table if exists t1; diff --git a/mysql-test/suite/rpl/r/rpl_packet.result b/mysql-test/suite/rpl/r/rpl_packet.result index 4a2a5d70d39..bb6269607fe 100644 --- a/mysql-test/suite/rpl/r/rpl_packet.result +++ b/mysql-test/suite/rpl/r/rpl_packet.result @@ -2,6 +2,8 @@ include/master-slave.inc [connection master] call mtr.add_suppression("Slave I/O: Got a packet bigger than 'slave_max_allowed_packet' bytes, .*error.* 1153"); call mtr.add_suppression("Log entry on master is longer than slave_max_allowed_packet"); +call mtr.add_suppression("Could not write packet:"); +call mtr.add_suppression("Got a packet bigger than 'max_allowed_packet' bytes"); drop database if exists DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; create database DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; connection master; diff --git a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result index eff939512e2..0b317c4682b 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result @@ -626,6 +626,7 @@ include/save_master_gtid.inc connection server_2; include/sync_with_master_gtid.inc connection server_2; +SET @org_log_warnings=@@GLOBAL.LOG_WARNINGS; set global log_warnings=2; BEGIN; INSERT INTO t1 SET a=1; @@ -651,7 +652,7 @@ connection server_2; include/sync_with_master_gtid.inc connection server_2; include/stop_slave.inc -set global log_warnings=default; +set global log_warnings=@org_log_warnings; SET GLOBAL slave_parallel_mode=@old_parallel_mode; SET GLOBAL slave_parallel_threads=@old_parallel_threads; include/start_slave.inc diff --git a/mysql-test/suite/rpl/r/rpl_parallel_optimistic_xa.result b/mysql-test/suite/rpl/r/rpl_parallel_optimistic_xa.result index 4136f1885db..90c3e5db614 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_optimistic_xa.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_optimistic_xa.result @@ -32,7 +32,6 @@ include/diff_tables.inc [master:t0, slave:t0] include/diff_tables.inc [master:t1, slave:t1] connection slave; include/stop_slave.inc -set global log_warnings=default; SET GLOBAL slave_parallel_mode=@old_parallel_mode; SET GLOBAL slave_parallel_threads=@old_parallel_threads; include/start_slave.inc diff --git a/mysql-test/suite/rpl/r/rpl_parallel_optimistic_xa_lsu_off.result b/mysql-test/suite/rpl/r/rpl_parallel_optimistic_xa_lsu_off.result index 4136f1885db..90c3e5db614 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_optimistic_xa_lsu_off.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_optimistic_xa_lsu_off.result @@ -32,7 +32,6 @@ include/diff_tables.inc [master:t0, slave:t0] include/diff_tables.inc [master:t1, slave:t1] connection slave; include/stop_slave.inc -set global log_warnings=default; SET GLOBAL slave_parallel_mode=@old_parallel_mode; SET GLOBAL slave_parallel_threads=@old_parallel_threads; include/start_slave.inc diff --git a/mysql-test/suite/rpl/r/rpl_row_find_row_debug.result b/mysql-test/suite/rpl/r/rpl_row_find_row_debug.result index f1a0059a04f..c2bb256a750 100644 --- a/mysql-test/suite/rpl/r/rpl_row_find_row_debug.result +++ b/mysql-test/suite/rpl/r/rpl_row_find_row_debug.result @@ -20,6 +20,5 @@ FOUND 1 /The slave is applying a ROW event on behalf of an UPDATE statement on t FOUND 1 /The slave is applying a ROW event on behalf of a DELETE statement on table t1 and is currently taking a considerable amount/ in mysqld.2.err include/stop_slave.inc SET @@GLOBAL.debug_dbug = @saved_dbug; -SET GLOBAL log_warnings = 2; include/start_slave.inc include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result index 99c3124957f..11cdb965dd6 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result @@ -2,6 +2,8 @@ include/master-slave.inc [connection master] call mtr.add_suppression("Replication event checksum verification failed"); call mtr.add_suppression("could not queue event from master"); +call mtr.add_suppression("Semisync ack receiver.*error reading communication packets"); +call mtr.add_suppression("Semisync ack receiver got hangup"); # # Set up a semisync connection connection master; diff --git a/mysql-test/suite/rpl/r/show_status_stop_slave_race-7126.result b/mysql-test/suite/rpl/r/show_status_stop_slave_race-7126.result index 999d9417b3f..35cb3fcdc13 100644 --- a/mysql-test/suite/rpl/r/show_status_stop_slave_race-7126.result +++ b/mysql-test/suite/rpl/r/show_status_stop_slave_race-7126.result @@ -1,6 +1,5 @@ include/master-slave.inc [connection master] -call mtr.add_suppression("Master is configured to log replication events"); connection slave; connection slave; include/wait_for_slave_to_stop.inc diff --git a/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test b/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test index 942a23576c4..b77aa7797e3 100644 --- a/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test +++ b/mysql-test/suite/rpl/t/rpl_binlog_dump_slave_gtid_state_info.test @@ -39,6 +39,7 @@ --source include/master-slave.inc --connection master +SET @org_log_warnings=@@GLOBAL.LOG_WARNINGS; SET GLOBAL LOG_WARNINGS=2; --connection slave @@ -110,6 +111,7 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos; --source include/wait_for_pattern_in_file.inc --echo "===== Clean up =====" +SET GLOBAL LOG_WARNINGS=@org_log_warnings; --connection slave --source include/stop_slave.inc CHANGE MASTER TO MASTER_USE_GTID=no; @@ -117,5 +119,4 @@ CHANGE MASTER TO MASTER_USE_GTID=no; --connection master DROP TABLE t; -SET GLOBAL LOG_WARNINGS=default; --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test index cdfdc098f5a..2ce273860fe 100644 --- a/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test +++ b/mysql-test/suite/rpl/t/rpl_domain_id_filter_master_crash.test @@ -6,9 +6,12 @@ connection master; +--disable_query_log call mtr.add_suppression("mysqld: Table '.*gtid_slave_pos' is marked as crashed and should be repaired"); call mtr.add_suppression("Checking table: './mysql/gtid_slave_pos'"); call mtr.add_suppression("mysql.gtid_slave_pos: 1 client is using or hasn't closed the table properly"); +call mtr.add_suppression("Could not read packet:.* errno: 11"); +--enable_query_log SET @@session.gtid_domain_id= 0; create table ti (a int auto_increment primary key) engine=innodb; diff --git a/mysql-test/suite/rpl/t/rpl_dump_request_retry_warning.test b/mysql-test/suite/rpl/t/rpl_dump_request_retry_warning.test index 1ee043623ae..633071a89b3 100644 --- a/mysql-test/suite/rpl/t/rpl_dump_request_retry_warning.test +++ b/mysql-test/suite/rpl/t/rpl_dump_request_retry_warning.test @@ -30,6 +30,10 @@ --let $rpl_skip_start_slave=1 --source include/master-slave.inc +--disable_query_log +call mtr.add_suppression("Could not read packet:.* errno: 11"); +--enable_query_log + # Do an insert on master CREATE TABLE t1(a int); INSERT INTO t1 VALUES(1); diff --git a/mysql-test/suite/rpl/t/rpl_get_lock.test b/mysql-test/suite/rpl/t/rpl_get_lock.test index b5c08858055..f0a11e712f6 100644 --- a/mysql-test/suite/rpl/t/rpl_get_lock.test +++ b/mysql-test/suite/rpl/t/rpl_get_lock.test @@ -1,6 +1,16 @@ source include/master-slave.inc; +--disable_query_log CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +call mtr.add_suppression("Could not read packet:.* errno: 11 "); +# The following one comes from calling dirty_close on client side +call mtr.add_suppression("Could not read packet:.* errno: 2 "); +--enable_query_log + +let $org_log_warnings=`select @@global.log_warnings`; + +# Test extended warnings +SET GLOBAL LOG_WARNINGS=4; create table t1(n int); # Use of get_lock gives a warning for unsafeness if binlog_format=statement @@ -41,6 +51,10 @@ connection master1; drop table t1; sync_slave_with_master; +connection default; +--disable_query_log +--eval SET GLOBAL LOG_WARNINGS=$org_log_warnings; +--enable_query_log --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash.test b/mysql-test/suite/rpl/t/rpl_gtid_crash.test index f2167911101..84dd9aa65e0 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_crash.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_crash.test @@ -12,6 +12,7 @@ call mtr.add_suppression("Checking table:"); call mtr.add_suppression("client is using or hasn't closed the table properly"); call mtr.add_suppression("Table .* is marked as crashed and should be repaired"); +call mtr.add_suppression("Could not read packet:.* errno: 11"); flush tables; ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; diff --git a/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam.test b/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam.test index faf388f5bed..e113e17b7ec 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_crash_myisam.test @@ -5,6 +5,10 @@ --let $rpl_topology=1->2 --source include/rpl_init.inc +--disable_query_log +call mtr.add_suppression("Could not read packet:.* errno: 11"); +--enable_query_log + --echo *** Test crashing master with InnoDB disabled, the binlog gtid state should still be correctly recovered. *** --connection server_1 diff --git a/mysql-test/suite/rpl/t/rpl_gtid_grouping.test b/mysql-test/suite/rpl/t/rpl_gtid_grouping.test index 66448c4f96c..bb1057a6e4f 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_grouping.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_grouping.test @@ -93,5 +93,4 @@ CHANGE MASTER TO MASTER_USE_GTID=no; --connection master DROP TABLE t; -SET GLOBAL LOG_WARNINGS=default; --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_heartbeat_debug.test b/mysql-test/suite/rpl/t/rpl_heartbeat_debug.test index bd66a249ada..e593786655b 100644 --- a/mysql-test/suite/rpl/t/rpl_heartbeat_debug.test +++ b/mysql-test/suite/rpl/t/rpl_heartbeat_debug.test @@ -3,6 +3,12 @@ --source include/have_debug.inc --source include/master-slave.inc +--disable_query_log +CALL mtr.add_suppression('SET @master_heartbeat_period to master failed with error'); +CALL mtr.add_suppression('Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again'); +call mtr.add_suppression("Could not read packet:.* errno: 11"); +--enable_query_log + connection slave; --source include/stop_slave.inc set @restore_slave_net_timeout= @@global.slave_net_timeout; @@ -14,14 +20,13 @@ set @@global.slave_net_timeout= 10; ### Checking the range ### -# + # default period slave_net_timeout/2 # --query_vertical show status like 'Slave_heartbeat_period'; SET @saved_dbug= @@GLOBAL.debug_dbug; SET GLOBAL debug_dbug="+d,simulate_slave_heartbeat_network_error"; -CALL mtr.add_suppression('SET @master_heartbeat_period to master failed with error'); -CALL mtr.add_suppression('Master command COM_REGISTER_SLAVE failed: failed registering on master, reconnecting to try again'); + --source include/start_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_packet.test b/mysql-test/suite/rpl/t/rpl_packet.test index cbde486bcbb..f1814e61f9b 100644 --- a/mysql-test/suite/rpl/t/rpl_packet.test +++ b/mysql-test/suite/rpl/t/rpl_packet.test @@ -20,6 +20,9 @@ source include/master-slave.inc; call mtr.add_suppression("Slave I/O: Got a packet bigger than 'slave_max_allowed_packet' bytes, .*error.* 1153"); call mtr.add_suppression("Log entry on master is longer than slave_max_allowed_packet"); +call mtr.add_suppression("Could not write packet:"); +call mtr.add_suppression("Got a packet bigger than 'max_allowed_packet' bytes"); + let $db= DB_NAME_OF_MAX_LENGTH_AKA_NAME_LEN_64_BYTES_____________________; disable_warnings; eval drop database if exists $db; diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test index f5e48282326..09da8c2df15 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test @@ -508,6 +508,7 @@ DELETE FROM t2; # The 1st of the following two trx:s a blocker on slave --connection server_2 +SET @org_log_warnings=@@GLOBAL.LOG_WARNINGS; set global log_warnings=2; BEGIN; INSERT INTO t1 SET a=1; @@ -555,7 +556,7 @@ DELETE FROM t2; # --connection server_2 --source include/stop_slave.inc -set global log_warnings=default; +set global log_warnings=@org_log_warnings; SET GLOBAL slave_parallel_mode=@old_parallel_mode; SET GLOBAL slave_parallel_threads=@old_parallel_threads; --source include/start_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa.test index 35c22d1e92e..6e5cf4367a7 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic_xa.test @@ -206,7 +206,6 @@ while($i > 0) # --connection slave --source include/stop_slave.inc -set global log_warnings=default; SET GLOBAL slave_parallel_mode=@old_parallel_mode; SET GLOBAL slave_parallel_threads=@old_parallel_threads; --source include/start_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_find_row_debug.test b/mysql-test/suite/rpl/t/rpl_row_find_row_debug.test index e3edabe239d..f06b2982ec5 100644 --- a/mysql-test/suite/rpl/t/rpl_row_find_row_debug.test +++ b/mysql-test/suite/rpl/t/rpl_row_find_row_debug.test @@ -51,7 +51,9 @@ DROP TABLE t1; # cleanup --source include/stop_slave.inc SET @@GLOBAL.debug_dbug = @saved_dbug; +--disable_query_log --eval SET GLOBAL log_warnings = $log_warnings_save +--enable_query_log --source include/start_slave.inc --source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test index 17d7b50d614..e1e7a4f1de3 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_fail_over.test @@ -10,6 +10,11 @@ --source include/have_binlog_format_row.inc --source include/master-slave.inc +--disable_query_log +call mtr.add_suppression("Could not read packet:.* errno: 11"); +flush tables; +--enable_query_log + # Initial slave --connection server_2 --source include/stop_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf index 2cf1b1786bd..5f69b557188 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.cnf @@ -1,13 +1,13 @@ !include ../my.cnf [mysqld.1] -log_warnings=9 +log_warnings=3 [mysqld.2] -log_warnings=9 +log_warnings=3 [mysqld.3] -log_warnings=9 +log_warnings=3 [ENV] SERVER_MYPORT_3= @mysqld.3.port diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test index 9e388ab4419..ed78eff52ea 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test @@ -14,7 +14,8 @@ call mtr.add_suppression("Replication event checksum verification failed"); call mtr.add_suppression("could not queue event from master"); - +call mtr.add_suppression("Semisync ack receiver.*error reading communication packets"); +call mtr.add_suppression("Semisync ack receiver got hangup"); --echo # --echo # Set up a semisync connection --connection master diff --git a/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test b/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test index cd0f8aad106..815b2537e93 100644 --- a/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test +++ b/mysql-test/suite/rpl/t/show_status_stop_slave_race-7126.test @@ -3,7 +3,10 @@ # --source include/master-slave.inc +--disable_query_log call mtr.add_suppression("Master is configured to log replication events"); +call mtr.add_suppression("Could not read packet:.* errno: 11"); +--enable_query_log --connection slave diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 3dff8442c6a..b1009b6552b 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -74,7 +74,13 @@ static int inline EXTRA_DEBUG_fflush(...) { return 0; } #ifdef MYSQL_SERVER #include #include -#define MYSQL_SERVER_my_error my_error + +static void inline MYSQL_SERVER_my_error(uint error, myf flags) +{ + my_error(error, + flags | MYF(global_system_variables.log_warnings > 3 ? ME_ERROR_LOG : 0)); +} + #else static void inline MYSQL_SERVER_my_error(...) {} #endif @@ -766,7 +772,19 @@ net_real_write(NET *net,const uchar *packet, size_t len) #endif /* !defined(MYSQL_SERVER) */ net->error= 2; /* Close socket */ net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED : - ER_NET_ERROR_ON_WRITE); + ER_NET_ERROR_ON_WRITE); +#ifdef MYSQL_SERVER + if (global_system_variables.log_warnings > 3) + { + my_printf_error(net->last_errno, + "Could not write packet: fd: %lld state: %d " + "errno: %d vio_errno: %d length: %ld", + MYF(ME_ERROR_LOG), + (longlong) vio_fd(net->vio), (int) net->vio->state, + vio_errno(net->vio), net->last_errno, (ulong) (end-pos)); + break; + } +#endif MYSQL_SERVER_my_error(net->last_errno, MYF(0)); break; } @@ -1064,20 +1082,34 @@ retry: (longlong) vio_fd(net->vio)); } #ifndef MYSQL_SERVER - if (length != 0 && vio_errno(net->vio) == SOCKET_EINTR) + if (length != 0 && vio_should_retry(net->vio)) { DBUG_PRINT("warning",("Interrupted read. Retrying...")); continue; } #endif - DBUG_PRINT("error",("Couldn't read packet: remain: %u errno: %d length: %ld", + DBUG_PRINT("error",("Could not read packet: remain: %u errno: %d length: %ld", remain, vio_errno(net->vio), (long) length)); len= packet_error; net->error= 2; /* Close socket */ net->last_errno= (vio_was_timeout(net->vio) ? - ER_NET_READ_INTERRUPTED : - ER_NET_READ_ERROR); - MYSQL_SERVER_my_error(net->last_errno, MYF(0)); + ER_NET_READ_INTERRUPTED : + ER_NET_READ_ERROR); +#ifdef MYSQL_SERVER + if (global_system_variables.log_warnings > 3) + { + my_printf_error(net->last_errno, + "Could not read packet: fd: %lld state: %d " + "remain: %u errno: %d vio_errno: %d " + "length: %lld", + MYF(ME_ERROR_LOG), + (longlong) vio_fd(net->vio), (int) net->vio->state, + remain, vio_errno(net->vio), net->last_errno, + (longlong) length); + } + else + my_error(net->last_errno, MYF(0)); +#endif /* MYSQL_SERVER */ goto end; } remain -= (uint32) length; @@ -1282,7 +1314,10 @@ ulong my_net_read_packet(NET *net, my_bool read_from_server) { ulong reallen = 0; - return my_net_read_packet_reallen(net, read_from_server, &reallen); + ulong length; + DBUG_ENTER("my_net_read_packet"); + length= my_net_read_packet_reallen(net, read_from_server, &reallen); + DBUG_RETURN(length); } diff --git a/sql/semisync_master_ack_receiver.cc b/sql/semisync_master_ack_receiver.cc index 9320c7fc3e6..bcc5bda8220 100644 --- a/sql/semisync_master_ack_receiver.cc +++ b/sql/semisync_master_ack_receiver.cc @@ -149,7 +149,7 @@ bool Ack_receiver::add_slave(THD *thd) slave->thd= thd; slave->vio= *thd->net.vio; slave->vio.mysql_socket.m_psi= NULL; - slave->vio.read_timeout= 1; + slave->vio.read_timeout= 1; // 1 ms mysql_mutex_lock(&m_mutex); @@ -337,6 +337,17 @@ void Ack_receiver::run() */ net.compress= slave->thd->net.compress; + if (unlikely(listener.is_socket_hangup(slave))) + { + if (global_system_variables.log_warnings > 2) + sql_print_warning("Semisync ack receiver got hangup " + "from slave server-id %d", + slave->server_id()); + it.remove(); + m_slaves_changed= true; + continue; + } + len= my_net_read(&net); if (likely(len != packet_error)) { diff --git a/sql/semisync_master_ack_receiver.h b/sql/semisync_master_ack_receiver.h index 817df513069..6b3ff3695d0 100644 --- a/sql/semisync_master_ack_receiver.h +++ b/sql/semisync_master_ack_receiver.h @@ -228,6 +228,11 @@ public: return m_fds[slave->m_fds_index].revents & POLLIN; } + bool is_socket_hangup(const Slave *slave) + { + return m_fds[slave->m_fds_index].revents & POLLHUP; + } + void clear_socket_info(const Slave *slave) { m_fds[slave->m_fds_index].fd= -1; @@ -296,6 +301,11 @@ public: return FD_ISSET(slave->sock_fd(), &m_fds); } + bool is_socket_hangup(const Slave *slave) + { + return 0; + } + bool has_signal_data() override { return FD_ISSET(local_read_signal, &m_fds); diff --git a/sql/slave.cc b/sql/slave.cc index 61c638c9fdf..b5558868cac 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1340,6 +1340,8 @@ static bool io_slave_killed(Master_info* mi) DBUG_ENTER("io_slave_killed"); DBUG_ASSERT(mi->slave_running); // tracking buffer overrun + if (mi->abort_slave || mi->io_thd->killed) + DBUG_PRINT("info", ("killed")); DBUG_RETURN(mi->abort_slave || mi->io_thd->killed); } diff --git a/vio/vio.c b/vio/vio.c index 7a98eb2af7b..bf1e79ae36b 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -79,6 +79,7 @@ static my_bool has_no_data(Vio *vio __attribute__((unused))) int vio_pipe_shutdown(Vio *vio, int how) { vio->shutdown_flag= how; + vio->state= VIO_STATE_SHUTDOWN; return CancelIoEx(vio->hPipe, NULL); } #endif @@ -98,6 +99,7 @@ static void vio_init(Vio *vio, enum enum_vio_type type, #endif memset(vio, 0, sizeof(*vio)); vio->type= type; + vio->state= VIO_STATE_ACTIVE; vio->mysql_socket= MYSQL_INVALID_SOCKET; mysql_socket_setfd(&vio->mysql_socket, sd); vio->localhost= flags & VIO_LOCALHOST; diff --git a/vio/viosocket.c b/vio/viosocket.c index 002ff274b74..bb6baac571e 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -288,12 +288,18 @@ size_t vio_write(Vio *vio, const uchar* buf, size_t size) int vio_socket_shutdown(Vio *vio, int how) { - int ret= shutdown(mysql_socket_getfd(vio->mysql_socket), how); + int ret; + DBUG_ENTER("vio_socket_shutdown"); + DBUG_PRINT("enter", ("sd: %d", (int)mysql_socket_getfd(vio->mysql_socket))); + + vio->state= VIO_STATE_SHUTDOWN; + ret= shutdown(mysql_socket_getfd(vio->mysql_socket), how); + #ifdef _WIN32 /* Cancel possible IO in progress (shutdown does not do that on Windows). */ (void) CancelIoEx((HANDLE)mysql_socket_getfd(vio->mysql_socket), NULL); #endif - return ret; + DBUG_RETURN(ret); } @@ -552,8 +558,10 @@ my_bool vio_should_retry(Vio *vio) { DBUG_ENTER("vio_should_retry"); - DBUG_PRINT("info", ("vio_errno: %d", vio_errno(vio))); - DBUG_RETURN(vio_errno(vio) == SOCKET_EINTR); + DBUG_PRINT("info", ("vio_errno: %d state: %d", + vio_errno(vio), (int) vio->state)); + DBUG_RETURN(vio_errno(vio) == SOCKET_EINTR && + vio->state < VIO_STATE_SHUTDOWN); } @@ -576,28 +584,30 @@ vio_was_timeout(Vio *vio) int vio_close(Vio *vio) { - int r=0; DBUG_ENTER("vio_close"); DBUG_PRINT("enter", ("sd: %d", (int)mysql_socket_getfd(vio->mysql_socket))); if (vio->type != VIO_CLOSED) { + MYSQL_SOCKET mysql_socket= vio->mysql_socket; DBUG_ASSERT(vio->type == VIO_TYPE_TCPIP || - vio->type == VIO_TYPE_SOCKET || - vio->type == VIO_TYPE_SSL); + vio->type == VIO_TYPE_SOCKET || + vio->type == VIO_TYPE_SSL); - DBUG_ASSERT(mysql_socket_getfd(vio->mysql_socket) >= 0); - if (mysql_socket_close(vio->mysql_socket)) - r= -1; + + vio->type= VIO_CLOSED; + vio->state= VIO_STATE_CLOSED; + vio->mysql_socket= MYSQL_INVALID_SOCKET; + + DBUG_ASSERT(mysql_socket_getfd(mysql_socket) >= 0); + if (mysql_socket_close(mysql_socket)) + { + DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno)); + /* FIXME: error handling (not critical for MySQL) */ + DBUG_RETURN(-1); + } } - if (r) - { - DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno)); - /* FIXME: error handling (not critical for MySQL) */ - } - vio->type= VIO_CLOSED; - vio->mysql_socket= MYSQL_INVALID_SOCKET; - DBUG_RETURN(r); + DBUG_RETURN(0); } @@ -917,7 +927,17 @@ int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout) my_socket sd= mysql_socket_getfd(vio->mysql_socket); MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */ DBUG_ENTER("vio_io_wait"); - DBUG_PRINT("enter", ("timeout: %d", timeout)); + DBUG_PRINT("enter", ("sd: %d timeout: %d", + (int) mysql_socket_getfd(vio->mysql_socket), + timeout)); + + if (vio->state >= VIO_STATE_SHUTDOWN) + { + DBUG_PRINT("info", ("vio deactivated. state: %ld", (int) vio->state)); + /* Socket is shutdown or closed */ + errno= EIO; + DBUG_RETURN(-1); + } memset(&pfd, 0, sizeof(pfd)); @@ -948,7 +968,7 @@ int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout) switch ((ret= poll(&pfd, 1, timeout))) { case -1: - DBUG_PRINT("error", ("poll returned -1")); + DBUG_PRINT("error", ("poll returned -1 errno: %d", vio_errno(vio))); /* On error, -1 is returned. */ break; case 0: @@ -980,6 +1000,14 @@ int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout) MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */ DBUG_ENTER("vio_io_wait"); + if (vio->state >= VIO_STATE_SHUTDOWN) + { + DBUG_PRINT("info", ("vio deactive. state: %ld", (int) vio->state)); + /* Socket is shutdown or closed */ + errno= EIO; + DBUG_RETURN(-1); + } + /* Convert the timeout, in milliseconds, to seconds and microseconds. */ if (timeout >= 0) { @@ -1153,12 +1181,16 @@ my_bool vio_is_connected(Vio *vio) uint bytes= 0; DBUG_ENTER("vio_is_connected"); + if (vio->state >= VIO_STATE_SHUTDOWN) + DBUG_RETURN(FALSE); + /* The first step of detecting an EOF condition is verifying whether there is data to read. Data in this case would be the EOF. An exceptional condition event and/or errors are interpreted as if there is data to read. */ + if (!vio_io_wait(vio, VIO_IO_EVENT_READ, 0)) DBUG_RETURN(TRUE); From 8532dd82f139476009ffa879eec2397a66ed0b6f Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 5 Mar 2024 18:31:56 +0530 Subject: [PATCH 046/106] MDEV-13765 encryption.encrypt_and_grep failed in buildbot with wrong result - Adjust the test case to check whether all tablespaces are encrypted by comparing it with existing table count. --- mysql-test/suite/encryption/t/encrypt_and_grep.test | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/encryption/t/encrypt_and_grep.test b/mysql-test/suite/encryption/t/encrypt_and_grep.test index 03f67db83f9..89f780fbe12 100644 --- a/mysql-test/suite/encryption/t/encrypt_and_grep.test +++ b/mysql-test/suite/encryption/t/encrypt_and_grep.test @@ -23,8 +23,9 @@ insert t2 values (repeat('tempsecret', 12)); insert t3 values (repeat('dummysecret', 12)); --echo # Wait max 10 min for key encryption threads to encrypt all spaces +--let $tables_count= `select count(*) from information_schema.tables where engine = 'InnoDB'` --let $wait_timeout= 600 ---let $wait_condition=SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 +--let $wait_condition=SELECT COUNT(*) = $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 --source include/wait_condition.inc --sorted_result @@ -93,8 +94,9 @@ UNLOCK TABLES; SET GLOBAL innodb_encrypt_tables = on; --echo # Wait max 10 min for key encryption threads to encrypt all spaces +--let $tables_count= `select count(*) from information_schema.tables where engine = 'InnoDB'` --let $wait_timeout= 600 ---let $wait_condition=SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0; +--let $wait_condition=SELECT COUNT(*) = $tables_count FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 --source include/wait_condition.inc --sorted_result From 738da4918d3cb77d429dd998e23a046ae6c07785 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 5 Mar 2024 21:32:30 +0530 Subject: [PATCH 047/106] MDEV-32346 Assertion failure sym_node->table != NULL in pars_retrieve_table_def on UPDATE - During update operation, InnoDB should avoid the initializing the FTS_DOC_ID of foreign table if the foreign table is discarded --- .../suite/innodb_fts/r/foreign_key_update.result | 12 ++++++++++++ .../suite/innodb_fts/t/foreign_key_update.test | 13 +++++++++++++ storage/innobase/row/row0mysql.cc | 3 ++- wsrep-lib | 2 +- 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb_fts/r/foreign_key_update.result b/mysql-test/suite/innodb_fts/r/foreign_key_update.result index f2d47da78c5..87c21c0bfc5 100644 --- a/mysql-test/suite/innodb_fts/r/foreign_key_update.result +++ b/mysql-test/suite/innodb_fts/r/foreign_key_update.result @@ -32,3 +32,15 @@ database database DROP TABLE t1_fk; DROP TABLE t1; +# +# MDEV-32346 Assertion failure sym_node->table != NULL +# in pars_retrieve_table_def on UPDATE +# +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a INT, b TEXT, FOREIGN KEY(a) REFERENCES t1(a), +FULLTEXT (b))ENGINE=InnoDB; +INSERT INTO t1 SET a=1; +ALTER TABLE t2 DISCARD TABLESPACE; +UPDATE t1 SET a=2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +DROP TABLE t2,t1; diff --git a/mysql-test/suite/innodb_fts/t/foreign_key_update.test b/mysql-test/suite/innodb_fts/t/foreign_key_update.test index 1f74e640088..8a64ac33d69 100644 --- a/mysql-test/suite/innodb_fts/t/foreign_key_update.test +++ b/mysql-test/suite/innodb_fts/t/foreign_key_update.test @@ -32,3 +32,16 @@ SELECT * FROM t1_fk WHERE MATCH(a) AGAINST('database'); DROP TABLE t1_fk; DROP TABLE t1; + +--echo # +--echo # MDEV-32346 Assertion failure sym_node->table != NULL +--echo # in pars_retrieve_table_def on UPDATE +--echo # +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (a INT, b TEXT, FOREIGN KEY(a) REFERENCES t1(a), + FULLTEXT (b))ENGINE=InnoDB; +INSERT INTO t1 SET a=1; +ALTER TABLE t2 DISCARD TABLESPACE; +--error ER_ROW_IS_REFERENCED_2 +UPDATE t1 SET a=2; +DROP TABLE t2,t1; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 2a594b0839c..e99735ba453 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1689,7 +1689,8 @@ init_fts_doc_id_for_ref( ut_ad(foreign->foreign_table != NULL); - if (foreign->foreign_table->fts != NULL) { + if (foreign->foreign_table->space + && foreign->foreign_table->fts) { fts_init_doc_id(foreign->foreign_table); } diff --git a/wsrep-lib b/wsrep-lib index 6a17207b7f4..a5d95f0175f 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit 6a17207b7f44379cdcd73d69203c1a37b901c9d3 +Subproject commit a5d95f0175f10b6127ea039c542725f6c4aa5cb9 From 6e5333fc8cf9efaee2abc7e34982a862c2268284 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Mon, 4 Mar 2024 18:50:12 +0530 Subject: [PATCH 048/106] MDEV-32445 InnoDB may corrupt its log before upgrading it on startup Problem: ======== During upgrade, InnoDB does write the redo log for adjusting the tablespace size or tablespace flags even before the log has upgraded to configured format. This could lead to data inconsistent if any crash happened during upgrade process. Fix: === srv_start(): Write the tablespace flags adjustment, increased tablespace size redo log only after redo log upgradation. log_write_low(), log_reserve_and_write_fast(): Check whether the redo log is in physical format. --- .../innodb/r/log_upgrade_101_flags.result | 12 ++ .../suite/innodb/t/log_upgrade_101_flags.test | 91 ++++++++ storage/innobase/include/log0log.inl | 1 + storage/innobase/mtr/mtr0mtr.cc | 2 + storage/innobase/srv/srv0start.cc | 194 +++++++++--------- 5 files changed, 202 insertions(+), 98 deletions(-) create mode 100644 mysql-test/suite/innodb/r/log_upgrade_101_flags.result create mode 100644 mysql-test/suite/innodb/t/log_upgrade_101_flags.test diff --git a/mysql-test/suite/innodb/r/log_upgrade_101_flags.result b/mysql-test/suite/innodb/r/log_upgrade_101_flags.result new file mode 100644 index 00000000000..6ae7c84807f --- /dev/null +++ b/mysql-test/suite/innodb/r/log_upgrade_101_flags.result @@ -0,0 +1,12 @@ +call mtr.add_suppression("InnoDB: The change buffer is corrupted"); +call mtr.add_suppression("InnoDB: Tablespace size stored in header is 768 pages, but the sum of data file sizes is 384 pages"); +call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS of file"); +# restart: --innodb-data-home-dir=MYSQLTEST_VARDIR/tmp/log_upgrade --innodb-log-group-home-dir=MYSQLTEST_VARDIR/tmp/log_upgrade --innodb-force-recovery=5 --innodb-log-file-size=4m --innodb_page_size=32k --innodb_buffer_pool_size=10M +SELECT COUNT(*) FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +COUNT(*) +1 +FOUND 1 /InnoDB: Upgrading redo log:/ in mysqld.1.err +# restart +# End of 10.5 tests diff --git a/mysql-test/suite/innodb/t/log_upgrade_101_flags.test b/mysql-test/suite/innodb/t/log_upgrade_101_flags.test new file mode 100644 index 00000000000..4358ccfa1ca --- /dev/null +++ b/mysql-test/suite/innodb/t/log_upgrade_101_flags.test @@ -0,0 +1,91 @@ +--source include/have_innodb.inc +--source include/big_test.inc +--source include/not_embedded.inc +call mtr.add_suppression("InnoDB: The change buffer is corrupted"); +call mtr.add_suppression("InnoDB: Tablespace size stored in header is 768 pages, but the sum of data file sizes is 384 pages"); +call mtr.add_suppression("InnoDB: adjusting FSP_SPACE_FLAGS of file"); +--source include/shutdown_mysqld.inc +let bugdir= $MYSQLTEST_VARDIR/tmp/log_upgrade; +--mkdir $bugdir +--let SEARCH_FILE = $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $dirs= --innodb-data-home-dir=$bugdir --innodb-log-group-home-dir=$bugdir + +# Test case similar to log_upgrade.test +perl; +do "$ENV{MTR_SUITE_DIR}/../innodb/include/crc32.pl"; +my $polynomial = 0x82f63b78; # CRC-32C + +die unless open OUT, ">", "$ENV{bugdir}/ibdata1"; +binmode OUT; + +my $head = pack("Nx[18]", 0); +# Add FSP_SPACE_FLAGS as 49152 (10.1.0...10.1.20), page_size = 32k +my $body = pack("x[8]Nx[4]Nx[2]Nx[32696]", 768, 49152, 97937874); +my $ck = mycrc32($head, 0, $polynomial) ^ mycrc32($body, 0, $polynomial); +print OUT pack("N",$ck).$head.pack("x[12]").$body.pack("Nx[4]",$ck); +# Dummy pages 1..6. +print OUT chr(0) x (6 * 32768); +# Dictionary header page (page 7). +$head = pack("Nx[18]", 7); +$body = pack("x[32]Nx[8]Nx[32674]", 8, 9); +$ck = mycrc32($head, 0, $polynomial) ^ mycrc32($body, 0, $polynomial); +print OUT pack("N",$ck).$head.pack("x[12]").$body.pack("Nx[4]",$ck); + +# Empty SYS_TABLES page (page 8). +$head = pack("NNNx[8]n", 8, ~0, ~0, 17855); +$body = pack("nnx[31]Cx[20]", 2, 124, 1); +$body .= pack("nxnn", 0x801, 3, 116) . "infimum"; +$body .= pack("xnxnxx", 0x901, 0x803) . "supremum"; +$body .= pack("x[32632]nn", 116, 101); +$ck = mycrc32($head, 0, $polynomial) ^ mycrc32($body, 0, $polynomial); +print OUT pack("N",$ck).$head.pack("x[12]").$body.pack("Nx[4]",$ck); + +# Empty SYS_INDEXES page (page 9). +$head = pack("NNNx[8]n", 9, ~0, ~0, 17855); +$body = pack("nnx[31]Cx[20]", 2, 124, 3); +$body .= pack("nxnn", 0x801, 3, 116) . "infimum"; +$body .= pack("xnxnxx", 0x901, 0x803) . "supremum"; +$body .= pack("x[32632]nn", 116, 101); +$ck = mycrc32($head, 0, $polynomial) ^ mycrc32($body, 0, $polynomial); +print OUT pack("N",$ck).$head.pack("x[12]").$body.pack("Nx[4]",$ck); + +die unless seek(OUT, 768 * 16384 - 1, 0); +print OUT chr(0); +close OUT or die; + +die unless open OUT, ">", "$ENV{bugdir}/ib_logfile0"; +binmode OUT; +$_= pack("Nx[5]nx[5]", 1, 0x1286) . "BogoDB 4.3.2.1" . chr(0) x 478; +print OUT $_, pack("N", mycrc32($_, 0, $polynomial)); +# checkpoint page 1 and all-zero checkpoint 2 +$_= pack("x[13]nCNNx[484]", 0x1286, 12, 2, 0x80c); +print OUT $_, pack("N", mycrc32($_, 0, $polynomial)); +die unless seek(OUT, 0x1FFFFFFFF, 0); +print OUT chr(0); +close OUT or die; +die unless open OUT, ">", "$ENV{bugdir}/ib_logfile1"; +binmode OUT; +die unless seek(OUT, 0x800, 0); # the first 2048 bytes are unused! +$_= pack("Nnnx[500]", 0x80000944, 12, 12); +print OUT $_, pack("N", mycrc32($_, 0, $polynomial)); +die unless seek(OUT, 0x1FFFFFFFF, 0); +print OUT chr(0); +close OUT or die; +EOF + +--let $restart_parameters= $dirs --innodb-force-recovery=5 --innodb-log-file-size=4m --innodb_page_size=32k --innodb_buffer_pool_size=10M +--source include/start_mysqld.inc +SELECT COUNT(*) FROM INFORMATION_SCHEMA.ENGINES +WHERE engine = 'innodb' +AND support IN ('YES', 'DEFAULT', 'ENABLED'); +--source include/shutdown_mysqld.inc +--let SEARCH_PATTERN= InnoDB: Upgrading redo log: +--source include/search_pattern_in_file.inc +--let $restart_parameters= $dirs + +--remove_files_wildcard $bugdir +--rmdir $bugdir +--let $restart_parameters= +--source include/start_mysqld.inc + +--echo # End of 10.5 tests diff --git a/storage/innobase/include/log0log.inl b/storage/innobase/include/log0log.inl index 0ff8c2523d7..8dd6f6ad573 100644 --- a/storage/innobase/include/log0log.inl +++ b/storage/innobase/include/log0log.inl @@ -270,6 +270,7 @@ log_reserve_and_write_fast( } lsn_t lsn = log_sys.get_lsn(); + ut_ad(log_sys.is_physical()); *start_lsn = lsn; memcpy(log_sys.buf + log_sys.buf_free, str, len); diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index dd9036f9e08..bf4b2b6b07c 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -850,6 +850,8 @@ static void log_write_low(const void *str, size_t size) len= trailer_offset - log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE; } + ut_ad(log_sys.is_physical()); + memcpy(log_sys.buf + log_sys.buf_free, str, len); size-= len; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 4382a318367..cd16b3265f6 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1555,6 +1555,102 @@ dberr_t srv_start(bool create_new_db) fil_system.space_id_reuse_warned = false; + if (srv_operation == SRV_OPERATION_RESTORE + || srv_operation == SRV_OPERATION_RESTORE_EXPORT) { + buf_flush_sync(); + recv_sys.debug_free(); + /* After applying the redo log from + SRV_OPERATION_BACKUP, flush the changes + to the data files and truncate or delete the log. + Unless --export is specified, no further change to + InnoDB files is needed. */ + ut_ad(srv_force_recovery <= SRV_FORCE_IGNORE_CORRUPT); + ut_ad(recv_no_log_write); + err = fil_write_flushed_lsn(log_sys.get_lsn()); + DBUG_ASSERT(!buf_pool.any_io_pending()); + log_sys.log.close_file(); + if (err == DB_SUCCESS) { + bool trunc = srv_operation + == SRV_OPERATION_RESTORE; + if (!trunc) { + delete_log_file("0"); + } else { + auto logfile0 = get_log_file_path(); + /* Truncate the first log file. */ + fclose(fopen(logfile0.c_str(), "w")); + } + } + return(err); + } + /* Upgrade or resize or rebuild the redo logs before + generating any dirty pages, so that the old redo log + file will not be written to. */ + + if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) { + /* Completely ignore the redo log. */ + } else if (srv_read_only_mode) { + /* Leave the redo log alone. */ + } else if (srv_log_file_size_requested == srv_log_file_size + && srv_log_file_found + && log_sys.log.format + == (srv_encrypt_log + ? log_t::FORMAT_ENC_10_5 + : log_t::FORMAT_10_5) + && log_sys.log.subformat == 2) { + /* No need to add or remove encryption, + upgrade, downgrade, or resize. */ + } else { + /* Prepare to delete the old redo log file */ + flushed_lsn = srv_prepare_to_delete_redo_log_file( + srv_log_file_found); + + DBUG_EXECUTE_IF("innodb_log_abort_1", + return(srv_init_abort(DB_ERROR));); + /* Prohibit redo log writes from any other + threads until creating a log checkpoint at the + end of create_log_file(). */ + ut_d(recv_no_log_write = true); + DBUG_ASSERT(!buf_pool.any_io_pending()); + + DBUG_EXECUTE_IF("innodb_log_abort_3", + return(srv_init_abort(DB_ERROR));); + DBUG_PRINT("ib_log", ("After innodb_log_abort_3")); + + /* Stamp the LSN to the data files. */ + err = fil_write_flushed_lsn(flushed_lsn); + + DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;); + DBUG_PRINT("ib_log", ("After innodb_log_abort_4")); + + if (err != DB_SUCCESS) { + return(srv_init_abort(err)); + } + + /* Close the redo log file, so that we can replace it */ + log_sys.log.close_file(); + + DBUG_EXECUTE_IF("innodb_log_abort_5", + return(srv_init_abort(DB_ERROR));); + DBUG_PRINT("ib_log", ("After innodb_log_abort_5")); + + ib::info() + << "Starting to delete and rewrite log file."; + + srv_log_file_size = srv_log_file_size_requested; + + err = create_log_file(false, flushed_lsn, logfile0); + + if (err == DB_SUCCESS) { + err = create_log_file_rename(flushed_lsn, + logfile0); + } + + if (err != DB_SUCCESS) { + return(srv_init_abort(err)); + } + } + recv_sys.debug_free(); + if (!srv_read_only_mode) { const ulint flags = FSP_FLAGS_PAGE_SSIZE(); for (ulint id = 0; id <= srv_undo_tablespaces; id++) { @@ -1639,104 +1735,6 @@ dberr_t srv_start(bool create_new_db) return(srv_init_abort(DB_ERROR)); } } - - if (srv_operation == SRV_OPERATION_RESTORE - || srv_operation == SRV_OPERATION_RESTORE_EXPORT) { - buf_flush_sync(); - recv_sys.debug_free(); - /* After applying the redo log from - SRV_OPERATION_BACKUP, flush the changes - to the data files and truncate or delete the log. - Unless --export is specified, no further change to - InnoDB files is needed. */ - ut_ad(srv_force_recovery <= SRV_FORCE_IGNORE_CORRUPT); - ut_ad(recv_no_log_write); - err = fil_write_flushed_lsn(log_sys.get_lsn()); - DBUG_ASSERT(!buf_pool.any_io_pending()); - log_sys.log.close_file(); - if (err == DB_SUCCESS) { - bool trunc = srv_operation - == SRV_OPERATION_RESTORE; - if (!trunc) { - delete_log_file("0"); - } else { - auto logfile0 = get_log_file_path(); - /* Truncate the first log file. */ - fclose(fopen(logfile0.c_str(), "w")); - } - } - return(err); - } - - /* Upgrade or resize or rebuild the redo logs before - generating any dirty pages, so that the old redo log - file will not be written to. */ - - if (srv_force_recovery == SRV_FORCE_NO_LOG_REDO) { - /* Completely ignore the redo log. */ - } else if (srv_read_only_mode) { - /* Leave the redo log alone. */ - } else if (srv_log_file_size_requested == srv_log_file_size - && srv_log_file_found - && log_sys.log.format - == (srv_encrypt_log - ? log_t::FORMAT_ENC_10_5 - : log_t::FORMAT_10_5) - && log_sys.log.subformat == 2) { - /* No need to add or remove encryption, - upgrade, downgrade, or resize. */ - } else { - /* Prepare to delete the old redo log file */ - flushed_lsn = srv_prepare_to_delete_redo_log_file( - srv_log_file_found); - - DBUG_EXECUTE_IF("innodb_log_abort_1", - return(srv_init_abort(DB_ERROR));); - /* Prohibit redo log writes from any other - threads until creating a log checkpoint at the - end of create_log_file(). */ - ut_d(recv_no_log_write = true); - DBUG_ASSERT(!buf_pool.any_io_pending()); - - DBUG_EXECUTE_IF("innodb_log_abort_3", - return(srv_init_abort(DB_ERROR));); - DBUG_PRINT("ib_log", ("After innodb_log_abort_3")); - - /* Stamp the LSN to the data files. */ - err = fil_write_flushed_lsn(flushed_lsn); - - DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;); - DBUG_PRINT("ib_log", ("After innodb_log_abort_4")); - - if (err != DB_SUCCESS) { - return(srv_init_abort(err)); - } - - /* Close the redo log file, so that we can replace it */ - log_sys.log.close_file(); - - DBUG_EXECUTE_IF("innodb_log_abort_5", - return(srv_init_abort(DB_ERROR));); - DBUG_PRINT("ib_log", ("After innodb_log_abort_5")); - - ib::info() - << "Starting to delete and rewrite log file."; - - srv_log_file_size = srv_log_file_size_requested; - - err = create_log_file(false, flushed_lsn, logfile0); - - if (err == DB_SUCCESS) { - err = create_log_file_rename(flushed_lsn, - logfile0); - } - - if (err != DB_SUCCESS) { - return(srv_init_abort(err)); - } - } - - recv_sys.debug_free(); } ut_ad(err == DB_SUCCESS); From 0df4651c13d68f1c228986f940d8ea4a226132f5 Mon Sep 17 00:00:00 2001 From: Monty Date: Wed, 6 Mar 2024 15:06:48 +0200 Subject: [PATCH 049/106] Fixed some mtr results found in Jenins after MDEV-333582 push MDEV-33582 Add more warnings to be able to better diagnose network issues - Disabled "Semisync ack receiver got hangup" warning - One could get this warning from semisync if running mtr --mysqld=log-warnings=3 rpl.rpl_semi_sync_shutdown_await_ack - Fixed result file for engines/funcs/rpl_get_lock.test --- mysql-test/mariadb-test-run.pl | 1 + mysql-test/suite/engines/funcs/r/rpl_get_lock.result | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/mariadb-test-run.pl b/mysql-test/mariadb-test-run.pl index d1124724e73..51d6aeb2d47 100755 --- a/mysql-test/mariadb-test-run.pl +++ b/mysql-test/mariadb-test-run.pl @@ -4492,6 +4492,7 @@ sub extract_warning_lines ($$) { qr/Could not write packet:.* errno: 32 /, qr/Could not write packet:.* errno: 104 /, qr/Semisync ack receiver got error 1158/, + qr/Semisync ack receiver got hangup/, qr/Connection was killed/, qr/Failed on request_dump/, qr/Slave: Can't drop database.* database doesn't exist/, diff --git a/mysql-test/suite/engines/funcs/r/rpl_get_lock.result b/mysql-test/suite/engines/funcs/r/rpl_get_lock.result index b852546e1bf..cbb02a32648 100644 --- a/mysql-test/suite/engines/funcs/r/rpl_get_lock.result +++ b/mysql-test/suite/engines/funcs/r/rpl_get_lock.result @@ -1,6 +1,6 @@ include/master-slave.inc [connection master] -CALL mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT"); +SET GLOBAL LOG_WARNINGS=4; create table t1(n int); insert into t1 values(get_lock("lock",2)); disconnect master; @@ -35,4 +35,5 @@ NULL connection master1; drop table t1; connection slave; +connection default; include/rpl_end.inc From afe9632913d5ed4c8d2aa81308f449e31766abaa Mon Sep 17 00:00:00 2001 From: mariadb-DebarunBanerjee Date: Tue, 5 Mar 2024 12:07:48 +0530 Subject: [PATCH 050/106] MDEV-33593 Auto increment deadlock error causes ASSERT in subsequent save point The issue here is ha_innobase::get_auto_increment() could cause a deadlock involving auto-increment lock and rollback the transaction implicitly. For such cases, storage engines usually call thd_mark_transaction_to_rollback() to inform SQL engine about it which in turn takes appropriate actions and close the transaction. In innodb, we call it while converting Innodb error code to MySQL. However, since ::innobase_get_autoinc() returns void, we skip the call for error code conversion and also miss marking the transaction for rollback for deadlock error. We assert eventually while releasing a savepoint as the transaction state is not active. Since convert_error_code_to_mysql() is handling some generic error handling part, like invoking the callback when needed, we should call that function in ha_innobase::get_auto_increment() even if we don't return the resulting mysql error code back. --- .../suite/innodb/r/autoinc_debug.result | 55 ++++++++++++++++ mysql-test/suite/innodb/t/autoinc_debug.test | 64 +++++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 7 ++ storage/innobase/lock/lock0lock.cc | 2 + 4 files changed, 128 insertions(+) diff --git a/mysql-test/suite/innodb/r/autoinc_debug.result b/mysql-test/suite/innodb/r/autoinc_debug.result index b3b7a469ada..94406a80ab5 100644 --- a/mysql-test/suite/innodb/r/autoinc_debug.result +++ b/mysql-test/suite/innodb/r/autoinc_debug.result @@ -105,3 +105,58 @@ t1 CREATE TABLE `t1` ( ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci DROP TABLE t1; SET DEBUG_SYNC='RESET'; +# +# MDEV-33593: Auto increment deadlock error causes ASSERT in subsequent save point +# +CREATE TABLE t1(col1 INT PRIMARY KEY AUTO_INCREMENT, col2 INT) ENGINE=InnoDB; +CREATE TABLE t2(col1 INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1(col2) values(100); +connect con1, localhost, root,,; +START TRANSACTION; +# T1: Acquiring Row X lock on table t2 +INSERT INTO t2 values(100); +connect con2, localhost, root,,; +START TRANSACTION; +# T2: Wait for (T1) row lock on t2 after acquiring GAP Lock on t1 +UPDATE t1 SET col2 = 20 where col1 = 10; +INSERT INTO t2 values(100); +connection default; +# T3: Wait for (T2) II row Lock on t1 after acquiring Auto Increment Lock on t1 +SET DEBUG_SYNC='lock_wait_suspend_thread_enter SIGNAL t3_waiting'; +INSERT INTO t1(col2) SELECT col2 from t1; +connection con1; +SAVEPOINT s1; +SET DEBUG_SYNC='now WAIT_FOR t3_waiting'; +# T1: Wait for (T3) auto increment lock on t1 causing T1 -> T3 -> T2 -> T1 deadlock +SET debug_dbug = '+d,innodb_deadlock_victim_self'; +INSERT INTO t1(col2) VALUES(200); +ERROR HY000: Failed to read auto-increment value from storage engine +# The transaction should have been rolled back +SELECT * FROM t1; +col1 col2 +1 100 +SELECT * FROM t2; +col1 +# Release the previous savepoint using the same name +SAVEPOINT s1; +COMMIT; +connection con2; +COMMIT; +connection default; +COMMIT; +disconnect con1; +disconnect con2; +# Cleanup +SELECT * FROM t1; +col1 col2 +1 100 +2 100 +DROP TABLE t1; +SELECT * FROM t2; +col1 +100 +DROP TABLE t2; +SET DEBUG_SYNC='RESET'; +# +# End of 10.5 tests +# diff --git a/mysql-test/suite/innodb/t/autoinc_debug.test b/mysql-test/suite/innodb/t/autoinc_debug.test index 7722b848c74..80168c9d7e1 100644 --- a/mysql-test/suite/innodb/t/autoinc_debug.test +++ b/mysql-test/suite/innodb/t/autoinc_debug.test @@ -92,3 +92,67 @@ SELECT * FROM t1; SHOW CREATE TABLE t1; DROP TABLE t1; SET DEBUG_SYNC='RESET'; + +--echo # +--echo # MDEV-33593: Auto increment deadlock error causes ASSERT in subsequent save point +--echo # + +CREATE TABLE t1(col1 INT PRIMARY KEY AUTO_INCREMENT, col2 INT) ENGINE=InnoDB; +CREATE TABLE t2(col1 INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t1(col2) values(100); + +--connect(con1, localhost, root,,) +START TRANSACTION; +--echo # T1: Acquiring Row X lock on table t2 +INSERT INTO t2 values(100); + +--connect(con2, localhost, root,,) +START TRANSACTION; +--echo # T2: Wait for (T1) row lock on t2 after acquiring GAP Lock on t1 +UPDATE t1 SET col2 = 20 where col1 = 10; +--send INSERT INTO t2 values(100) + +--connection default +--echo # T3: Wait for (T2) II row Lock on t1 after acquiring Auto Increment Lock on t1 +SET DEBUG_SYNC='lock_wait_suspend_thread_enter SIGNAL t3_waiting'; +--send INSERT INTO t1(col2) SELECT col2 from t1 + +--connection con1 +SAVEPOINT s1; +SET DEBUG_SYNC='now WAIT_FOR t3_waiting'; +--echo # T1: Wait for (T3) auto increment lock on t1 causing T1 -> T3 -> T2 -> T1 deadlock +SET debug_dbug = '+d,innodb_deadlock_victim_self'; +--error ER_AUTOINC_READ_FAILED +INSERT INTO t1(col2) VALUES(200); + +--echo # The transaction should have been rolled back +SELECT * FROM t1; +SELECT * FROM t2; + +--echo # Release the previous savepoint using the same name +SAVEPOINT s1; +COMMIT; + +--connection con2 +--reap +COMMIT; + +--connection default +--reap +COMMIT; + +--disconnect con1 +--disconnect con2 + +--echo # Cleanup +SELECT * FROM t1; +DROP TABLE t1; + +SELECT * FROM t2; +DROP TABLE t2; + +SET DEBUG_SYNC='RESET'; + +--echo # +--echo # End of 10.5 tests +--echo # diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c45b0ad0bbb..ad2e022f0b3 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -16655,6 +16655,13 @@ ha_innobase::get_auto_increment( if (error != DB_SUCCESS) { *first_value = (~(ulonglong) 0); + /* This is an error case. We do the error handling by calling + the error code conversion function. Specifically, we need to + call thd_mark_transaction_to_rollback() to inform sql that we + have rolled back innodb transaction after a deadlock error. We + ignore the returned mysql error code here. */ + std::ignore = convert_error_code_to_mysql( + error, m_prebuilt->table->flags, m_user_thd); return; } diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index c781ae23852..0891ad5ceb7 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -6712,6 +6712,8 @@ DeadlockChecker::select_victim() const ut_ad(m_start->lock.wait_lock != 0); ut_ad(m_wait_lock->trx != m_start); + DBUG_EXECUTE_IF("innodb_deadlock_victim_self", return m_start;); + if (trx_weight_ge(m_wait_lock->trx, m_start)) { /* The joining transaction is 'smaller', choose it as the victim and roll it back. */ From 9a132d423abe07ddb6af8e48c152932c924b8f30 Mon Sep 17 00:00:00 2001 From: Monty Date: Thu, 7 Mar 2024 11:25:30 +0200 Subject: [PATCH 051/106] MDEV-33620 Improve times and states in show processlist for replication This will makes it easier to find out what replication workers are doing and what they are waiting for. Things changed in processlist: - Slave_SQL time was not consistent. Now time for state "Slave has read all relay log; waiting for more updates" shows how long it has waited for getting the next event. - Slave_worker threads did often show "Closing tables" for a long time. Now the state is reverted to the previous state after "Closing tables" is done. - Commit and Rollback states where not shown for replication (and some other threads). Now Commit and Rollback states are always shown and the state is reverted to previous state when the Commit/Rollback have finished. Code changes: - Added thd->set_time_for_next_stage() for parallel replication when when starting to wait for prior transactions to commit, group commit, and FTWRL and for free space in thread pool. Before we reset the time only after the above events. - Moved THD_STAGE_INFO(stage_rollback) and THD_STAGE_INFO(stage_commit) from sql_parse.cc to transaction.cc to ensure this is done for all commits and not only 'normal connection queries'. Test case changes: - close_thread_tables() reverting stage to previous stage caused the counter in performance_schema to be increased. In many case it is the 'sql/starting' stage that was effected. - We only change to "Commit" stage if there is a need for a commit. This caused some "Commit" stages to disapper from perfschema reports. TODO in 11.#: - Slave_IO always showes "Waiting for master to send event" and the time is from SLAVE START. We should in 11.# change this to be the time since reading the last event. --- .../perfschema/r/alter_table_progress.result | 3 +- .../suite/perfschema/r/event_aggregate.result | 378 +++++++++--------- .../perfschema/r/event_aggregate_no_a.result | 266 ++++++------ .../r/event_aggregate_no_a_no_h.result | 228 +++++------ .../r/event_aggregate_no_a_no_u.result | 146 +++---- .../r/event_aggregate_no_a_no_u_no_h.result | 108 ++--- .../perfschema/r/event_aggregate_no_h.result | 340 ++++++++-------- .../perfschema/r/event_aggregate_no_u.result | 258 ++++++------ .../r/event_aggregate_no_u_no_h.result | 220 +++++----- mysql-test/suite/perfschema/r/nesting.result | 28 +- .../perfschema/r/stage_mdl_global.result | 4 +- .../suite/perfschema/r/stage_mdl_table.result | 2 +- .../suite/perfschema/r/threads_history.result | 24 +- sql/rpl_parallel.cc | 11 +- sql/sql_base.cc | 14 +- sql/sql_parse.cc | 4 - sql/transaction.cc | 33 ++ 17 files changed, 1054 insertions(+), 1013 deletions(-) diff --git a/mysql-test/suite/perfschema/r/alter_table_progress.result b/mysql-test/suite/perfschema/r/alter_table_progress.result index 08c2c3a6145..caca7378d21 100644 --- a/mysql-test/suite/perfschema/r/alter_table_progress.result +++ b/mysql-test/suite/perfschema/r/alter_table_progress.result @@ -82,11 +82,10 @@ stage/sql/Unlocking tables NULL NULL stage/sql/Rename result table NULL NULL stage/sql/End of update loop NULL NULL stage/sql/Query end NULL NULL -stage/sql/Commit NULL NULL stage/sql/closing tables NULL NULL stage/sql/Unlocking tables NULL NULL stage/sql/closing tables NULL NULL -stage/sql/Commit implicit NULL NULL +stage/sql/Query end NULL NULL stage/sql/Starting cleanup NULL NULL stage/sql/Freeing items NULL NULL stage/sql/Reset for next command NULL NULL diff --git a/mysql-test/suite/perfschema/r/event_aggregate.result b/mysql-test/suite/perfschema/r/event_aggregate.result index 4ad4c773941..c0074672b2f 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate.result +++ b/mysql-test/suite/perfschema/r/event_aggregate.result @@ -251,35 +251,35 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 4 localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 -localhost stage/sql/starting 6 +localhost stage/sql/starting 7 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -383,7 +383,7 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 0 user2 localhost stage/sql/closing tables 0 user2 localhost stage/sql/init 0 @@ -395,7 +395,7 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 0 user2 stage/sql/closing tables 0 user2 stage/sql/init 0 @@ -407,21 +407,21 @@ localhost stage/sql/checking permissions 4 localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 -localhost stage/sql/starting 6 +localhost stage/sql/starting 7 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -551,45 +551,45 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 8 localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 -localhost stage/sql/starting 12 +localhost stage/sql/starting 14 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -712,12 +712,12 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 0 user3 localhost stage/sql/closing tables 0 user3 localhost stage/sql/init 0 @@ -729,12 +729,12 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 0 user3 stage/sql/closing tables 0 user3 stage/sql/init 0 @@ -746,21 +746,21 @@ localhost stage/sql/checking permissions 8 localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 -localhost stage/sql/starting 12 +localhost stage/sql/starting 14 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -909,55 +909,55 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 12 localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 -localhost stage/sql/starting 18 +localhost stage/sql/starting 21 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1099,17 +1099,17 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 0 user4 localhost stage/sql/closing tables 0 user4 localhost stage/sql/init 0 @@ -1121,17 +1121,17 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 0 user4 stage/sql/closing tables 0 user4 stage/sql/init 0 @@ -1143,21 +1143,21 @@ localhost stage/sql/checking permissions 12 localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 -localhost stage/sql/starting 18 +localhost stage/sql/starting 21 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1325,65 +1325,65 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 24 +localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1538,65 +1538,65 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 25 +localhost stage/sql/starting 29 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1751,65 +1751,65 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 26 +localhost stage/sql/starting 30 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1963,65 +1963,65 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 27 +localhost stage/sql/starting 31 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2174,65 +2174,65 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2386,65 +2386,65 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2597,65 +2597,65 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2808,65 +2808,65 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3019,65 +3019,65 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3230,65 +3230,65 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3441,65 +3441,65 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3674,43 +3674,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3907,21 +3907,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4125,14 +4125,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4343,7 +4343,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4554,7 +4554,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4765,7 +4765,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4976,7 +4976,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5187,7 +5187,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5398,7 +5398,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5609,7 +5609,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5820,7 +5820,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -6031,7 +6031,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -6242,7 +6242,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -6453,7 +6453,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -6636,7 +6636,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -6763,7 +6763,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -6862,7 +6862,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a.result index 9ce3bb7efe8..7f8dfb4d3a0 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a.result @@ -235,28 +235,28 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 4 localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 -localhost stage/sql/starting 6 +localhost stage/sql/starting 7 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -350,7 +350,7 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 0 user2 stage/sql/closing tables 0 user2 stage/sql/init 0 @@ -362,21 +362,21 @@ localhost stage/sql/checking permissions 4 localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 -localhost stage/sql/starting 6 +localhost stage/sql/starting 7 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -489,33 +489,33 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 8 localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 -localhost stage/sql/starting 12 +localhost stage/sql/starting 14 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -619,12 +619,12 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 0 user3 stage/sql/closing tables 0 user3 stage/sql/init 0 @@ -636,21 +636,21 @@ localhost stage/sql/checking permissions 8 localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 -localhost stage/sql/starting 12 +localhost stage/sql/starting 14 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -773,38 +773,38 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 12 localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 -localhost stage/sql/starting 18 +localhost stage/sql/starting 21 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -918,17 +918,17 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 0 user4 stage/sql/closing tables 0 user4 stage/sql/init 0 @@ -940,21 +940,21 @@ localhost stage/sql/checking permissions 12 localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 -localhost stage/sql/starting 18 +localhost stage/sql/starting 21 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1087,43 +1087,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 24 +localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1243,43 +1243,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 25 +localhost stage/sql/starting 29 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1399,43 +1399,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 26 +localhost stage/sql/starting 30 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1554,43 +1554,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 27 +localhost stage/sql/starting 31 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1708,43 +1708,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1863,43 +1863,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2017,43 +2017,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2171,43 +2171,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2325,43 +2325,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2479,43 +2479,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2633,43 +2633,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2787,43 +2787,43 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2963,21 +2963,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3124,14 +3124,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3285,7 +3285,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3439,7 +3439,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3593,7 +3593,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3747,7 +3747,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3901,7 +3901,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4055,7 +4055,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4209,7 +4209,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4363,7 +4363,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4517,7 +4517,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4671,7 +4671,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4825,7 +4825,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4979,7 +4979,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -5105,7 +5105,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -5203,7 +5203,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result index 6590c162dda..d0cda4214d1 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_h.result @@ -205,7 +205,7 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -214,14 +214,14 @@ stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -306,7 +306,7 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 0 user2 stage/sql/closing tables 0 user2 stage/sql/init 0 @@ -320,14 +320,14 @@ stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -431,12 +431,12 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -445,14 +445,14 @@ stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -547,12 +547,12 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 0 user3 stage/sql/closing tables 0 user3 stage/sql/init 0 @@ -566,14 +566,14 @@ stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -687,17 +687,17 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -706,14 +706,14 @@ stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -818,17 +818,17 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 0 user4 stage/sql/closing tables 0 user4 stage/sql/init 0 @@ -842,14 +842,14 @@ stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -973,22 +973,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -997,14 +997,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1115,22 +1115,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -1139,14 +1139,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1257,22 +1257,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -1281,14 +1281,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1398,22 +1398,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -1422,14 +1422,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1538,22 +1538,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -1562,14 +1562,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1679,22 +1679,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -1703,14 +1703,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1819,22 +1819,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -1843,14 +1843,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1959,22 +1959,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -1983,14 +1983,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2099,22 +2099,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -2123,14 +2123,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2239,22 +2239,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -2263,14 +2263,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2379,22 +2379,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -2403,14 +2403,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2519,22 +2519,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -2543,14 +2543,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2683,14 +2683,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2823,14 +2823,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2970,7 +2970,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3110,7 +3110,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3250,7 +3250,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3390,7 +3390,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3530,7 +3530,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3670,7 +3670,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3810,7 +3810,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3950,7 +3950,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4090,7 +4090,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4230,7 +4230,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4370,7 +4370,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4510,7 +4510,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4622,7 +4622,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4706,7 +4706,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result index b7cf3b8a5ce..1115c7a73fa 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u.result @@ -219,21 +219,21 @@ localhost stage/sql/checking permissions 4 localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 -localhost stage/sql/starting 6 +localhost stage/sql/starting 7 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -317,21 +317,21 @@ localhost stage/sql/checking permissions 4 localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 -localhost stage/sql/starting 6 +localhost stage/sql/starting 7 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -427,21 +427,21 @@ localhost stage/sql/checking permissions 8 localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 -localhost stage/sql/starting 12 +localhost stage/sql/starting 14 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -526,21 +526,21 @@ localhost stage/sql/checking permissions 8 localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 -localhost stage/sql/starting 12 +localhost stage/sql/starting 14 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -637,21 +637,21 @@ localhost stage/sql/checking permissions 12 localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 -localhost stage/sql/starting 18 +localhost stage/sql/starting 21 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -737,21 +737,21 @@ localhost stage/sql/checking permissions 12 localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 -localhost stage/sql/starting 18 +localhost stage/sql/starting 21 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -849,21 +849,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 24 +localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -948,21 +948,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 25 +localhost stage/sql/starting 29 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1047,21 +1047,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 26 +localhost stage/sql/starting 30 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1145,21 +1145,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 27 +localhost stage/sql/starting 31 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1242,21 +1242,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1340,21 +1340,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1437,21 +1437,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1534,21 +1534,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1631,21 +1631,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1728,21 +1728,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1825,21 +1825,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1922,21 +1922,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2019,21 +2019,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2123,14 +2123,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2227,7 +2227,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2324,7 +2324,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2421,7 +2421,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2518,7 +2518,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2615,7 +2615,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2712,7 +2712,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2809,7 +2809,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2906,7 +2906,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3003,7 +3003,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3100,7 +3100,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3197,7 +3197,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3294,7 +3294,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3391,7 +3391,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -3488,7 +3488,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result index 24de36da22b..0c2318f5e74 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_a_no_u_no_h.result @@ -191,14 +191,14 @@ stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -275,14 +275,14 @@ stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -371,14 +371,14 @@ stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -456,14 +456,14 @@ stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -553,14 +553,14 @@ stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -639,14 +639,14 @@ stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -737,14 +737,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -822,14 +822,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -907,14 +907,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -991,14 +991,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1074,14 +1074,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1158,14 +1158,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1241,14 +1241,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1324,14 +1324,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1407,14 +1407,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1490,14 +1490,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1573,14 +1573,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1656,14 +1656,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1739,14 +1739,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1822,14 +1822,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1912,7 +1912,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -1995,7 +1995,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2078,7 +2078,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2161,7 +2161,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2244,7 +2244,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2327,7 +2327,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2410,7 +2410,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2493,7 +2493,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2576,7 +2576,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2659,7 +2659,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2742,7 +2742,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2825,7 +2825,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2908,7 +2908,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -2991,7 +2991,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_h.result index 2f0c96d7234..f18161f094e 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_h.result @@ -221,14 +221,14 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -237,14 +237,14 @@ stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -339,7 +339,7 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 0 user2 localhost stage/sql/closing tables 0 user2 localhost stage/sql/init 0 @@ -351,7 +351,7 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 0 user2 stage/sql/closing tables 0 user2 stage/sql/init 0 @@ -365,14 +365,14 @@ stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -493,24 +493,24 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -519,14 +519,14 @@ stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -640,12 +640,12 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 0 user3 localhost stage/sql/closing tables 0 user3 localhost stage/sql/init 0 @@ -657,12 +657,12 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 0 user3 stage/sql/closing tables 0 user3 stage/sql/init 0 @@ -676,14 +676,14 @@ stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -823,34 +823,34 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -859,14 +859,14 @@ stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -999,17 +999,17 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 0 user4 localhost stage/sql/closing tables 0 user4 localhost stage/sql/init 0 @@ -1021,17 +1021,17 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 0 user4 stage/sql/closing tables 0 user4 stage/sql/init 0 @@ -1045,14 +1045,14 @@ stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1211,44 +1211,44 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 6 +user1 stage/sql/starting 7 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -1257,14 +1257,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1410,44 +1410,44 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 6 +user2 stage/sql/starting 7 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -1456,14 +1456,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1609,44 +1609,44 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 6 +user3 stage/sql/starting 7 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -1655,14 +1655,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1807,44 +1807,44 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 6 +user4 stage/sql/starting 7 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -1853,14 +1853,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2004,44 +2004,44 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -2050,14 +2050,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2202,44 +2202,44 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -2248,14 +2248,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2399,44 +2399,44 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -2445,14 +2445,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2596,44 +2596,44 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -2642,14 +2642,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2793,44 +2793,44 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -2839,14 +2839,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2990,44 +2990,44 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -3036,14 +3036,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3187,44 +3187,44 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -3233,14 +3233,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3406,22 +3406,22 @@ user1 stage/sql/checking permissions 4 user1 stage/sql/closing tables 11 user1 stage/sql/init 3 user1 stage/sql/Opening tables 7 -user1 stage/sql/starting 7 +user1 stage/sql/starting 8 user2 stage/sql/checking permissions 4 user2 stage/sql/closing tables 10 user2 stage/sql/init 3 user2 stage/sql/Opening tables 6 -user2 stage/sql/starting 7 +user2 stage/sql/starting 8 user3 stage/sql/checking permissions 4 user3 stage/sql/closing tables 10 user3 stage/sql/init 3 user3 stage/sql/Opening tables 6 -user3 stage/sql/starting 7 +user3 stage/sql/starting 8 user4 stage/sql/checking permissions 4 user4 stage/sql/closing tables 10 user4 stage/sql/init 3 user4 stage/sql/Opening tables 6 -user4 stage/sql/starting 7 +user4 stage/sql/starting 8 execute dump_stages_host; host event_name count_star execute dump_stages_global; @@ -3430,14 +3430,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3627,14 +3627,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3824,14 +3824,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4028,7 +4028,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4225,7 +4225,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4422,7 +4422,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4619,7 +4619,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4816,7 +4816,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5013,7 +5013,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5210,7 +5210,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5407,7 +5407,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5604,7 +5604,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5801,7 +5801,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -5998,7 +5998,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -6167,7 +6167,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -6280,7 +6280,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -6365,7 +6365,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_u.result b/mysql-test/suite/perfschema/r/event_aggregate_no_u.result index 618201d9b85..9d5dc210985 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_u.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_u.result @@ -233,7 +233,7 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -242,21 +242,21 @@ localhost stage/sql/checking permissions 4 localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 -localhost stage/sql/starting 6 +localhost stage/sql/starting 7 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -348,7 +348,7 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 0 user2 localhost stage/sql/closing tables 0 user2 localhost stage/sql/init 0 @@ -362,21 +362,21 @@ localhost stage/sql/checking permissions 4 localhost stage/sql/closing tables 11 localhost stage/sql/init 3 localhost stage/sql/Opening tables 7 -localhost stage/sql/starting 6 +localhost stage/sql/starting 7 execute dump_stages_global; event_name count_star stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -487,12 +487,12 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -501,21 +501,21 @@ localhost stage/sql/checking permissions 8 localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 -localhost stage/sql/starting 12 +localhost stage/sql/starting 14 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -617,12 +617,12 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 0 user3 localhost stage/sql/closing tables 0 user3 localhost stage/sql/init 0 @@ -636,21 +636,21 @@ localhost stage/sql/checking permissions 8 localhost stage/sql/closing tables 21 localhost stage/sql/init 6 localhost stage/sql/Opening tables 13 -localhost stage/sql/starting 12 +localhost stage/sql/starting 14 execute dump_stages_global; event_name count_star stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -771,17 +771,17 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -790,21 +790,21 @@ localhost stage/sql/checking permissions 12 localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 -localhost stage/sql/starting 18 +localhost stage/sql/starting 21 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -916,17 +916,17 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 0 user4 localhost stage/sql/closing tables 0 user4 localhost stage/sql/init 0 @@ -940,21 +940,21 @@ localhost stage/sql/checking permissions 12 localhost stage/sql/closing tables 31 localhost stage/sql/init 9 localhost stage/sql/Opening tables 19 -localhost stage/sql/starting 18 +localhost stage/sql/starting 21 execute dump_stages_global; event_name count_star stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1085,22 +1085,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1109,21 +1109,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 24 +localhost stage/sql/starting 28 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1241,22 +1241,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1265,21 +1265,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 25 +localhost stage/sql/starting 29 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1397,22 +1397,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1421,21 +1421,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 26 +localhost stage/sql/starting 30 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1552,22 +1552,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1576,21 +1576,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 27 +localhost stage/sql/starting 31 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1706,22 +1706,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1730,21 +1730,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1861,22 +1861,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1885,21 +1885,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2015,22 +2015,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -2039,21 +2039,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2169,22 +2169,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -2193,21 +2193,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2323,22 +2323,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -2347,21 +2347,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2477,22 +2477,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -2501,21 +2501,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2631,22 +2631,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -2655,21 +2655,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2809,21 +2809,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2963,21 +2963,21 @@ localhost stage/sql/checking permissions 16 localhost stage/sql/closing tables 41 localhost stage/sql/init 12 localhost stage/sql/Opening tables 25 -localhost stage/sql/starting 28 +localhost stage/sql/starting 32 execute dump_stages_global; event_name count_star stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3124,14 +3124,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3285,7 +3285,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3439,7 +3439,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3593,7 +3593,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3747,7 +3747,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3901,7 +3901,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4055,7 +4055,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4209,7 +4209,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4363,7 +4363,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4517,7 +4517,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4671,7 +4671,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4825,7 +4825,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4951,7 +4951,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -5049,7 +5049,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -5147,7 +5147,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result b/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result index d6dd322a70c..ef68b4f69e3 100644 --- a/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result +++ b/mysql-test/suite/perfschema/r/event_aggregate_no_u_no_h.result @@ -203,7 +203,7 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -214,14 +214,14 @@ stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -304,7 +304,7 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 0 user2 localhost stage/sql/closing tables 0 user2 localhost stage/sql/init 0 @@ -320,14 +320,14 @@ stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 4 stage/sql/closing tables 11 stage/sql/init 3 stage/sql/Opening tables 7 -stage/sql/starting 6 +stage/sql/starting 7 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -429,12 +429,12 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -445,14 +445,14 @@ stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -545,12 +545,12 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 0 user3 localhost stage/sql/closing tables 0 user3 localhost stage/sql/init 0 @@ -566,14 +566,14 @@ stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 8 stage/sql/closing tables 21 stage/sql/init 6 stage/sql/Opening tables 13 -stage/sql/starting 12 +stage/sql/starting 14 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -685,17 +685,17 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -706,14 +706,14 @@ stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -816,17 +816,17 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 0 user4 localhost stage/sql/closing tables 0 user4 localhost stage/sql/init 0 @@ -842,14 +842,14 @@ stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 12 stage/sql/closing tables 31 stage/sql/init 9 stage/sql/Opening tables 19 -stage/sql/starting 18 +stage/sql/starting 21 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -971,22 +971,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 6 +user1 localhost stage/sql/starting 7 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -997,14 +997,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 24 +stage/sql/starting 28 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1113,22 +1113,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 6 +user2 localhost stage/sql/starting 7 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1139,14 +1139,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 25 +stage/sql/starting 29 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1255,22 +1255,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 6 +user3 localhost stage/sql/starting 7 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1281,14 +1281,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 26 +stage/sql/starting 30 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1396,22 +1396,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 6 +user4 localhost stage/sql/starting 7 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1422,14 +1422,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 27 +stage/sql/starting 31 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1536,22 +1536,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1562,14 +1562,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1677,22 +1677,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1703,14 +1703,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1817,22 +1817,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1843,14 +1843,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -1957,22 +1957,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -1983,14 +1983,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2097,22 +2097,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -2123,14 +2123,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2237,22 +2237,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -2263,14 +2263,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2377,22 +2377,22 @@ user1 localhost stage/sql/checking permissions 4 user1 localhost stage/sql/closing tables 11 user1 localhost stage/sql/init 3 user1 localhost stage/sql/Opening tables 7 -user1 localhost stage/sql/starting 7 +user1 localhost stage/sql/starting 8 user2 localhost stage/sql/checking permissions 4 user2 localhost stage/sql/closing tables 10 user2 localhost stage/sql/init 3 user2 localhost stage/sql/Opening tables 6 -user2 localhost stage/sql/starting 7 +user2 localhost stage/sql/starting 8 user3 localhost stage/sql/checking permissions 4 user3 localhost stage/sql/closing tables 10 user3 localhost stage/sql/init 3 user3 localhost stage/sql/Opening tables 6 -user3 localhost stage/sql/starting 7 +user3 localhost stage/sql/starting 8 user4 localhost stage/sql/checking permissions 4 user4 localhost stage/sql/closing tables 10 user4 localhost stage/sql/init 3 user4 localhost stage/sql/Opening tables 6 -user4 localhost stage/sql/starting 7 +user4 localhost stage/sql/starting 8 execute dump_stages_user; user event_name count_star execute dump_stages_host; @@ -2403,14 +2403,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2543,14 +2543,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2683,14 +2683,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2823,14 +2823,14 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_stages_history; event_name count(event_name) stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -2970,7 +2970,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3110,7 +3110,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3250,7 +3250,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3390,7 +3390,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3530,7 +3530,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3670,7 +3670,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3810,7 +3810,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -3950,7 +3950,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4090,7 +4090,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4230,7 +4230,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4370,7 +4370,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star user1 localhost statement/com/Error 0 @@ -4482,7 +4482,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4566,7 +4566,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; @@ -4650,7 +4650,7 @@ stage/sql/checking permissions 16 stage/sql/closing tables 41 stage/sql/init 12 stage/sql/Opening tables 25 -stage/sql/starting 28 +stage/sql/starting 32 execute dump_statements_account; user host event_name count_star execute dump_statements_user; diff --git a/mysql-test/suite/perfschema/r/nesting.result b/mysql-test/suite/perfschema/r/nesting.result index ba655d3c329..dd8bdcc990d 100644 --- a/mysql-test/suite/perfschema/r/nesting.result +++ b/mysql-test/suite/perfschema/r/nesting.result @@ -128,8 +128,8 @@ relative_event_id relative_end_event_id event_name comment nesting_event_type re 11 11 stage/sql/Executing (stage) STATEMENT 0 12 12 stage/sql/End of update loop (stage) STATEMENT 0 13 13 stage/sql/Query end (stage) STATEMENT 0 -14 14 stage/sql/Commit (stage) STATEMENT 0 -15 15 stage/sql/closing tables (stage) STATEMENT 0 +14 14 stage/sql/closing tables (stage) STATEMENT 0 +15 15 stage/sql/Query end (stage) STATEMENT 0 16 16 stage/sql/Starting cleanup (stage) STATEMENT 0 17 17 stage/sql/Freeing items (stage) STATEMENT 0 18 18 wait/io/socket/sql/client_connection send STATEMENT 0 @@ -152,8 +152,8 @@ relative_event_id relative_end_event_id event_name comment nesting_event_type re 35 35 stage/sql/Executing (stage) STATEMENT 24 36 36 stage/sql/End of update loop (stage) STATEMENT 24 37 37 stage/sql/Query end (stage) STATEMENT 24 -38 38 stage/sql/Commit (stage) STATEMENT 24 -39 39 stage/sql/closing tables (stage) STATEMENT 24 +38 38 stage/sql/closing tables (stage) STATEMENT 24 +39 39 stage/sql/Query end (stage) STATEMENT 24 40 40 stage/sql/Starting cleanup (stage) STATEMENT 24 41 41 stage/sql/Freeing items (stage) STATEMENT 24 42 42 wait/io/socket/sql/client_connection send STATEMENT 24 @@ -176,8 +176,8 @@ relative_event_id relative_end_event_id event_name comment nesting_event_type re 59 59 stage/sql/Executing (stage) STATEMENT 48 60 60 stage/sql/End of update loop (stage) STATEMENT 48 61 61 stage/sql/Query end (stage) STATEMENT 48 -62 62 stage/sql/Commit (stage) STATEMENT 48 -63 63 stage/sql/closing tables (stage) STATEMENT 48 +62 62 stage/sql/closing tables (stage) STATEMENT 48 +63 63 stage/sql/Query end (stage) STATEMENT 48 64 64 stage/sql/Starting cleanup (stage) STATEMENT 48 65 65 stage/sql/Freeing items (stage) STATEMENT 48 66 66 wait/io/socket/sql/client_connection send STATEMENT 48 @@ -203,8 +203,8 @@ select "With a third part to make things complete" as payload NULL NULL 84 84 stage/sql/Executing (stage) STATEMENT 72 85 85 stage/sql/End of update loop (stage) STATEMENT 72 86 86 stage/sql/Query end (stage) STATEMENT 72 -87 87 stage/sql/Commit (stage) STATEMENT 72 -88 88 stage/sql/closing tables (stage) STATEMENT 72 +87 87 stage/sql/closing tables (stage) STATEMENT 72 +88 88 stage/sql/Query end (stage) STATEMENT 72 89 89 stage/sql/Starting cleanup (stage) STATEMENT 72 90 92 stage/sql/Freeing items (stage) STATEMENT 72 91 91 wait/io/socket/sql/client_connection send STAGE 90 @@ -222,8 +222,8 @@ select "With a third part to make things complete" as payload NULL NULL 102 102 stage/sql/Executing (stage) STATEMENT 93 103 103 stage/sql/End of update loop (stage) STATEMENT 93 104 104 stage/sql/Query end (stage) STATEMENT 93 -105 105 stage/sql/Commit (stage) STATEMENT 93 -106 106 stage/sql/closing tables (stage) STATEMENT 93 +105 105 stage/sql/closing tables (stage) STATEMENT 93 +106 106 stage/sql/Query end (stage) STATEMENT 93 107 107 stage/sql/Starting cleanup (stage) STATEMENT 93 108 110 stage/sql/Freeing items (stage) STATEMENT 93 109 109 wait/io/socket/sql/client_connection send STAGE 108 @@ -239,8 +239,8 @@ select "With a third part to make things complete" as payload NULL NULL 119 119 stage/sql/Executing (stage) STATEMENT 111 120 120 stage/sql/End of update loop (stage) STATEMENT 111 121 121 stage/sql/Query end (stage) STATEMENT 111 -122 122 stage/sql/Commit (stage) STATEMENT 111 -123 123 stage/sql/closing tables (stage) STATEMENT 111 +122 122 stage/sql/closing tables (stage) STATEMENT 111 +123 123 stage/sql/Query end (stage) STATEMENT 111 124 124 stage/sql/Starting cleanup (stage) STATEMENT 111 125 125 stage/sql/Freeing items (stage) STATEMENT 111 126 126 wait/io/socket/sql/client_connection send STATEMENT 111 @@ -263,8 +263,8 @@ select "With a third part to make things complete" as payload NULL NULL 143 143 stage/sql/Executing (stage) STATEMENT 132 144 144 stage/sql/End of update loop (stage) STATEMENT 132 145 145 stage/sql/Query end (stage) STATEMENT 132 -146 146 stage/sql/Commit (stage) STATEMENT 132 -147 147 stage/sql/closing tables (stage) STATEMENT 132 +146 146 stage/sql/closing tables (stage) STATEMENT 132 +147 147 stage/sql/Query end (stage) STATEMENT 132 148 148 stage/sql/Starting cleanup (stage) STATEMENT 132 149 149 stage/sql/Freeing items (stage) STATEMENT 132 150 150 wait/io/socket/sql/client_connection send STATEMENT 132 diff --git a/mysql-test/suite/perfschema/r/stage_mdl_global.result b/mysql-test/suite/perfschema/r/stage_mdl_global.result index b9eda506700..48aca9e5529 100644 --- a/mysql-test/suite/perfschema/r/stage_mdl_global.result +++ b/mysql-test/suite/perfschema/r/stage_mdl_global.result @@ -10,10 +10,10 @@ username event_name nesting_event_type username event_name nesting_event_type user1 stage/sql/starting STATEMENT user1 stage/sql/starting STATEMENT +user1 stage/sql/starting STATEMENT user1 stage/sql/Query end STATEMENT -user1 stage/sql/Commit STATEMENT user1 stage/sql/closing tables STATEMENT -user1 stage/sql/Commit implicit STATEMENT +user1 stage/sql/Query end STATEMENT user1 stage/sql/Starting cleanup STATEMENT user1 stage/sql/Freeing items STATEMENT user1 stage/sql/Reset for next command STATEMENT diff --git a/mysql-test/suite/perfschema/r/stage_mdl_table.result b/mysql-test/suite/perfschema/r/stage_mdl_table.result index 5ba0ba04fca..b9b2dc1257d 100644 --- a/mysql-test/suite/perfschema/r/stage_mdl_table.result +++ b/mysql-test/suite/perfschema/r/stage_mdl_table.result @@ -19,10 +19,10 @@ username event_name nesting_event_type user1 stage/sql/Sending data STATEMENT user1 stage/sql/End of update loop STATEMENT user1 stage/sql/Query end STATEMENT -user1 stage/sql/Commit STATEMENT user1 stage/sql/closing tables STATEMENT user1 stage/sql/Unlocking tables STATEMENT user1 stage/sql/closing tables STATEMENT +user1 stage/sql/Query end STATEMENT user1 stage/sql/Starting cleanup STATEMENT user1 stage/sql/Freeing items STATEMENT user1 stage/sql/Reset for next command STATEMENT diff --git a/mysql-test/suite/perfschema/r/threads_history.result b/mysql-test/suite/perfschema/r/threads_history.result index aaf2cd09e31..364a5f6f9e3 100644 --- a/mysql-test/suite/perfschema/r/threads_history.result +++ b/mysql-test/suite/perfschema/r/threads_history.result @@ -167,16 +167,16 @@ stage/sql/Freeing items stage/sql/Reset for next command stage/sql/starting stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command EVENT_NAME stage/sql/starting stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command @@ -189,29 +189,29 @@ stage/sql/Optimizing stage/sql/Executing stage/sql/End of update loop stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command stage/sql/starting stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command stage/sql/starting stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command stage/sql/starting stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command @@ -585,16 +585,16 @@ stage/sql/Freeing items stage/sql/Reset for next command stage/sql/starting stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command EVENT_NAME stage/sql/starting stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command @@ -607,29 +607,29 @@ stage/sql/Optimizing stage/sql/Executing stage/sql/End of update loop stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command stage/sql/starting stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command stage/sql/starting stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command stage/sql/starting stage/sql/Query end -stage/sql/Commit stage/sql/closing tables +stage/sql/Query end stage/sql/Starting cleanup stage/sql/Freeing items stage/sql/Reset for next command diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index 6d6b78054f9..a63fa4a4b6b 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -137,6 +137,7 @@ wait_for_pending_deadlock_kill(THD *thd, rpl_group_info *rgi) PSI_stage_info old_stage; mysql_mutex_lock(&thd->LOCK_wakeup_ready); + thd->set_time_for_next_stage(); thd->ENTER_COND(&thd->COND_wakeup_ready, &thd->LOCK_wakeup_ready, &stage_waiting_for_deadlock_kill, &old_stage); while (rgi->killed_for_retry == rpl_group_info::RETRY_KILL_PENDING) @@ -394,12 +395,12 @@ do_gco_wait(rpl_group_info *rgi, group_commit_orderer *gco, if (wait_count > entry->count_committing_event_groups) { DEBUG_SYNC(thd, "rpl_parallel_start_waiting_for_prior"); + thd->set_time_for_next_stage(); thd->ENTER_COND(&gco->COND_group_commit_orderer, &entry->LOCK_parallel_entry, &stage_waiting_for_prior_transaction_to_start_commit, old_stage); *did_enter_cond= true; - thd->set_time_for_next_stage(); do { if (!rgi->worker_error && unlikely(thd->check_killed(1))) @@ -487,10 +488,10 @@ do_ftwrl_wait(rpl_group_info *rgi, */ if (unlikely(sub_id > entry->pause_sub_id)) { + thd->set_time_for_next_stage(); thd->ENTER_COND(&entry->COND_parallel_entry, &entry->LOCK_parallel_entry, &stage_waiting_for_ftwrl, old_stage); *did_enter_cond= true; - thd->set_time_for_next_stage(); do { if (entry->force_abort || rgi->worker_error) @@ -553,9 +554,9 @@ pool_mark_busy(rpl_parallel_thread_pool *pool, THD *thd) mysql_mutex_lock(&pool->LOCK_rpl_thread_pool); if (thd) { + thd->set_time_for_next_stage(); thd->ENTER_COND(&pool->COND_rpl_thread_pool, &pool->LOCK_rpl_thread_pool, &stage_waiting_for_rpl_thread_pool, &old_stage); - thd->set_time_for_next_stage(); } while (pool->busy) { @@ -694,9 +695,9 @@ rpl_pause_for_ftwrl(THD *thd) mysql_mutex_lock(&e->LOCK_parallel_entry); }); } + thd->set_time_for_next_stage(); thd->ENTER_COND(&e->COND_parallel_entry, &e->LOCK_parallel_entry, &stage_waiting_for_ftwrl_threads_to_pause, &old_stage); - thd->set_time_for_next_stage(); while (e->pause_sub_id < (uint64)ULONGLONG_MAX && e->last_committed_sub_id < e->pause_sub_id && !err) @@ -2420,6 +2421,7 @@ rpl_parallel_entry::choose_thread(rpl_group_info *rgi, bool *did_enter_cond, STRING_WITH_LEN("now SIGNAL wait_queue_ready")); };); #endif + rli->sql_driver_thd->set_time_for_next_stage(); rli->sql_driver_thd->ENTER_COND(&thr->COND_rpl_thread_queue, &thr->LOCK_rpl_thread, &stage_waiting_for_room_in_worker_thread, @@ -2717,6 +2719,7 @@ rpl_parallel::wait_for_workers_idle(THD *thd) e= (struct rpl_parallel_entry *)my_hash_element(&domain_hash, i); mysql_mutex_lock(&e->LOCK_parallel_entry); ++e->need_sub_id_signal; + thd->set_time_for_next_stage(); thd->ENTER_COND(&e->COND_parallel_entry, &e->LOCK_parallel_entry, &stage_waiting_for_workers_idle, &old_stage); while (e->current_sub_id > e->last_committed_sub_id) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 45a9b123cd9..1ad43d865e8 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -803,8 +803,10 @@ int close_thread_tables(THD *thd) { TABLE *table; int error= 0; + PSI_stage_info org_stage; DBUG_ENTER("close_thread_tables"); + thd->backup_stage(&org_stage); THD_STAGE_INFO(thd, stage_closing_tables); #ifdef EXTRA_DEBUG @@ -917,7 +919,10 @@ int close_thread_tables(THD *thd) we will exit this function a few lines below. */ if (! thd->lex->requires_prelocking()) - DBUG_RETURN(0); + { + error= 0; + goto end; + } /* We are in the top-level statement of a prelocked statement, @@ -928,7 +933,10 @@ int close_thread_tables(THD *thd) thd->locked_tables_mode= LTM_LOCK_TABLES; if (thd->locked_tables_mode == LTM_LOCK_TABLES) - DBUG_RETURN(0); + { + error= 0; + goto end; + } thd->leave_locked_tables_mode(); @@ -957,6 +965,8 @@ int close_thread_tables(THD *thd) while (thd->open_tables) (void) close_thread_table(thd, &thd->open_tables); +end: + THD_STAGE_INFO(thd, org_stage); DBUG_RETURN(error); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index bfec3c9fcf0..ad1abc4c4a0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6166,13 +6166,11 @@ finish: if (unlikely(thd->is_error()) || (thd->variables.option_bits & OPTION_MASTER_SQL_ERROR)) { - THD_STAGE_INFO(thd, stage_rollback); trans_rollback_stmt(thd); } else { /* If commit fails, we should be able to reset the OK status. */ - THD_STAGE_INFO(thd, stage_commit); thd->get_stmt_da()->set_overwrite_status(true); trans_commit_stmt(thd); thd->get_stmt_da()->set_overwrite_status(false); @@ -6200,7 +6198,6 @@ finish: one of storage engines (e.g. due to deadlock). Rollback transaction in all storage engines including binary log. */ - THD_STAGE_INFO(thd, stage_rollback_implicit); trans_rollback_implicit(thd); thd->release_transactional_locks(); } @@ -6210,7 +6207,6 @@ finish: DBUG_ASSERT(! thd->in_sub_stmt); if (!(thd->variables.option_bits & OPTION_GTID_BEGIN)) { - THD_STAGE_INFO(thd, stage_commit_implicit); /* If commit fails, we should be able to reset the OK status. */ thd->get_stmt_da()->set_overwrite_status(true); /* Commit the normal transaction if one is active. */ diff --git a/sql/transaction.cc b/sql/transaction.cc index 1e855781f44..0d1ad6fb252 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -255,11 +255,15 @@ bool trans_begin(THD *thd, uint flags) bool trans_commit(THD *thd) { int res; + PSI_stage_info org_stage; DBUG_ENTER("trans_commit"); if (trans_check(thd)) DBUG_RETURN(TRUE); + thd->backup_stage(&org_stage); + THD_STAGE_INFO(thd, stage_commit); + thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); @@ -288,6 +292,7 @@ bool trans_commit(THD *thd) DBUG_ASSERT(thd->m_transaction_psi == NULL); trans_track_end_trx(thd); + THD_STAGE_INFO(thd, org_stage); DBUG_RETURN(MY_TEST(res)); } @@ -320,6 +325,10 @@ bool trans_commit_implicit(THD *thd) if (thd->in_multi_stmt_transaction_mode() || (thd->variables.option_bits & OPTION_TABLE_LOCK)) { + PSI_stage_info org_stage; + thd->backup_stage(&org_stage); + THD_STAGE_INFO(thd, stage_commit_implicit); + /* Safety if one did "drop table" on locked tables */ if (!thd->locked_tables_mode) thd->variables.option_bits&= ~OPTION_TABLE_LOCK; @@ -327,6 +336,8 @@ bool trans_commit_implicit(THD *thd) ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); res= MY_TEST(ha_commit_trans(thd, TRUE)); + + THD_STAGE_INFO(thd, org_stage); } thd->variables.option_bits&= ~(OPTION_BEGIN | OPTION_KEEP_LOG); @@ -361,11 +372,15 @@ bool trans_commit_implicit(THD *thd) bool trans_rollback(THD *thd) { int res; + PSI_stage_info org_stage; DBUG_ENTER("trans_rollback"); if (trans_check(thd)) DBUG_RETURN(TRUE); + thd->backup_stage(&org_stage); + THD_STAGE_INFO(thd, stage_rollback); + thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); @@ -384,6 +399,7 @@ bool trans_rollback(THD *thd) trans_track_end_trx(thd); + THD_STAGE_INFO(thd, org_stage); DBUG_RETURN(MY_TEST(res)); } @@ -406,8 +422,12 @@ bool trans_rollback(THD *thd) bool trans_rollback_implicit(THD *thd) { int res; + PSI_stage_info org_stage; DBUG_ENTER("trans_rollback_implict"); + thd->backup_stage(&org_stage); + THD_STAGE_INFO(thd, stage_rollback_implicit); + /* Always commit/rollback statement transaction before manipulating with the normal one. @@ -434,6 +454,7 @@ bool trans_rollback_implicit(THD *thd) trans_track_end_trx(thd); + THD_STAGE_INFO(thd, org_stage); DBUG_RETURN(MY_TEST(res)); } @@ -469,11 +490,17 @@ bool trans_commit_stmt(THD *thd) if (thd->transaction->stmt.ha_list) { + PSI_stage_info org_stage; + thd->backup_stage(&org_stage); + THD_STAGE_INFO(thd, stage_commit); + res= ha_commit_trans(thd, FALSE); if (! thd->in_active_multi_stmt_transaction()) { trans_reset_one_shot_chistics(thd); } + + THD_STAGE_INFO(thd, org_stage); } mysql_mutex_assert_not_owner(&LOCK_prepare_ordered); @@ -532,9 +559,15 @@ bool trans_rollback_stmt(THD *thd) if (thd->transaction->stmt.ha_list) { + PSI_stage_info org_stage; + thd->backup_stage(&org_stage); + THD_STAGE_INFO(thd, stage_rollback); + ha_rollback_trans(thd, FALSE); if (! thd->in_active_multi_stmt_transaction()) trans_reset_one_shot_chistics(thd); + + THD_STAGE_INFO(thd, org_stage); } #ifdef HAVE_REPLICATION From f838b2d7998f18ac2a1bb9d56081aac6e563de1e Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 8 Mar 2024 15:18:21 +0200 Subject: [PATCH 052/106] MDEV-33623 Partitioning is broken on big endian architectures MDEV-33502 Slowdown when running nested statement with many partitions caused this error as I failed to take into account bigendian architectures. This patch also introduces bitmap_import() and bitmap_export() to be used when one wants to store bitmaps in files/logs in a portable way. Reviewed-by: Kristian Nielsen --- include/my_bitmap.h | 32 +++--- mysys/my_bitmap.c | 134 ++++++++++++++++++------- sql/log_event.cc | 22 ++-- sql/log_event_old.cc | 27 +++-- sql/log_event_server.cc | 26 +++-- sql/opt_range.cc | 3 +- storage/spider/ha_spider.cc | 44 ++++---- storage/spider/spd_db_handlersocket.cc | 6 +- storage/spider/spd_db_mysql.cc | 6 +- unittest/mysys/bitmap-t.c | 20 +++- 10 files changed, 202 insertions(+), 118 deletions(-) diff --git a/include/my_bitmap.h b/include/my_bitmap.h index 5f722d9fbec..5589236664d 100644 --- a/include/my_bitmap.h +++ b/include/my_bitmap.h @@ -79,64 +79,68 @@ extern void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2); extern void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2); extern void bitmap_invert(MY_BITMAP *map); extern void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2); +/* Functions to export/import bitmaps to an architecture independent format */ +extern void bitmap_export(uchar *to, MY_BITMAP *map); +extern void bitmap_import(MY_BITMAP *map, uchar *from); extern uint bitmap_lock_set_next(MY_BITMAP *map); extern void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit); #define my_bitmap_map_bytes sizeof(my_bitmap_map) #define my_bitmap_map_bits (my_bitmap_map_bytes*8) -#define bitmap_buffer_size(bits) (MY_ALIGN(bits, my_bitmap_map_bits)*my_bitmap_map_bytes) -#define no_bytes_in_map(map) (((map)->n_bits + 7)/8) +#define bitmap_buffer_size(bits) (MY_ALIGN((bits), my_bitmap_map_bits)/8) +#define my_bitmap_buffer_size(map) bitmap_buffer_size((map)->n_bits) +#define no_bytes_in_export_map(map) (((map)->n_bits + 7)/8) #define no_words_in_map(map) (((map)->n_bits + (my_bitmap_map_bits-1))/my_bitmap_map_bits) -#define bytes_word_aligned(bytes) (8*((bytes + 7)/8)) /* Fast, not thread safe, bitmap functions */ /* The following functions must be compatible with create_last_bit_mask()! */ static inline void bitmap_set_bit(MY_BITMAP *map,uint bit) { - uchar *b= (uchar*) map->bitmap + bit / 8; DBUG_ASSERT(bit < map->n_bits); - *b= (uchar) (*b | 1U << (bit & 7)); + map->bitmap[bit/my_bitmap_map_bits]|= + (1ULL << (bit & (my_bitmap_map_bits-1))); } static inline void bitmap_flip_bit(MY_BITMAP *map,uint bit) { - uchar *b= (uchar*) map->bitmap + bit / 8; DBUG_ASSERT(bit < map->n_bits); - *b= (uchar) (*b ^ 1U << (bit & 7)); + map->bitmap[bit/my_bitmap_map_bits]^= + (1ULL << (bit & (my_bitmap_map_bits-1))); } static inline void bitmap_clear_bit(MY_BITMAP *map,uint bit) { - uchar *b= (uchar*) map->bitmap + bit / 8; DBUG_ASSERT(bit < map->n_bits); - *b= (uchar) (*b & ~(1U << (bit & 7))); + map->bitmap[bit/my_bitmap_map_bits]&= + ~(1ULL << (bit & (my_bitmap_map_bits-1))); } static inline uint bitmap_is_set(const MY_BITMAP *map,uint bit) { - const uchar *b= (const uchar*) map->bitmap + bit / 8; DBUG_ASSERT(bit < map->n_bits); - return !!(*b & (1U << (bit & 7))); + return (!!(map->bitmap[bit/my_bitmap_map_bits] & + (1ULL << (bit & (my_bitmap_map_bits-1))))); } /* Return true if bitmaps are equal */ static inline my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) { DBUG_ASSERT(map1->n_bits == map2->n_bits); - return (memcmp(map1->bitmap, map2->bitmap, 8*(no_words_in_map(map1))) == 0); + return (memcmp(map1->bitmap, map2->bitmap, + my_bitmap_buffer_size(map1)) == 0); } #define bitmap_clear_all(MAP) \ - { memset((MAP)->bitmap, 0, 8*no_words_in_map((MAP))); } + { memset((MAP)->bitmap, 0, my_bitmap_buffer_size(MAP)); } static inline void bitmap_set_all(const MY_BITMAP *map) { if (map->n_bits) { - memset(map->bitmap, 0xFF, 8*(no_words_in_map(map)-1)); + memset(map->bitmap, 0xFF, my_bitmap_map_bytes * (no_words_in_map(map)-1)); DBUG_ASSERT(map->bitmap + no_words_in_map(map)-1 == map->last_word_ptr); *map->last_word_ptr= ~map->last_bit_mask; } diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index 6a646a35fd1..68747f57702 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -18,7 +18,7 @@ */ /* - Handling of uchar arrays as large bitmaps. + Handling of my_bitmap_map (ulonglong) arrays as large bitmaps. API limitations (or, rather asserted safety assumptions, to encourage correct programming) @@ -222,12 +222,14 @@ void my_bitmap_free(MY_BITMAP *map) my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) { - uchar *value= ((uchar*) map->bitmap) + (bitmap_bit / 8); - uchar bit= 1 << ((bitmap_bit) & 7); - uchar res= (*value) & bit; + my_bitmap_map *value, bit, res; DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit); + + value= map->bitmap + (bitmap_bit/my_bitmap_map_bits); + bit= 1ULL << (bitmap_bit & (my_bitmap_map_bits-1)); + res= *value & bit; *value|= bit; - return res; + return MY_TEST(res); } @@ -269,13 +271,14 @@ my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit) { - uchar *byte= (uchar*) map->bitmap + (bitmap_bit / 8); - uchar bit= 1 << ((bitmap_bit) & 7); - uchar res= (*byte) & bit; + my_bitmap_map *value, bit, res; DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit); - *byte&= ~bit; - return res; + value= map->bitmap + (bitmap_bit/my_bitmap_map_bits); + bit= 1ULL << (bitmap_bit & (my_bitmap_map_bits-1)); + res= *value & bit; + *value&= ~bit; + return MY_TEST(res); } @@ -310,23 +313,24 @@ uint bitmap_set_next(MY_BITMAP *map) void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) { - uint prefix_bytes, prefix_bits, d; - uchar *m= (uchar *)map->bitmap; + uint prefix, prefix_bits; + my_bitmap_map *value= map->bitmap; DBUG_ASSERT_BITMAP(map); DBUG_ASSERT(prefix_size <= map->n_bits || prefix_size == (uint) ~0); - set_if_smaller(prefix_size, map->n_bits); - if ((prefix_bytes= prefix_size / 8)) - memset(m, 0xff, prefix_bytes); - m+= prefix_bytes; - if ((prefix_bits= prefix_size & 7)) + + if ((prefix= prefix_size / my_bitmap_map_bits)) { - *(m++)= (1 << prefix_bits)-1; - // As the prefix bits are set, lets count this byte too as a prefix byte. - prefix_bytes ++; + my_bitmap_map *end= value+prefix; + do + { + *value++= ~(my_bitmap_map) 0; + } while (value < end); } - if ((d= no_bytes_in_map(map)-prefix_bytes)) - memset(m, 0, d); + if ((prefix_bits= prefix_size & (my_bitmap_map_bits-1))) + *value++= (1ULL << prefix_bits)-1; + while (value <= map->last_word_ptr) + *value++= 0; DBUG_ASSERT_BITMAP(map); } @@ -343,10 +347,9 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) { - uint prefix_mask= last_byte_mask(prefix_size); - uchar *m= (uchar*) map->bitmap; - uchar *end_prefix= m+(prefix_size-1)/8; - uchar *end; + my_bitmap_map *value= map->bitmap; + my_bitmap_map *end= value+ (prefix_size/my_bitmap_map_bits); + uint prefix_bits; /* Empty prefix is always true */ if (!prefix_size) @@ -354,16 +357,18 @@ my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) DBUG_ASSERT_BITMAP_AND_BIT(map, prefix_size-1); - while (m < end_prefix) - if (*m++ != 0xff) + while (value < end) + if (*value++ != ~(my_bitmap_map) 0) return 0; - end= ((uchar*) map->last_word_ptr) + sizeof(*map->last_word_ptr)-1; - if (*m != prefix_mask) - return 0; - - while (++m <= end) - if (*m != 0) + if ((prefix_bits= prefix_size & (my_bitmap_map_bits-1))) + { + if (*value++ != (1ULL << prefix_bits)-1) + return 0; + } + end= map->last_word_ptr; + while (value <= end) + if (*value++ != 0) return 0; return 1; } @@ -700,3 +705,64 @@ void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit) bitmap_clear_bit(map, bitmap_bit); bitmap_unlock(map); } +/* + Functions to export/import bitmaps to an architecture independent format + (low_byte_first) +*/ + +#ifdef WORDS_BIGENDIAN +/* Big endian machines, like powerpc or s390x */ + +void bitmap_export(uchar *to, MY_BITMAP *map) +{ + my_bitmap_map *value; + uint length; + uchar buff[my_bitmap_map_bytes]; + + for (value= map->bitmap ; value < map->last_word_ptr ; value++) + { + int8store(to, *value); + to+= 8; + } + int8store(buff, *value); + + /* We want length & 7 to return a serie 8,2,3,4,5,6,7, 8,2,3,... */ + length= 1+ ((no_bytes_in_export_map(map) + 7) & 7); + memcpy(to, buff, length); +} + + +void bitmap_import(MY_BITMAP *map, uchar *from) +{ + my_bitmap_map *value; + uint length; + uchar buff[my_bitmap_map_bytes]; + + for (value= map->bitmap ; value < map->last_word_ptr ; value++) + { + *value= uint8korr(from); + from+= 8; + } + bzero(buff, sizeof(buff)); + + /* We want length & 7 to return a serie 8,2,3,4,5,6,7, 8,2,3,... */ + length= 1+ ((no_bytes_in_export_map(map) + 7) & 7); + memcpy(buff, from, length); + *value= uint8korr(buff) & ~map->last_bit_mask; +} + +#else + +/* Little endian machines, like intel and amd */ + +void bitmap_export(uchar *to, MY_BITMAP *map) +{ + memcpy(to, (uchar*) map->bitmap, no_bytes_in_export_map(map)); +} + +void bitmap_import(MY_BITMAP *map, uchar *from) +{ + memcpy((uchar*) map->bitmap, from, no_bytes_in_export_map(map)); + *map->last_word_ptr&= ~map->last_bit_mask; +} +#endif /* WORDS_BIGENDIAN */ diff --git a/sql/log_event.cc b/sql/log_event.cc index 5719296746a..6779419e682 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3392,10 +3392,9 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len, false))) { DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); - memcpy(m_cols.bitmap, ptr_after_width, (m_width + 7) / 8); - create_last_bit_mask(&m_cols); // Needed to fix last part of bitmap + bitmap_import(&m_cols, ptr_after_width); + DBUG_DUMP("m_cols", (uchar*) ptr_after_width, no_bytes_in_export_map(&m_cols)); ptr_after_width+= (m_width + 7) / 8; - DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); } else DBUG_VOID_RETURN; @@ -3414,11 +3413,9 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len, false))) { DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); - memcpy(m_cols_ai.bitmap, ptr_after_width, (m_width + 7) / 8); - create_last_bit_mask(&m_cols_ai); // Needed to fix last part of bitmap + bitmap_import(&m_cols_ai, ptr_after_width); + DBUG_DUMP("m_cols_ai", ptr_after_width, no_bytes_in_export_map(&m_cols_ai)); ptr_after_width+= (m_width + 7) / 8; - DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap, - no_bytes_in_map(&m_cols_ai)); } else DBUG_VOID_RETURN; @@ -3497,9 +3494,10 @@ int Rows_log_event::get_data_size() uchar *end= net_store_length(buf, m_width); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", - return (int)(6 + no_bytes_in_map(&m_cols) + (end - buf) + - (general_type_code == UPDATE_ROWS_EVENT ? no_bytes_in_map(&m_cols_ai) : 0) + - m_rows_cur - m_rows_buf);); + return (int) (6 + no_bytes_in_export_map(&m_cols) + (end - buf) + + (general_type_code == UPDATE_ROWS_EVENT ? + no_bytes_in_export_map(&m_cols_ai) : 0) + + m_rows_cur - m_rows_buf);); int data_size= 0; Log_event_type type= get_type_code(); bool is_v2_event= LOG_EVENT_IS_ROW_V2(type); @@ -3514,11 +3512,11 @@ int Rows_log_event::get_data_size() { data_size= ROWS_HEADER_LEN_V1; } - data_size+= no_bytes_in_map(&m_cols); + data_size+= no_bytes_in_export_map(&m_cols); data_size+= (uint) (end - buf); if (general_type_code == UPDATE_ROWS_EVENT) - data_size+= no_bytes_in_map(&m_cols_ai); + data_size+= no_bytes_in_export_map(&m_cols_ai); data_size+= (uint) (m_rows_cur - m_rows_buf); return data_size; diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index a7d5519276c..29465e30efb 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1229,17 +1229,12 @@ Old_rows_log_event::Old_rows_log_event(const uchar *buf, uint event_len, false))) { DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); - memcpy(m_cols.bitmap, ptr_after_width, (m_width + 7) / 8); - create_last_bit_mask(&m_cols); // Needed to fix last part of bitmap + bitmap_import(&m_cols, ptr_after_width); + DBUG_DUMP("m_cols", ptr_after_width, no_bytes_in_export_map(&m_cols)); ptr_after_width+= (m_width + 7) / 8; - DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); } else - { - // Needed because my_bitmap_init() does not set it to null on failure - m_cols.bitmap= NULL; DBUG_VOID_RETURN; - } const uchar* const ptr_rows_data= (const uchar*) ptr_after_width; size_t const data_size= event_len - (ptr_rows_data - (const uchar *) buf); @@ -1257,8 +1252,6 @@ Old_rows_log_event::Old_rows_log_event(const uchar *buf, uint event_len, m_rows_cur= m_rows_end; memcpy(m_rows_buf, ptr_rows_data, data_size); } - else - m_cols.bitmap= 0; // to not free it DBUG_VOID_RETURN; } @@ -1277,10 +1270,10 @@ int Old_rows_log_event::get_data_size() uchar *end= net_store_length(buf, (m_width + 7) / 8); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", - return (int)(6 + no_bytes_in_map(&m_cols) + (end - buf) + - m_rows_cur - m_rows_buf);); + return (int)(6 + no_bytes_in_export_map(&m_cols) + (end - buf) + + m_rows_cur - m_rows_buf);); int data_size= ROWS_HEADER_LEN; - data_size+= no_bytes_in_map(&m_cols); + data_size+= no_bytes_in_export_map(&m_cols); data_size+= (uint) (end - buf); data_size+= (uint) (m_rows_cur - m_rows_buf); @@ -1798,6 +1791,8 @@ bool Old_rows_log_event::write_data_body() */ uchar sbuf[MAX_INT_WIDTH]; my_ptrdiff_t const data_size= m_rows_cur - m_rows_buf; + uint bitmap_size= no_bytes_in_export_map(&m_cols); + uchar *bitmap; // This method should not be reached. assert(0); @@ -1809,10 +1804,14 @@ bool Old_rows_log_event::write_data_body() DBUG_DUMP("m_width", sbuf, (size_t) (sbuf_end - sbuf)); res= res || write_data(sbuf, (size_t) (sbuf_end - sbuf)); - DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); - res= res || write_data((uchar*)m_cols.bitmap, no_bytes_in_map(&m_cols)); + bitmap= (uchar*) my_alloca(bitmap_size); + bitmap_export(bitmap, &m_cols); + + DBUG_DUMP("m_cols", bitmap, no_bytes_in_export_map(&m_cols)); + res= res || write_data(bitmap, no_bytes_in_export_map(&m_cols)); DBUG_DUMP("rows", m_rows_buf, data_size); res= res || write_data(m_rows_buf, (size_t) data_size); + my_afree(bitmap); return res; diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 744a41ca782..cafac67a51d 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -6085,30 +6085,37 @@ bool Rows_log_event::write_data_body() my_ptrdiff_t const data_size= m_rows_cur - m_rows_buf; bool res= false; uchar *const sbuf_end= net_store_length(sbuf, (size_t) m_width); + uint bitmap_size= no_bytes_in_export_map(&m_cols); + uchar *bitmap; DBUG_ASSERT(static_cast(sbuf_end - sbuf) <= sizeof(sbuf)); DBUG_DUMP("m_width", sbuf, (size_t) (sbuf_end - sbuf)); res= res || write_data(sbuf, (size_t) (sbuf_end - sbuf)); - DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); - res= res || write_data((uchar*)m_cols.bitmap, no_bytes_in_map(&m_cols)); + bitmap= (uchar*) my_alloca(bitmap_size); + bitmap_export(bitmap, &m_cols); + + DBUG_DUMP("m_cols", bitmap, bitmap_size); + res= res || write_data(bitmap, bitmap_size); /* TODO[refactor write]: Remove the "down cast" here (and elsewhere). */ if (get_general_type_code() == UPDATE_ROWS_EVENT) { - DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap, - no_bytes_in_map(&m_cols_ai)); - res= res || write_data((uchar*)m_cols_ai.bitmap, - no_bytes_in_map(&m_cols_ai)); + DBUG_ASSERT(m_cols.n_bits == m_cols_ai.n_bits); + bitmap_export(bitmap, &m_cols_ai); + + DBUG_DUMP("m_cols_ai", bitmap, bitmap_size); + res= res || write_data(bitmap, bitmap_size); } DBUG_DUMP("rows", m_rows_buf, data_size); res= res || write_data(m_rows_buf, (size_t) data_size); + my_afree(bitmap); return res; - } + bool Rows_log_event::write_compressed() { uchar *m_rows_buf_tmp= m_rows_buf; @@ -8391,10 +8398,7 @@ void Update_rows_log_event::init(MY_BITMAP const *cols) { /* Cols can be zero if this is a dummy binrows event */ if (likely(cols != NULL)) - { - memcpy(m_cols_ai.bitmap, cols->bitmap, no_bytes_in_map(cols)); - create_last_bit_mask(&m_cols_ai); // Needed to fix last part of bitmap - } + bitmap_copy(&m_cols_ai, cols); } } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 7bf712cff2b..9c47639596d 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6781,8 +6781,7 @@ ROR_INTERSECT_INFO* ror_intersect_init(const PARAM *param) void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src) { dst->param= src->param; - memcpy(dst->covered_fields.bitmap, src->covered_fields.bitmap, - no_bytes_in_map(&src->covered_fields)); + bitmap_copy(&dst->covered_fields, &src->covered_fields); dst->out_rows= src->out_rows; dst->is_covering= src->is_covering; dst->index_records= src->index_records; diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index eaf2ac9289d..60e2bc198a8 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -379,19 +379,19 @@ int ha_spider::open( spider_bulk_malloc(spider_current_trx, 16, MYF(MY_WME | MY_ZEROFILL), &wide_handler, sizeof(SPIDER_WIDE_HANDLER), &searched_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &ft_discard_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &position_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &idx_read_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &idx_write_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &rnd_read_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &rnd_write_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &partition_handler, (uint) sizeof(SPIDER_PARTITION_HANDLER), NullS) @@ -399,19 +399,19 @@ int ha_spider::open( spider_bulk_malloc(spider_current_trx, 16, MYF(MY_WME | MY_ZEROFILL), &wide_handler, sizeof(SPIDER_WIDE_HANDLER), &searched_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &ft_discard_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &position_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &idx_read_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &idx_write_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &rnd_read_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &rnd_write_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), NullS) #endif ) @@ -436,9 +436,9 @@ int ha_spider::open( wide_handler->top_share = table->s; owner->wide_handler_owner = TRUE; memset(wide_handler->ft_discard_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); memset(wide_handler->searched_bitmap, 0, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); wide_handler_alloc = TRUE; if (!share && !spider_get_share(name, table, thd, this, &error_num)) @@ -1386,9 +1386,9 @@ int ha_spider::reset() if (!is_clone) { memset(wide_handler->ft_discard_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); memset(wide_handler->searched_bitmap, 0, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); } while (wide_handler->condition) { @@ -1678,7 +1678,7 @@ int ha_spider::index_init( bitmap_set_all(table->read_set); if (is_clone) memset(wide_handler->searched_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); } } @@ -4114,7 +4114,7 @@ ha_rows ha_spider::multi_range_read_info_const( bitmap_set_all(table->read_set); if (is_clone) memset(wide_handler->searched_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); } } @@ -4179,7 +4179,7 @@ ha_rows ha_spider::multi_range_read_info( bitmap_set_all(table->read_set); if (is_clone) memset(wide_handler->searched_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); } } @@ -7183,7 +7183,7 @@ int ha_spider::rnd_init( bitmap_set_all(table->read_set); if (is_clone) memset(wide_handler->searched_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); } set_select_column_mode(); diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc index 656ea991619..e5b4607d6b0 100644 --- a/storage/spider/spd_db_handlersocket.cc +++ b/storage/spider/spd_db_handlersocket.cc @@ -4484,7 +4484,7 @@ int spider_handlersocket_handler::init() &link_for_hash, sizeof(SPIDER_LINK_FOR_HASH) * share->link_count, &minimum_select_bitmap, - table ? sizeof(uchar) * no_bytes_in_map(table->read_set) : 0, + table ? sizeof(uchar) * my_bitmap_buffer_size(table->read_set) : 0, NullS)) ) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -6159,7 +6159,7 @@ void spider_handlersocket_handler::minimum_select_bitmap_create() TABLE *table = spider->get_table(); Field **field_p; DBUG_ENTER("spider_handlersocket_handler::minimum_select_bitmap_create"); - memset(minimum_select_bitmap, 0, no_bytes_in_map(table->read_set)); + memset(minimum_select_bitmap, 0, my_bitmap_buffer_size(table->read_set)); if ( spider->use_index_merge || #ifdef HA_CAN_BULK_ACCESS @@ -6174,7 +6174,7 @@ void spider_handlersocket_handler::minimum_select_bitmap_create() table_share->primary_key == MAX_KEY ) { /* need all columns */ - memset(minimum_select_bitmap, 0xFF, no_bytes_in_map(table->read_set)); + memset(minimum_select_bitmap, 0xFF, my_bitmap_buffer_size(table->read_set)); DBUG_VOID_RETURN; } else { /* need primary key columns */ diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index ee215add995..cc9af072c8d 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -8591,7 +8591,7 @@ int spider_mbase_handler::init() &link_for_hash, sizeof(SPIDER_LINK_FOR_HASH) * share->link_count, &minimum_select_bitmap, - table ? sizeof(uchar) * no_bytes_in_map(table->read_set) : 0, + table ? sizeof(uchar) * my_bitmap_buffer_size(table->read_set) : 0, NullS)) ) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -15750,7 +15750,7 @@ void spider_mbase_handler::minimum_select_bitmap_create() Field **field_p; DBUG_ENTER("spider_mbase_handler::minimum_select_bitmap_create"); DBUG_PRINT("info",("spider this=%p", this)); - memset(minimum_select_bitmap, 0, no_bytes_in_map(table->read_set)); + memset(minimum_select_bitmap, 0, my_bitmap_buffer_size(table->read_set)); if ( spider->use_index_merge || #ifdef HA_CAN_BULK_ACCESS @@ -15765,7 +15765,7 @@ void spider_mbase_handler::minimum_select_bitmap_create() table_share->primary_key == MAX_KEY ) { /* need all columns */ - memset(minimum_select_bitmap, 0xFF, no_bytes_in_map(table->read_set)); + memset(minimum_select_bitmap, 0xFF, my_bitmap_buffer_size(table->read_set)); DBUG_VOID_RETURN; } else { /* need primary key columns */ diff --git a/unittest/mysys/bitmap-t.c b/unittest/mysys/bitmap-t.c index 1f438dd67c5..3698d76654d 100644 --- a/unittest/mysys/bitmap-t.c +++ b/unittest/mysys/bitmap-t.c @@ -512,10 +512,14 @@ error: my_bool test_copy(MY_BITMAP *map, uint bitsize) { - my_bitmap_map buff[16]; - MY_BITMAP map2; + my_bitmap_map buff[16], buff2[16], buff3[16]; + MY_BITMAP map2, map3; + uint rnd_bit; + my_bitmap_init(&map2, buff, sizeof(buff)*8, FALSE); - memset((void*) buff, 0xff, sizeof(buff)); + my_bitmap_init(&map3, buff2, sizeof(buff)*8, FALSE); + bitmap_set_all(&map2); + bitmap_set_all(&map3); bitsize= MY_MIN(bitsize, map2.n_bits); bitmap_copy(map, &map2); @@ -524,6 +528,15 @@ my_bool test_copy(MY_BITMAP *map, uint bitsize) diag("bitmap_copy failed on bitsize %d", bitsize); return 1; } + bitmap_set_prefix(&map2, rnd_bit= get_rand_bit(bitsize)+1); + bitmap_export((uchar*) buff3, &map2); + bitmap_import(&map3, (uchar*) buff3); + if (!bitmap_cmp(&map2, &map3)) + { + diag("bitmap_export/bitmap_import failed on bitsize %d rnd_bit: %d", + bitsize, rnd_bit); + return 1; + } return 0; } @@ -639,6 +652,7 @@ my_bool do_test(uint bitsize) bitmap_clear_all(&map); if (test_copy(&map,bitsize)) goto error; + bitmap_clear_all(&map); if (test_bitmap_exists_intersection(&map, bitsize)) goto error; return FALSE; From 648d2da8f25606374066f67e9cfb82d9860e12e6 Mon Sep 17 00:00:00 2001 From: Daniele Sciascia Date: Thu, 7 Mar 2024 15:24:43 +0100 Subject: [PATCH 053/106] MDEV-33540 Avoid writes to TRX_SYS page during mariabackup operations Fix a scenario where `mariabackup --prepare` fails with assertion `!m_modifications || !recv_no_log_write' in `mtr_t::commit()`. This happens if the prepare step of the backup encounters a data directory which happens to store wsrep xid position in TRX SYS page (this is no longer the case since 10.3.5). And since MDEV-17458, `trx_rseg_array_init()` handles this case by copying the xid position to rollback segments, before clearing the xid from TRX SYS page. However, this step should be avoided when `trx_rseg_array_init()` is invoked from mariabackup. The relevant code was surrounded by the condition `srv_operation == SRV_OPERATION_NORMAL`. An additional check ensures that we are not trying to copy a xid position which has already zeroed. --- storage/innobase/trx/trx0rseg.cc | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index be52373d03b..c393ba862e7 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -207,6 +207,11 @@ bool trx_rseg_read_wsrep_checkpoint(const trx_rsegf_t* rseg_header, XID& xid) @return whether the WSREP XID is present */ static bool trx_rseg_init_wsrep_xid(const page_t* page, XID& xid) { + if (memcmp(TRX_SYS + TRX_SYS_WSREP_XID_INFO + page, + field_ref_zero, TRX_SYS_WSREP_XID_LEN) == 0) { + return false; + } + if (mach_read_from_4(TRX_SYS + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_MAGIC_N_FLD + page) @@ -570,10 +575,6 @@ static void trx_rseg_init_binlog_info(const page_t* page) + TRX_SYS + page); trx_sys.recovered_binlog_is_legacy_pos= true; } - -#ifdef WITH_WSREP - trx_rseg_init_wsrep_xid(page, trx_sys.recovered_wsrep_xid); -#endif } /** Initialize or recover the rollback segments at startup. */ @@ -605,7 +606,11 @@ dberr_t trx_rseg_array_init() + sys->frame); trx_rseg_init_binlog_info(sys->frame); #ifdef WITH_WSREP - wsrep_sys_xid.set(&trx_sys.recovered_wsrep_xid); + if (trx_rseg_init_wsrep_xid( + sys->frame, trx_sys.recovered_wsrep_xid)) { + wsrep_sys_xid.set( + &trx_sys.recovered_wsrep_xid); + } #endif } @@ -662,7 +667,7 @@ dberr_t trx_rseg_array_init() } #ifdef WITH_WSREP - if (!wsrep_sys_xid.is_null()) { + if (srv_operation == SRV_OPERATION_NORMAL && !wsrep_sys_xid.is_null()) { /* Upgrade from a version prior to 10.3.5, where WSREP XID was stored in TRX_SYS page. If no rollback segment has a WSREP XID set, From b3d507ff13311a4c2c40a0ff614494084a1eb6e9 Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 9 Mar 2024 12:09:43 +0200 Subject: [PATCH 054/106] Suppressed new warning for rpl_get_lock on amd-freebsd and aarch64-macos --- mysql-test/suite/rpl/t/rpl_get_lock.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/suite/rpl/t/rpl_get_lock.test b/mysql-test/suite/rpl/t/rpl_get_lock.test index f0a11e712f6..c6f2f6ec83b 100644 --- a/mysql-test/suite/rpl/t/rpl_get_lock.test +++ b/mysql-test/suite/rpl/t/rpl_get_lock.test @@ -5,6 +5,7 @@ CALL mtr.add_suppression("Unsafe statement written to the binary log using state call mtr.add_suppression("Could not read packet:.* errno: 11 "); # The following one comes from calling dirty_close on client side call mtr.add_suppression("Could not read packet:.* errno: 2 "); +call mtr.add_suppression("Could not read packet:.* errno: 35 "); --enable_query_log let $org_log_warnings=`select @@global.log_warnings`; From 015f69a779b2585fab733bedd2df899c3c7dfa4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 11 Mar 2024 09:52:59 +0200 Subject: [PATCH 055/106] MDEV-14448 fixup: clang -Wunused-function --- client/mysql.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/mysql.cc b/client/mysql.cc index c917501fdc3..e47fb9b2981 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2018,11 +2018,13 @@ static int get_options(int argc, char **argv) return(0); } +#ifdef USE_LIBEDIT_INTERFACE static inline void reset_prompt(char *in_string, bool *ml_comment) { glob_buffer.length(0); *ml_comment = false; *in_string = 0; } +#endif static int read_and_execute(bool interactive) { From 09ea2dc788a660e2dd747eca7aa73d9fefb92f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 11 Mar 2024 09:53:04 +0200 Subject: [PATCH 056/106] MDEV-33209 Stack overflow in main.json_debug_nonembedded due to incorrect debug injection In the JSON functions, the debug injection for stack overflows is inaccurate and may cause actual stack overflows. Let us simply inject stack overflow errors without actually relying on the ability of check_stack_overrun() to do so. Reviewed by: Rucha Deodhar --- sql/item_jsonfunc.cc | 48 ++++++++++++-------------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index b0a792e94b9..5d350358b5d 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -20,20 +20,14 @@ #include "item.h" #include "sql_parse.h" // For check_stack_overrun -/* - Allocating memory and *also* using it (reading and - writing from it) because some build instructions cause - compiler to optimize out stack_used_up. Since alloca() - here depends on stack_used_up, it doesnt get executed - correctly and causes json_debug_nonembedded to fail - ( --error ER_STACK_OVERRUN_NEED_MORE does not occur). -*/ -#define ALLOCATE_MEM_ON_STACK(A) do \ - { \ - uchar *array= (uchar*)alloca(A); \ - bzero(array, A); \ - my_checksum(0, array, A); \ - } while(0) +#ifndef DBUG_OFF +static int dbug_json_check_min_stack_requirement() +{ + my_error(ER_STACK_OVERRUN_NEED_MORE, MYF(ME_FATAL), + my_thread_stack_size, my_thread_stack_size, STACK_MIN_SIZE); + return 1; +} +#endif /* Compare ASCII string against the string with the specified @@ -151,11 +145,8 @@ int json_path_parts_compare( int res, res2; DBUG_EXECUTE_IF("json_check_min_stack_requirement", - { - long arbitrary_var; - long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); - ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE); - }); + return dbug_json_check_min_stack_requirement();); + if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL)) return 1; @@ -1210,11 +1201,7 @@ static int check_contains(json_engine_t *js, json_engine_t *value) json_engine_t loc_js; bool set_js; DBUG_EXECUTE_IF("json_check_min_stack_requirement", - { - long arbitrary_var; - long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); - ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE); - }); + return dbug_json_check_min_stack_requirement();); if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL)) return 1; @@ -2128,13 +2115,8 @@ err_return: static int do_merge(String *str, json_engine_t *je1, json_engine_t *je2) { - DBUG_EXECUTE_IF("json_check_min_stack_requirement", - { - long arbitrary_var; - long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); - ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE); - }); + return dbug_json_check_min_stack_requirement();); if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL)) return 1; @@ -2471,11 +2453,7 @@ static int do_merge_patch(String *str, json_engine_t *je1, json_engine_t *je2, bool *empty_result) { DBUG_EXECUTE_IF("json_check_min_stack_requirement", - { - long arbitrary_var; - long stack_used_up= (available_stack_size(current_thd->thread_stack, &arbitrary_var)); - ALLOCATE_MEM_ON_STACK(my_thread_stack_size-stack_used_up-STACK_MIN_SIZE); - }); + return dbug_json_check_min_stack_requirement();); if (check_stack_overrun(current_thd, STACK_MIN_SIZE , NULL)) return 1; From 67abdb9f33820a8209727e7d3b7c5cdb09b7c537 Mon Sep 17 00:00:00 2001 From: mariadb-DebarunBanerjee Date: Mon, 11 Mar 2024 15:59:56 +0530 Subject: [PATCH 057/106] MDEV-33593 Auto increment deadlock error causes ASSERT in subsequent save point innodb.autoinc_debug: Correct the test case for predictable deadlock. --- mysql-test/suite/innodb/r/autoinc_debug.result | 2 ++ mysql-test/suite/innodb/t/autoinc_debug.test | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mysql-test/suite/innodb/r/autoinc_debug.result b/mysql-test/suite/innodb/r/autoinc_debug.result index 94406a80ab5..1baf5d2573b 100644 --- a/mysql-test/suite/innodb/r/autoinc_debug.result +++ b/mysql-test/suite/innodb/r/autoinc_debug.result @@ -119,8 +119,10 @@ connect con2, localhost, root,,; START TRANSACTION; # T2: Wait for (T1) row lock on t2 after acquiring GAP Lock on t1 UPDATE t1 SET col2 = 20 where col1 = 10; +SET DEBUG_SYNC='lock_wait_suspend_thread_enter SIGNAL t2_waiting'; INSERT INTO t2 values(100); connection default; +SET DEBUG_SYNC='now WAIT_FOR t2_waiting'; # T3: Wait for (T2) II row Lock on t1 after acquiring Auto Increment Lock on t1 SET DEBUG_SYNC='lock_wait_suspend_thread_enter SIGNAL t3_waiting'; INSERT INTO t1(col2) SELECT col2 from t1; diff --git a/mysql-test/suite/innodb/t/autoinc_debug.test b/mysql-test/suite/innodb/t/autoinc_debug.test index 80168c9d7e1..e48df6e81f7 100644 --- a/mysql-test/suite/innodb/t/autoinc_debug.test +++ b/mysql-test/suite/innodb/t/autoinc_debug.test @@ -110,9 +110,11 @@ INSERT INTO t2 values(100); START TRANSACTION; --echo # T2: Wait for (T1) row lock on t2 after acquiring GAP Lock on t1 UPDATE t1 SET col2 = 20 where col1 = 10; +SET DEBUG_SYNC='lock_wait_suspend_thread_enter SIGNAL t2_waiting'; --send INSERT INTO t2 values(100) --connection default +SET DEBUG_SYNC='now WAIT_FOR t2_waiting'; --echo # T3: Wait for (T2) II row Lock on t1 after acquiring Auto Increment Lock on t1 SET DEBUG_SYNC='lock_wait_suspend_thread_enter SIGNAL t3_waiting'; --send INSERT INTO t1(col2) SELECT col2 from t1 From 0a9cec229abb055d8a6538a0ab97dfa152359b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 11 Mar 2024 16:14:54 +0200 Subject: [PATCH 058/106] MDEV-33642: MemorySanitizer: SEGV on unknown address on shutdown signal_hand(): Remove the cmake -DWITH_DBUG_TRACE=ON instrumentation. It can cause a crash on shutdown when the only other thread is waiting in wait_for_signal_thread_to_end(). --- sql/mysqld.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 50b2698ccba..4d0a891faf9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3209,7 +3209,6 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) sigset_t set; int sig; my_thread_init(); // Init new thread - DBUG_ENTER("signal_hand"); signal_thread_in_use= 1; /* @@ -3263,7 +3262,6 @@ pthread_handler_t signal_hand(void *arg __attribute__((unused))) { DBUG_PRINT("quit",("signal_handler: calling my_thread_end()")); my_thread_end(); - DBUG_LEAVE; // Must match DBUG_ENTER() signal_thread_in_use= 0; pthread_exit(0); // Safety return 0; // Avoid compiler warnings From 4ac8c4c820ebcff3571a2c67acc4fc41510b2d33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 12 Mar 2024 09:20:36 +0200 Subject: [PATCH 059/106] MDEV-24167 fixup: Stricter assertion log_free_check(): Assert that the current thread is not holding lock_sys.latch in any mode. This fixes up commit 5f2dcd112b3b052dc20766b055ab63bcc1ff1c33 --- storage/innobase/log/log0log.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 2bd056feae0..666e4418d27 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -1067,7 +1067,7 @@ NOTE that this function may only be called while not holding any synchronization objects except dict_sys.latch. */ void log_free_check() { - ut_ad(!lock_sys.is_writer()); + ut_ad(!lock_sys.is_holder()); if (log_sys.check_flush_or_checkpoint()) log_check_margins(); } From 428a67315294c32bedc4bbc48d898ae7a47893c4 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Tue, 12 Mar 2024 16:13:49 +0700 Subject: [PATCH 060/106] MDEV-33549: Incorrect handling of UPDATE in PS mode in case a table's colum declared as NOT NULL UPDATE statement that is run in PS mode and uses positional parameter handles columns declared with the clause DEFAULT NULL incorrectly in case the clause DEFAULT is passed as actual value for the positional parameter of the prepared statement. Similar issue happens in case an expression specified in the DEFAULT clause of table's column definition. The reason for incorrect processing of columns declared as DEFAULT NULL is that setting of null flag for a field being updated was missed in implementation of the method Item_param::assign_default(). The reason for incorrect handling of an expression in DEFAULT clause is also missed saving of a field inside implementation of the method Item_param::assign_default(). --- mysql-test/main/ps.result | 50 ++++++++++++++++++++++++++++++++++++ mysql-test/main/ps.test | 54 +++++++++++++++++++++++++++++++++++++++ sql/item.cc | 16 +++++++++--- sql/item.h | 6 +++++ 4 files changed, 123 insertions(+), 3 deletions(-) diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index 4ed0e71a29a..aeed24f253b 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -5933,5 +5933,55 @@ a b 2 30 DROP TABLE t1, t2; # +# MDEV-33549: Incorrect handling of UPDATE in PS mode in case a table's colum declared as NOT NULL +# +CREATE TABLE t1 (a INT, b INT DEFAULT NULL); +INSERT INTO t1 VALUES (20, 30); +EXECUTE IMMEDIATE 'UPDATE t1 SET b=?' USING DEFAULT; +SELECT * FROM t1; +a b +20 NULL +# Run twice the same update in PS mode to check +# that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1 SET b=?'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; +# Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1; +# The same test for multi-table update +CREATE TABLE t1 (a INT, b INT DEFAULT NULL); +CREATE TABLE t2 (a INT, c INT DEFAULT NULL); +INSERT INTO t1 VALUES (20, 30); +INSERT INTO t2 VALUES (20, 30); +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET b=? WHERE t1.a=t2.a' USING DEFAULT; +SELECT * FROM t1; +a b +20 NULL +# Run twice the same multi-table update in PS mode to check +# that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1,t2 SET b=? WHERE t1.a=t2.a'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; +DEALLOCATE PREPARE stmt; +# Clean up +DROP TABLE t1; +# This time checks that a default value for table's column +# represented by a function call is handled correctly on UPDATE in PS mode +CREATE TABLE t1 (a INT, b INT DEFAULT MOD(a, 3)); +INSERT INTO t1 VALUES (20, 30); +EXECUTE IMMEDIATE 'UPDATE t1, t2 SET b=? WHERE t1.a=t2.a' USING DEFAULT; +SELECT * FROM t1; +a b +20 2 +# Run twice the same multi-table update in PS mode to check +# that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1, t2 SET b=? WHERE t1.a=t2.a'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; +# Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; +# # End of 10.4 tests # diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test index e710050cb48..61d1513fa0b 100644 --- a/mysql-test/main/ps.test +++ b/mysql-test/main/ps.test @@ -5362,6 +5362,60 @@ SELECT * FROM t2; # Cleanup DROP TABLE t1, t2; +--echo # +--echo # MDEV-33549: Incorrect handling of UPDATE in PS mode in case a table's colum declared as NOT NULL +--echo # + +CREATE TABLE t1 (a INT, b INT DEFAULT NULL); +INSERT INTO t1 VALUES (20, 30); +EXECUTE IMMEDIATE 'UPDATE t1 SET b=?' USING DEFAULT; +SELECT * FROM t1; + +--echo # Run twice the same update in PS mode to check +--echo # that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1 SET b=?'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; + +--echo # Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + +--echo # The same test for multi-table update +CREATE TABLE t1 (a INT, b INT DEFAULT NULL); +CREATE TABLE t2 (a INT, c INT DEFAULT NULL); + +INSERT INTO t1 VALUES (20, 30); +INSERT INTO t2 VALUES (20, 30); + +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET b=? WHERE t1.a=t2.a' USING DEFAULT; +SELECT * FROM t1; +--echo # Run twice the same multi-table update in PS mode to check +--echo # that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1,t2 SET b=? WHERE t1.a=t2.a'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; +DEALLOCATE PREPARE stmt; +--echo # Clean up +DROP TABLE t1; + +--echo # This time checks that a default value for table's column +--echo # represented by a function call is handled correctly on UPDATE in PS mode +CREATE TABLE t1 (a INT, b INT DEFAULT MOD(a, 3)); +INSERT INTO t1 VALUES (20, 30); +EXECUTE IMMEDIATE 'UPDATE t1, t2 SET b=? WHERE t1.a=t2.a' USING DEFAULT; +SELECT * FROM t1; + +--echo # Run twice the same multi-table update in PS mode to check +--echo # that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1, t2 SET b=? WHERE t1.a=t2.a'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; + +--echo # Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; + --echo # --echo # End of 10.4 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 07463b202f9..f70775b86e8 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5064,9 +5064,19 @@ bool Item_param::assign_default(Field *field) } if (m_default_field->default_value) - m_default_field->set_default(); - - return field_conv(field, m_default_field); + { + return m_default_field->default_value->expr->save_in_field(field, 0); + } + else if (m_default_field->is_null()) + { + field->set_null(); + return false; + } + else + { + field->set_notnull(); + return field_conv(field, m_default_field); + } } diff --git a/sql/item.h b/sql/item.h index 9fc5cc4068f..0e8eeae402a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -4000,6 +4000,12 @@ public: Item_param(THD *thd, const LEX_CSTRING *name_arg, uint pos_in_query_arg, uint len_in_query_arg); + void cleanup() override + { + m_default_field= NULL; + Item::cleanup(); + } + enum Type type() const { // Don't pretend to be a constant unless value for this item is set. From cfa8268ef914cde4bfe03b1ae9349849d1384820 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 12 Mar 2024 18:23:51 +0200 Subject: [PATCH 061/106] MDEV-33622 Server crashes when the UPDATE statement (which has duplicate key) is run after setting a low thread_stack This was caused by wrong allocation of variable on stack. (Was allocating 4K of data instead of 512 bytes). No test case as the original MDEV test cases is not usable for mtr. --- include/my_bitmap.h | 1 + sql/sql_update.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/my_bitmap.h b/include/my_bitmap.h index 5589236664d..42a093c5bed 100644 --- a/include/my_bitmap.h +++ b/include/my_bitmap.h @@ -88,6 +88,7 @@ extern void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit); #define my_bitmap_map_bytes sizeof(my_bitmap_map) #define my_bitmap_map_bits (my_bitmap_map_bytes*8) +/* Size in bytes to store 'bits' number of bits */ #define bitmap_buffer_size(bits) (MY_ALIGN((bits), my_bitmap_map_bits)/8) #define my_bitmap_buffer_size(map) bitmap_buffer_size((map)->n_bits) #define no_bytes_in_export_map(map) (((map)->n_bits + 7)/8) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 81910cf651b..8617c41c522 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -257,7 +257,7 @@ static void prepare_record_for_error_message(int error, TABLE *table) Field *field; uint keynr; MY_BITMAP unique_map; /* Fields in offended unique. */ - my_bitmap_map unique_map_buf[bitmap_buffer_size(MAX_FIELDS)]; + my_bitmap_map unique_map_buf[bitmap_buffer_size(MAX_FIELDS)/sizeof(my_bitmap_map)]; DBUG_ENTER("prepare_record_for_error_message"); /* From ac20edd7370043bbbb55ce43c860ede268108be7 Mon Sep 17 00:00:00 2001 From: Dmitry Shulga Date: Wed, 13 Mar 2024 17:46:05 +0700 Subject: [PATCH 062/106] MDEV-33549: Incorrect handling of UPDATE in PS mode in case a table's colum declared as NOT NULL Follow-up to fix comiler warings caused by present of the clause override in declaration of the method Item_param::cleanup --- sql/item.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item.h b/sql/item.h index 0e8eeae402a..9022683118b 100644 --- a/sql/item.h +++ b/sql/item.h @@ -4000,7 +4000,7 @@ public: Item_param(THD *thd, const LEX_CSTRING *name_arg, uint pos_in_query_arg, uint len_in_query_arg); - void cleanup() override + void cleanup() { m_default_field= NULL; Item::cleanup(); From 7828aadd3a529588f508dc9a49391319acc8e570 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 26 Jan 2024 21:50:51 +0100 Subject: [PATCH 063/106] MDEV-33318 ORDER BY COLLATE improperly applied to non-character columns when changing charset from latin1 to utf8, adjust max_length accordingly --- mysql-test/main/ctype_collate.result | 24 ++++++++++++++++++++++++ mysql-test/main/ctype_collate.test | 15 +++++++++++++++ sql/item_strfunc.cc | 4 +++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/ctype_collate.result b/mysql-test/main/ctype_collate.result index ea9e3e96b46..67139883eb6 100644 --- a/mysql-test/main/ctype_collate.result +++ b/mysql-test/main/ctype_collate.result @@ -772,3 +772,27 @@ string # # End of 10.2 tests # +# +# MDEV-33318 ORDER BY COLLATE improperly applied to non-character columns +# +set names utf8; +create table t1 (ts datetime); +insert t1 values ('2024-01-26 21:37:54'), ('2024-01-26 21:37:54'), +('2024-01-26 21:37:54'), ('2024-01-26 21:37:54'), +('2024-01-26 21:37:58'), ('2024-01-26 21:37:58'), +('2024-01-26 21:37:58'), ('2024-01-26 21:38:02'), +('2024-01-26 21:38:02'), ('2024-01-26 21:38:02'); +select * from t1 order by ts collate utf8_bin; +ts +2024-01-26 21:37:54 +2024-01-26 21:37:54 +2024-01-26 21:37:54 +2024-01-26 21:37:54 +2024-01-26 21:37:58 +2024-01-26 21:37:58 +2024-01-26 21:37:58 +2024-01-26 21:38:02 +2024-01-26 21:38:02 +2024-01-26 21:38:02 +drop table t1; +# End of 10.6 tests diff --git a/mysql-test/main/ctype_collate.test b/mysql-test/main/ctype_collate.test index 2366b130e7c..96ad216dd20 100644 --- a/mysql-test/main/ctype_collate.test +++ b/mysql-test/main/ctype_collate.test @@ -357,3 +357,18 @@ SELECT COLUMN_GET(COLUMN_CREATE(0, 'string'),0 AS CHAR CHARACTER SET latin1 COLL --echo # --echo # End of 10.2 tests --echo # + +--echo # +--echo # MDEV-33318 ORDER BY COLLATE improperly applied to non-character columns +--echo # +set names utf8; +create table t1 (ts datetime); +insert t1 values ('2024-01-26 21:37:54'), ('2024-01-26 21:37:54'), + ('2024-01-26 21:37:54'), ('2024-01-26 21:37:54'), + ('2024-01-26 21:37:58'), ('2024-01-26 21:37:58'), + ('2024-01-26 21:37:58'), ('2024-01-26 21:38:02'), + ('2024-01-26 21:38:02'), ('2024-01-26 21:38:02'); +select * from t1 order by ts collate utf8_bin; +drop table t1; + +--echo # End of 10.6 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index f3e1a7877e1..4f4b0a20b29 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3590,7 +3590,9 @@ bool Item_func_set_collation::fix_length_and_dec() } collation.set(m_set_collation, DERIVATION_EXPLICIT, args[0]->collation.repertoire); - max_length= args[0]->max_length; + ulonglong max_char_length= (ulonglong) args[0]->max_char_length(); + fix_char_length_ulonglong(max_char_length * collation.collation->mbmaxlen); + return FALSE; } From 62a9a54a94362b63127aefa4cc3dfe8dc81fee27 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 1 Feb 2024 13:23:26 +0100 Subject: [PATCH 064/106] MDEV-33344 REGEXP empty string inconsistent --- mysql-test/main/func_regexp.result | 22 +++++++++++++++++++--- mysql-test/main/func_regexp.test | 18 +++++++++++++++--- sql/item_cmpfunc.cc | 2 +- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/mysql-test/main/func_regexp.result b/mysql-test/main/func_regexp.result index b883c8188df..e0a4702c095 100644 --- a/mysql-test/main/func_regexp.result +++ b/mysql-test/main/func_regexp.result @@ -110,7 +110,7 @@ R2 R3 deallocate prepare stmt1; drop table t1; -End of 4.1 tests +# End of 4.1 tests SELECT 1 REGEXP NULL; 1 REGEXP NULL NULL @@ -126,7 +126,7 @@ NULL SELECT "ABC" REGEXP BINARY NULL; "ABC" REGEXP BINARY NULL NULL -End of 5.0 tests +# End of 5.0 tests CREATE TABLE t1(a INT, b CHAR(4)); INSERT INTO t1 VALUES (1, '6.1'), (1, '7.0'), (1, '8.0'); PREPARE stmt1 FROM "SELECT a FROM t1 WHERE a=1 AND '7.0' REGEXP b LIMIT 1"; @@ -144,7 +144,7 @@ a 1 DEALLOCATE PREPARE stmt1; DROP TABLE t1; -End of 5.1 tests +# End of 5.1 tests SELECT ' ' REGEXP '[[:blank:]]'; ' ' REGEXP '[[:blank:]]' 1 @@ -163,3 +163,19 @@ SELECT '\t' REGEXP '[[:space:]]'; SELECT REGEXP_INSTR('111222333',2); REGEXP_INSTR('111222333',2) 4 +# End of 10.3 tests +# +# MDEV-33344 REGEXP empty string inconsistent +# +create table t1 (x char(5)); +insert t1 values (''), ('x'); +select 'foo' regexp x from t1 order by x asc; +'foo' regexp x +1 +0 +select 'foo' regexp x from t1 order by x desc; +'foo' regexp x +0 +1 +drop table t1; +# End of 10.5 tests diff --git a/mysql-test/main/func_regexp.test b/mysql-test/main/func_regexp.test index 6d5186269a5..b9e2ef197d6 100644 --- a/mysql-test/main/func_regexp.test +++ b/mysql-test/main/func_regexp.test @@ -55,7 +55,7 @@ execute stmt1 using @a; deallocate prepare stmt1; drop table t1; ---echo End of 4.1 tests +--echo # End of 4.1 tests # @@ -74,7 +74,7 @@ SELECT NULL REGEXP BINARY NULL; SELECT 'A' REGEXP BINARY NULL; SELECT "ABC" REGEXP BINARY NULL; ---echo End of 5.0 tests +--echo # End of 5.0 tests # @@ -91,7 +91,7 @@ DEALLOCATE PREPARE stmt1; DROP TABLE t1; ---echo End of 5.1 tests +--echo # End of 5.1 tests # # MDEV-5820 MySQL Bug #54805 definitions in regex/my_regex.h conflict with /usr/include/regex.h @@ -110,3 +110,15 @@ SELECT '\t' REGEXP '[[:space:]]'; --echo # SELECT REGEXP_INSTR('111222333',2); +--echo # End of 10.3 tests + +--echo # +--echo # MDEV-33344 REGEXP empty string inconsistent +--echo # +create table t1 (x char(5)); +insert t1 values (''), ('x'); +select 'foo' regexp x from t1 order by x asc; +select 'foo' regexp x from t1 order by x desc; +drop table t1; + +--echo # End of 10.5 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d860456a702..d0d1bb841ef 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -6062,8 +6062,8 @@ bool Regexp_processor_pcre::compile(String *pattern, bool send_error) if (!stringcmp(pattern, &m_prev_pattern)) return false; cleanup(); - m_prev_pattern.copy(*pattern); } + m_prev_pattern.copy(*pattern); if (!(pattern= convert_if_needed(pattern, &pattern_converter))) return true; From 424210abd223655520296c0179f62f4cdf85af53 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 11 Jan 2024 00:33:25 +0100 Subject: [PATCH 065/106] cleanup: reduce code duplication --- sql/sql_base.cc | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 1ad43d865e8..7c09c5ac41c 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4739,6 +4739,9 @@ prepare_fk_prelocking_list(THD *thd, Query_tables_list *prelocking_ctx, Query_arena *arena, backup; TABLE *table= table_list->table; + if (!table->file->referenced_by_foreign_key()) + DBUG_RETURN(FALSE); + arena= thd->activate_stmt_arena_if_needed(&backup); table->file->get_parent_foreign_key_list(thd, &fk_list); @@ -4824,16 +4827,12 @@ bool DML_prelocking_strategy::handle_table(THD *thd, return TRUE; } - if (table->file->referenced_by_foreign_key()) - { - if (prepare_fk_prelocking_list(thd, prelocking_ctx, table_list, - need_prelocking, - table_list->trg_event_map)) - return TRUE; - } + if (prepare_fk_prelocking_list(thd, prelocking_ctx, table_list, + need_prelocking, + table_list->trg_event_map)) + return TRUE; } - else if (table_list->slave_fk_event_map && - table->file->referenced_by_foreign_key()) + else if (table_list->slave_fk_event_map) { if (prepare_fk_prelocking_list(thd, prelocking_ctx, table_list, need_prelocking, From bc46f1a7d95c918fc0548c8e23d5173c31c3df60 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 25 Jan 2024 15:00:39 +0100 Subject: [PATCH 066/106] cleanup: remove SEARCH_TYPE from search_pattern_in_file.inc --- mysql-test/include/search_pattern_in_file.inc | 13 +------------ .../binlog/include/print_optional_metadata.inc | 3 +-- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/mysql-test/include/search_pattern_in_file.inc b/mysql-test/include/search_pattern_in_file.inc index 3105f7f9077..d26495ca3ed 100644 --- a/mysql-test/include/search_pattern_in_file.inc +++ b/mysql-test/include/search_pattern_in_file.inc @@ -9,9 +9,6 @@ # # The environment variables SEARCH_FILE and SEARCH_PATTERN must be set # before sourcing this routine. -# SEARCH_TYPE can also be set to either NULL(default) or _gm_ -# NULL is equivalent of using m/SEARCH_PATTERN/gs -# _gm_ is equivalent of using m/SEARCH_RANGE/gm # # Optionally, SEARCH_RANGE can be set to the max number of bytes of the file # to search. If negative, it will search that many bytes at the end of the @@ -83,15 +80,7 @@ perl; close(FILE); $content.= $file_content; } - my @matches; - if (not defined($ENV{SEARCH_TYPE})) - { - @matches=($content =~ /$search_pattern/gs); - } - elsif($ENV{SEARCH_TYPE} == "_gm_") - { - @matches=($content =~ /$search_pattern/gm); - } + my @matches= ($content =~ /$search_pattern/gs); my $res; if (@matches) { diff --git a/mysql-test/suite/binlog/include/print_optional_metadata.inc b/mysql-test/suite/binlog/include/print_optional_metadata.inc index 739903ab190..47feede80ec 100644 --- a/mysql-test/suite/binlog/include/print_optional_metadata.inc +++ b/mysql-test/suite/binlog/include/print_optional_metadata.inc @@ -16,10 +16,9 @@ if ($stop_position) --exec $MYSQL_BINLOG -F --print-table-metadata $_stop_position_opt $binlog_file > $output_file ---let SEARCH_PATTERN= # (?:Columns\(| {8}).* +--let SEARCH_PATTERN= (?m-s:# (?:Columns\(| {8}).*) --let SEARCH_FILE= $output_file --let SEARCH_OUTPUT=matches ---let SEARCH_TYPE="_gm_" --source include/search_pattern_in_file.inc if ($print_primary_key) From 6711540518e6d24f002eaae1b71c93be41389916 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 25 Jan 2024 16:02:45 +0100 Subject: [PATCH 067/106] remove `exit 1` from search_pattern_in_file.inc it broke tests on Windows. Use SEARCH_ABORT instead. also, remove redundant features and simplify --- mysql-test/include/search_pattern_in_file.inc | 44 +++++-------------- .../include/wait_for_pattern_in_file.inc | 13 +++--- 2 files changed, 16 insertions(+), 41 deletions(-) diff --git a/mysql-test/include/search_pattern_in_file.inc b/mysql-test/include/search_pattern_in_file.inc index d26495ca3ed..c229ddab55a 100644 --- a/mysql-test/include/search_pattern_in_file.inc +++ b/mysql-test/include/search_pattern_in_file.inc @@ -48,15 +48,12 @@ # Created: 2011-11-11 mleich # ---error 0,1 perl; use strict; die "SEARCH_FILE not set" unless $ENV{SEARCH_FILE}; my @search_files= glob($ENV{SEARCH_FILE}); my $search_pattern= $ENV{SEARCH_PATTERN} or die "SEARCH_PATTERN not set"; my $search_range= $ENV{SEARCH_RANGE}; - my $silent= $ENV{SEARCH_SILENT}; - my $search_result= 0; my $content; foreach my $search_file (@search_files) { open(FILE, '<', $search_file) || die("Can't open file $search_file: $!"); @@ -81,39 +78,18 @@ perl; $content.= $file_content; } my @matches= ($content =~ /$search_pattern/gs); - my $res; - if (@matches) - { - $res="FOUND " . scalar(@matches); - $search_result= 1; - } - else - { - $res= "NOT FOUND"; - } + my $res=@matches ? "FOUND " . scalar(@matches) : "NOT FOUND"; + $ENV{SEARCH_FILE} =~ s{^.*?([^/\\]+)$}{$1}; - if (!$silent || $search_result) - { - if ($ENV{SEARCH_OUTPUT} eq "matches") - { - foreach (@matches) - { - print $_ . "\n"; - } - } - else - { - print "$res /$search_pattern/ in $ENV{SEARCH_FILE}\n"; + if ($ENV{SEARCH_OUTPUT} eq "matches") { + foreach (@matches) { + print $_ . "\n"; } } - die "$ENV{SEARCH_ABORT}\n" - if $ENV{SEARCH_ABORT} && $res =~ /^$ENV{SEARCH_ABORT}/; - exit($search_result != 1); + elsif ($ENV{SEARCH_ABORT} and $res =~ /^$ENV{SEARCH_ABORT}/) { + die "$res /$search_pattern/ in $ENV{SEARCH_FILE}\n"; + } else { + print "$res /$search_pattern/ in $ENV{SEARCH_FILE}\n"; + } EOF - -let $SEARCH_RESULT= 1; # Found pattern -if ($errno) -{ - let $SEARCH_RESULT= 0; # Did not find pattern -} diff --git a/mysql-test/include/wait_for_pattern_in_file.inc b/mysql-test/include/wait_for_pattern_in_file.inc index 52226acd2da..a551761012f 100644 --- a/mysql-test/include/wait_for_pattern_in_file.inc +++ b/mysql-test/include/wait_for_pattern_in_file.inc @@ -25,23 +25,23 @@ if (!$_timeout) } let $_timeout_counter=`SELECT $_timeout * 10`; -let SEARCH_SILENT=1; - +let SEARCH_ABORT=NOT FOUND; let $_continue= 1; +disable_abort_on_error; while ($_continue) { source include/search_pattern_in_file.inc; - if ($SEARCH_RESULT) + if (!$errno) { # Found match let $_continue= 0; } - if (!$SEARCH_RESULT) + if ($errno) { dec $_timeout_counter; if ($_timeout_counter == 1) { - let $SEARCH_SILENT= 0; + enable_abort_on_error; } if (!$_timeout_counter) { @@ -49,8 +49,7 @@ while ($_continue) } } } - -let SEARCH_SILENT=0; +enable_abort_on_error; --source include/end_include_file.inc --let $keep_include_silent=$wait_save_keep_include_silent From 0e8cda613094523583f4b97923dab12bcdca5626 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 25 Jan 2024 22:39:29 +0100 Subject: [PATCH 068/106] MDEV-33313 Incorrect error message for "ALTER TABLE ... DROP CONSTRAINT ..., DROP col, DROP col" --- mysql-test/main/alter_table.result | 8 ++++++++ mysql-test/main/alter_table.test | 9 +++++++++ sql/sql_table.cc | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result index 38fe52348c5..c3d364b8edb 100644 --- a/mysql-test/main/alter_table.result +++ b/mysql-test/main/alter_table.result @@ -3124,5 +3124,13 @@ CREATE TEMPORARY TABLE t2 LIKE t1; DROP TEMPORARY TABLE t2; DROP TABLE t1; # +# MDEV-33313 Incorrect error message for "ALTER TABLE ... DROP CONSTRAINT ..., DROP col, DROP col" +# +create table t2(id int primary key) engine=innodb; +create table t1(id int primary key, t2_id int, constraint t1_fk_t2_id foreign key(t2_id) references t2(id)) engine=innodb; +alter table t1 drop constraint t1_fk_t2_id, drop t2_id, drop t2_id; +ERROR 42000: Can't DROP COLUMN `t2_id`; check that it exists +drop table t1, t2; +# # End of 10.6 tests # diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test index 051a0b9fd08..053ce29bdee 100644 --- a/mysql-test/main/alter_table.test +++ b/mysql-test/main/alter_table.test @@ -2406,6 +2406,15 @@ CREATE TEMPORARY TABLE t2 LIKE t1; DROP TEMPORARY TABLE t2; DROP TABLE t1; +--echo # +--echo # MDEV-33313 Incorrect error message for "ALTER TABLE ... DROP CONSTRAINT ..., DROP col, DROP col" +--echo # +create table t2(id int primary key) engine=innodb; +create table t1(id int primary key, t2_id int, constraint t1_fk_t2_id foreign key(t2_id) references t2(id)) engine=innodb; +--error ER_CANT_DROP_FIELD_OR_KEY +alter table t1 drop constraint t1_fk_t2_id, drop t2_id, drop t2_id; +drop table t1, t2; + --echo # --echo # End of 10.6 tests --echo # diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 8a918db5542..cfef41b1ab8 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -8804,7 +8804,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, case Alter_drop::CHECK_CONSTRAINT: case Alter_drop::PERIOD: my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop->type_name(), - alter_info->drop_list.head()->name); + drop->name); goto err; case Alter_drop::FOREIGN_KEY: // Leave the DROP FOREIGN KEY names in the alter_info->drop_list. From 61f6dc5e30113e66d53c826093b40ac15fd91bf9 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 18 Dec 2023 17:37:30 +0100 Subject: [PATCH 069/106] perfschema: LOCK_all_status_vars not LOCK_status to iterate over all status variables one should use LOCK_all_status_vars not LOCK_status this fixes sporadic mutex lock inversion in plugins.password_reuse_check: * acl_cache->lock is taken over complex operations that might increment status counters (under LOCK_status). * acl_cache->lock is needed to get the values of Acl% status variables when iterating over status variables --- storage/perfschema/pfs_variable.cc | 64 ++++++++++++------------------ storage/perfschema/pfs_visitor.cc | 3 +- 2 files changed, 26 insertions(+), 41 deletions(-) diff --git a/storage/perfschema/pfs_variable.cc b/storage/perfschema/pfs_variable.cc index e2193cfb8a6..a33fe2edd06 100644 --- a/storage/perfschema/pfs_variable.cc +++ b/storage/perfschema/pfs_variable.cc @@ -766,7 +766,7 @@ bool PFS_status_variable_cache::filter_show_var(const SHOW_VAR *show_var, bool s /** Build an array of SHOW_VARs from the global status array. Expand nested subarrays, filter unwanted variables. - NOTE: Must be done inside of LOCK_status to guard against plugin load/unload. + NOTE: Must be done under LOCK_all_status_vars */ bool PFS_status_variable_cache::init_show_var_array(enum_var_type scope, bool strict) { @@ -885,14 +885,12 @@ char * PFS_status_variable_cache::make_show_var_name(const char* prefix, const c */ bool PFS_status_variable_cache::do_initialize_session(void) { - /* Acquire LOCK_status to guard against plugin load/unload. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + /* Acquire LOCK_all_status_vars to guard against plugin load/unload. */ + mysql_rwlock_rdlock(&LOCK_all_status_vars); bool ret= init_show_var_array(OPT_SESSION, true); - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); return ret; } @@ -921,13 +919,12 @@ int PFS_status_variable_cache::do_materialize_global(void) m_materialized= false; DEBUG_SYNC(m_current_thd, "before_materialize_global_status_array"); - /* Acquire LOCK_status to guard against plugin load/unload. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + /* Acquire LOCK_all_status_vars to guard against plugin load/unload. */ + mysql_rwlock_rdlock(&LOCK_all_status_vars); /* - Build array of SHOW_VARs from global status array. Do this within - LOCK_status to ensure that the array remains unchanged during + Build array of SHOW_VARs from global status array. Do this under + LOCK_all_status_vars to ensure that the array remains unchanged during materialization. */ if (!m_external_init) @@ -950,8 +947,7 @@ int PFS_status_variable_cache::do_materialize_global(void) */ manifest(m_current_thd, m_show_var_array.front(), &status_totals, "", false, true); - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); m_materialized= true; DEBUG_SYNC(m_current_thd, "after_materialize_global_status_array"); @@ -971,13 +967,11 @@ int PFS_status_variable_cache::do_materialize_all(THD* unsafe_thd) m_materialized= false; m_cache.clear(); - /* Avoid recursive acquisition of LOCK_status. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + mysql_rwlock_rdlock(&LOCK_all_status_vars); /* - Build array of SHOW_VARs from global status array. Do this within - LOCK_status to ensure that the array remains unchanged while this + Build array of SHOW_VARs from global status array. Do this under + LOCK_all_status_vars to ensure that the array remains unchanged while this thread is materialized. */ if (!m_external_init) @@ -1001,8 +995,7 @@ int PFS_status_variable_cache::do_materialize_all(THD* unsafe_thd) ret= 0; } - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); return ret; } @@ -1018,13 +1011,11 @@ int PFS_status_variable_cache::do_materialize_session(THD* unsafe_thd) m_materialized= false; m_cache.clear(); - /* Avoid recursive acquisition of LOCK_status. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + mysql_rwlock_rdlock(&LOCK_all_status_vars); /* - Build array of SHOW_VARs from global status array. Do this within - LOCK_status to ensure that the array remains unchanged while this + Build array of SHOW_VARs from global status array. Do this under + LOCK_all_status_vars to ensure that the array remains unchanged while this thread is materialized. */ if (!m_external_init) @@ -1048,8 +1039,7 @@ int PFS_status_variable_cache::do_materialize_session(THD* unsafe_thd) ret= 0; } - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); return ret; } @@ -1066,9 +1056,8 @@ int PFS_status_variable_cache::do_materialize_session(PFS_thread *pfs_thread) m_materialized= false; m_cache.clear(); - /* Acquire LOCK_status to guard against plugin load/unload. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + /* Acquire LOCK_all_status_vars to guard against plugin load/unload. */ + mysql_rwlock_rdlock(&LOCK_all_status_vars); /* The SHOW_VAR array must be initialized externally. */ assert(m_initialized); @@ -1091,8 +1080,7 @@ int PFS_status_variable_cache::do_materialize_session(PFS_thread *pfs_thread) ret= 0; } - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); return ret; } @@ -1111,9 +1099,8 @@ int PFS_status_variable_cache::do_materialize_client(PFS_client *pfs_client) m_materialized= false; m_cache.clear(); - /* Acquire LOCK_status to guard against plugin load/unload. */ - //if (m_current_thd->fill_status_recursion_level++ == 0) - mysql_mutex_lock(&LOCK_status); + /* Acquire LOCK_all_status_vars to guard against plugin load/unload. */ + mysql_rwlock_rdlock(&LOCK_all_status_vars); /* The SHOW_VAR array must be initialized externally. */ assert(m_initialized); @@ -1130,8 +1117,7 @@ int PFS_status_variable_cache::do_materialize_client(PFS_client *pfs_client) */ manifest(m_current_thd, m_show_var_array.front(), &status_totals, "", false, true); - //if (m_current_thd->fill_status_recursion_level-- == 1) - mysql_mutex_unlock(&LOCK_status); + mysql_rwlock_unlock(&LOCK_all_status_vars); m_materialized= true; return 0; @@ -1224,7 +1210,7 @@ Status_variable::Status_variable(const SHOW_VAR *show_var, STATUS_VAR *status_va /** Resolve status value, convert to string. show_var->value is an offset into status_vars. - NOTE: Assumes LOCK_status is held. + NOTE: Assumes LOCK_all_status_vars is held. */ void Status_variable::init(const SHOW_VAR *show_var, STATUS_VAR *status_vars, enum_var_type query_scope) { @@ -1290,7 +1276,7 @@ void sum_account_status(PFS_client *pfs_account, STATUS_VAR *status_totals) /** Reset aggregated status counter stats for account, user and host. - NOTE: Assumes LOCK_status is held. + NOTE: Assumes LOCK_all_status_vars is held. */ void reset_pfs_status_stats() { diff --git a/storage/perfschema/pfs_visitor.cc b/storage/perfschema/pfs_visitor.cc index 92a5c99e13b..7e3027ac9a6 100644 --- a/storage/perfschema/pfs_visitor.cc +++ b/storage/perfschema/pfs_visitor.cc @@ -1356,8 +1356,7 @@ PFS_connection_status_visitor::~PFS_connection_status_visitor() = default; /** Aggregate from global status. */ void PFS_connection_status_visitor::visit_global() { - /* NOTE: Requires lock on LOCK_status. */ - mysql_mutex_assert_owner(&LOCK_status); + /* NOTE: Requires lock on LOCK_all_status_vars. */ add_to_status(m_status_vars, &global_status_var); } From 967a148966a13fe7eb58232403a3c289abff91a8 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 13 Mar 2024 14:41:24 +0530 Subject: [PATCH 070/106] MDEV-33635 innodb.innodb-64k-crash - Found warnings/errors in server log file - Suppress the "Difficult to find free blocks" warning globally to avoid many different test case failing. - Demote the error information in validate_first_page() to note. So first page can recovered from doublewrite buffer and can throw error in case the page wasn't found in doublewrite buffer. --- mysql-test/mysql-test-run.pl | 1 + .../suite/innodb/r/innodb-lru-force-no-free-page.result | 1 - mysql-test/suite/innodb/r/log_file_name.result | 6 +++--- .../suite/innodb/t/innodb-lru-force-no-free-page.test | 2 -- mysql-test/suite/innodb/t/log_file_name.test | 6 +++--- storage/innobase/fsp/fsp0file.cc | 7 ++++--- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index df00402181d..6834a499c6e 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -4510,6 +4510,7 @@ sub extract_warning_lines ($$) { qr/WSREP: Failed to guess base node address/, qr/WSREP: Guessing address for incoming client/, + qr/InnoDB: Difficult to find free blocks in the buffer pool*/, # for UBSAN qr/decimal\.c.*: runtime error: signed integer overflow/, # Disable test for UBSAN on dynamically loaded objects diff --git a/mysql-test/suite/innodb/r/innodb-lru-force-no-free-page.result b/mysql-test/suite/innodb/r/innodb-lru-force-no-free-page.result index 09e53b59d9d..ac3010a101a 100644 --- a/mysql-test/suite/innodb/r/innodb-lru-force-no-free-page.result +++ b/mysql-test/suite/innodb/r/innodb-lru-force-no-free-page.result @@ -1,4 +1,3 @@ -call mtr.add_suppression("InnoDB: Difficult to find free blocks in the buffer pool"); SET @saved_debug = @@SESSION.debug_dbug; SET SESSION debug_dbug="+d,ib_lru_force_no_free_page"; CREATE TABLE t1 (j LONGBLOB) ENGINE = InnoDB; diff --git a/mysql-test/suite/innodb/r/log_file_name.result b/mysql-test/suite/innodb/r/log_file_name.result index 3d48a24d217..9f9268d905e 100644 --- a/mysql-test/suite/innodb/r/log_file_name.result +++ b/mysql-test/suite/innodb/r/log_file_name.result @@ -90,7 +90,7 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -FOUND 1 /\[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err +FOUND 1 /\[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err FOUND 1 /\[ERROR\] InnoDB: Datafile .*u1.*\. Cannot determine the space ID from the first 64 pages/ in mysqld.1.err NOT FOUND /\[Note\] InnoDB: Cannot read first page of .*u2.ibd/ in mysqld.1.err # Fault 7: Missing or wrong data file and innodb_force_recovery @@ -99,11 +99,11 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'innodb' AND support IN ('YES', 'DEFAULT', 'ENABLED'); ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS -FOUND 1 /\[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err +FOUND 1 /\[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err FOUND 1 /InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace/ in mysqld.1.err FOUND 1 /\[ERROR\] InnoDB: Cannot replay rename of tablespace \d+ from '.*u4.ibd' to '.*u6.ibd' because the target file exists/ in mysqld.1.err # restart: --innodb-force-recovery=1 -FOUND 1 /\[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err +FOUND 1 /\[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd/ in mysqld.1.err FOUND 1 /InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace/ in mysqld.1.err FOUND 1 /\[Warning\] InnoDB: Tablespace \d+ was not found at .*u[1-5].ibd, and innodb_force_recovery was set. All redo log for this tablespace will be ignored!/ in mysqld.1.err # restart diff --git a/mysql-test/suite/innodb/t/innodb-lru-force-no-free-page.test b/mysql-test/suite/innodb/t/innodb-lru-force-no-free-page.test index d4f08b5afe6..bbf0e1757c3 100644 --- a/mysql-test/suite/innodb/t/innodb-lru-force-no-free-page.test +++ b/mysql-test/suite/innodb/t/innodb-lru-force-no-free-page.test @@ -2,8 +2,6 @@ --source include/have_debug.inc --source include/not_embedded.inc -call mtr.add_suppression("InnoDB: Difficult to find free blocks in the buffer pool"); - SET @saved_debug = @@SESSION.debug_dbug; SET SESSION debug_dbug="+d,ib_lru_force_no_free_page"; diff --git a/mysql-test/suite/innodb/t/log_file_name.test b/mysql-test/suite/innodb/t/log_file_name.test index 494d256cd11..a95b5b37fb9 100644 --- a/mysql-test/suite/innodb/t/log_file_name.test +++ b/mysql-test/suite/innodb/t/log_file_name.test @@ -218,7 +218,7 @@ EOF --source include/start_mysqld.inc eval $check_no_innodb; -let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +let SEARCH_PATTERN= \[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= \[ERROR\] InnoDB: Datafile .*u1.*\. Cannot determine the space ID from the first 64 pages; @@ -243,7 +243,7 @@ let SEARCH_PATTERN= \[Note\] InnoDB: Cannot read first page of .*u2.ibd; --source include/start_mysqld.inc eval $check_no_innodb; -let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +let SEARCH_PATTERN= \[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace; @@ -256,7 +256,7 @@ let SEARCH_PATTERN= \[ERROR\] InnoDB: Cannot replay rename of tablespace \d+ fro --source include/restart_mysqld.inc -let SEARCH_PATTERN= \[ERROR\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; +let SEARCH_PATTERN= \[Note\] InnoDB: Header page consists of zero bytes in datafile: .*u1.ibd; --source include/search_pattern_in_file.inc let SEARCH_PATTERN= InnoDB: At LSN: \d+: unable to open file .*u[1-5].ibd for tablespace; diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 653c848953a..e08b1749e4e 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -538,9 +538,10 @@ Datafile::validate_first_page(lsn_t* flush_lsn) if (error_txt != NULL) { err_exit: - sql_print_error("InnoDB: %s in datafile: %s, Space ID: %zu, " - "Flags: %zu", error_txt, m_filepath, - m_space_id, m_flags); + sql_print_information( + "InnoDB: %s in datafile: %s, Space ID: %zu, " + "Flags: %zu", error_txt, m_filepath, + m_space_id, m_flags); m_is_valid = false; free_first_page(); return(DB_CORRUPTION); From 7eb6d5aa21c679e2d6fceb8ec9ac727c62738b71 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 14 Mar 2024 09:15:53 +0100 Subject: [PATCH 071/106] update s3.partition result after 57ffcd686ffa --- mysql-test/suite/s3/partition.result | 2 -- 1 file changed, 2 deletions(-) diff --git a/mysql-test/suite/s3/partition.result b/mysql-test/suite/s3/partition.result index bc411be9cf6..5d00661b1bc 100644 --- a/mysql-test/suite/s3/partition.result +++ b/mysql-test/suite/s3/partition.result @@ -57,8 +57,6 @@ ERROR HY000: Table 't2' is read only ALTER TABLE t2 ANALYZE PARTITION p3; Table Op Msg_type Msg_text s3.t2 analyze status Table 's3.t2' is read only -s3.t2 analyze status Engine-independent statistics collected -s3.t2 analyze status OK SELECT count(*) FROM t2; count(*) 6 From 49cf702ee54040cefcab67f6758c233a6370f5d0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 14 Mar 2024 10:53:49 +0100 Subject: [PATCH 072/106] build failure with cmake < 3.10 cmake bug #14362 --- cmake/cpack_rpm.cmake | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 414b4f6a902..60b7c15935e 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -163,8 +163,8 @@ SET(CPACK_RPM_server_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*" "%config(noreplace) ${INSTALL_SYSCONFDIR}/logrotate.d/mysql" - "%caps(cap_ipc_lock=pe) %{_sbindir}/mysqld" ) + SET(CPACK_RPM_common_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONFDIR}/my.cnf") SET(CPACK_RPM_shared_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*") SET(CPACK_RPM_client_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*") @@ -180,6 +180,13 @@ MACRO(SETA var) ENDFOREACH() ENDMACRO(SETA) +IF (CMAKE_VERSION VERSION_GREATER 3.10.0) + # cmake bug #14362 + SETA(CPACK_RPM_server_USER_FILELIST + "%caps(cap_ipc_lock=pe) %{_sbindir}/mysqld" + ) +ENDIF() + SETA(CPACK_RPM_client_PACKAGE_OBSOLETES "mysql-client" "MySQL-client" From 9d5a8bd663cb06161201a6870eb0d07f06382b9d Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Wed, 13 Mar 2024 16:05:42 +0300 Subject: [PATCH 073/106] MDEV-33665: MSAN failure due to uninitialized Item_func::not_null_tables_cache eliminate_item_equal() uses quick_fix_field() for Item objects it creates. It computes some of their attributes on its own (see update_used_tables() call) but it doesn't update not_null_tables_cache. Recompute not_null_tables_cache also. Not computing it is currently harmless, except for producing MSAN error when some other code propagates the wrong value of not_null_tables_cache to other item. --- sql/sql_select.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f762cfd7ac4..aac35d6ef17 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -16209,6 +16209,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, if (!eq_item || eq_item->set_cmp_func(thd)) return 0; + eq_item->eval_not_null_tables(0); eq_item->quick_fix_field(); } current_sjm= field_sjm; @@ -16266,6 +16267,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, { res->quick_fix_field(); res->update_used_tables(); + res->eval_not_null_tables(0); } return res; From 51e3f1daf54309d14fe8db438024d88aa110e86a Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 14 Mar 2024 15:31:46 +0100 Subject: [PATCH 074/106] cmake: append to the array correctly it was generating broken spec files --- cmake/cpack_rpm.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 60b7c15935e..be94a3387f1 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -182,7 +182,7 @@ ENDMACRO(SETA) IF (CMAKE_VERSION VERSION_GREATER 3.10.0) # cmake bug #14362 - SETA(CPACK_RPM_server_USER_FILELIST + SET(CPACK_RPM_server_USER_FILELIST ${CPACK_RPM_server_USER_FILELIST} "%caps(cap_ipc_lock=pe) %{_sbindir}/mysqld" ) ENDIF() From dbd36bb140a57a7b238576c3b4ed131a77acf7d5 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 14 Mar 2024 10:55:28 +0100 Subject: [PATCH 075/106] after merge fix --- ...erver-core-10.5.postinst => mariadb-server-core-10.6.postinst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename debian/{mariadb-server-core-10.5.postinst => mariadb-server-core-10.6.postinst} (100%) diff --git a/debian/mariadb-server-core-10.5.postinst b/debian/mariadb-server-core-10.6.postinst similarity index 100% rename from debian/mariadb-server-core-10.5.postinst rename to debian/mariadb-server-core-10.6.postinst From bb451d2cade4dbfb6a8d3600e1b9e722cea7a38d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 14 Mar 2024 13:38:13 +0100 Subject: [PATCH 076/106] fix galera tests after 9a132d423ab --- .../suite/galera/r/galera_parallel_apply_lock_table.result | 2 +- mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test | 2 +- mysql-test/suite/galera/t/galera_parallel_simple.test | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result b/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result index 48625b3ba4a..6caba56fe08 100644 --- a/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result +++ b/mysql-test/suite/galera/r/galera_parallel_apply_lock_table.result @@ -10,7 +10,7 @@ INSERT INTO t1 VALUES (1); INSERT INTO t2 VALUES (1); connection node_2a; SET SESSION wsrep_sync_wait=0; -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committing%'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Commit'; COUNT(*) = 1 1 SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Waiting for table metadata lock%'; diff --git a/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test b/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test index 5a33c16c86e..8e97a9cb5e3 100644 --- a/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test +++ b/mysql-test/suite/galera/t/galera_parallel_apply_lock_table.test @@ -32,7 +32,7 @@ INSERT INTO t2 VALUES (1); --connection node_2a --sleep 1 SET SESSION wsrep_sync_wait=0; -SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%committing%'; +SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Commit'; SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE '%Waiting for table metadata lock%'; SELECT COUNT(*) = 0 FROM t1; SELECT COUNT(*) = 0 FROM t2; diff --git a/mysql-test/suite/galera/t/galera_parallel_simple.test b/mysql-test/suite/galera/t/galera_parallel_simple.test index d49dc0ae876..89adaf8cbd2 100644 --- a/mysql-test/suite/galera/t/galera_parallel_simple.test +++ b/mysql-test/suite/galera/t/galera_parallel_simple.test @@ -51,7 +51,7 @@ SET SESSION wsrep_sync_wait = 0; --let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Waiting for table metadata lock%'; --source include/wait_condition.inc ---let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'committing%'; +--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE STATE LIKE 'Commit'; --source include/wait_condition.inc UNLOCK TABLES; From 7f498fbab888bd24d76a0292f4d22cacfb2f95b2 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 15 Mar 2024 00:41:28 +0100 Subject: [PATCH 077/106] Fix "Assertion `THR_PFS_initialized' failed" in main.bootstrap This patch makes the server wait for the manager thread to actually start before proceeding with server startup. Without this, if thread scheduling is really slow and the server shutdowns quickly, then it is possible that the manager thread is not yet started when shutdown_performance_schema() is called. If the manager thread starts at just the wrong moment and just before the main server reaches exit(), the thread can try to access no longer available performance schema data. This was seen as occasional assertion in the main.bootstrap test. As an additional improvement, make sure to run all pending actions before exiting the manager thread. Reviewed-by: Monty Signed-off-by: Kristian Nielsen --- sql/sql_manager.cc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sql/sql_manager.cc b/sql/sql_manager.cc index 3d3728b9e00..5cd66d8047a 100644 --- a/sql/sql_manager.cc +++ b/sql/sql_manager.cc @@ -76,7 +76,9 @@ pthread_handler_t handle_manager(void *arg __attribute__((unused))) pthread_detach_this_thread(); manager_thread = pthread_self(); mysql_mutex_lock(&LOCK_manager); - while (!abort_manager) + manager_thread_in_use = 1; + mysql_cond_signal(&COND_manager); + while (!abort_manager || cb_list) { /* XXX: This will need to be made more general to handle different * polling needs. */ @@ -116,6 +118,7 @@ pthread_handler_t handle_manager(void *arg __attribute__((unused))) } mysql_mutex_lock(&LOCK_manager); } + DBUG_ASSERT(cb_list == NULL); manager_thread_in_use = 0; mysql_mutex_unlock(&LOCK_manager); mysql_mutex_destroy(&LOCK_manager); @@ -135,12 +138,19 @@ void start_handle_manager() pthread_t hThread; int err; DBUG_EXECUTE_IF("delay_start_handle_manager", my_sleep(1000);); - manager_thread_in_use = 1; mysql_cond_init(key_COND_manager, &COND_manager,NULL); mysql_mutex_init(key_LOCK_manager, &LOCK_manager, NULL); if ((err= mysql_thread_create(key_thread_handle_manager, &hThread, &connection_attrib, handle_manager, 0))) + { sql_print_warning("Can't create handle_manager thread (errno: %M)", err); + DBUG_VOID_RETURN; + } + + mysql_mutex_lock(&LOCK_manager); + while (!manager_thread_in_use) + mysql_cond_wait(&COND_manager, &LOCK_manager); + mysql_mutex_unlock(&LOCK_manager); } DBUG_VOID_RETURN; } From fb774eb1ebab7d397c10a516be364d395440d079 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 15 Mar 2024 14:54:36 +0100 Subject: [PATCH 078/106] Fix occasional test failure of rpl.rpl_parallel_stop_slave Signed-off-by: Kristian Nielsen --- .../rpl_parallel_stop_slave.result | 4 +++- .../rpl/r/rpl_parallel_stop_slave.result | 4 +++- .../suite/rpl/t/rpl_parallel_stop_slave.test | 23 ++++++++++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/binlog_encryption/rpl_parallel_stop_slave.result b/mysql-test/suite/binlog_encryption/rpl_parallel_stop_slave.result index 6c9fd168e73..de4798f0cee 100644 --- a/mysql-test/suite/binlog_encryption/rpl_parallel_stop_slave.result +++ b/mysql-test/suite/binlog_encryption/rpl_parallel_stop_slave.result @@ -35,7 +35,9 @@ connection con_temp1; BEGIN; INSERT INTO t2 VALUES (21); connection server_2; -START SLAVE; +START SLAVE IO_THREAD; +include/wait_for_slave_param.inc [Read_Master_Log_Pos] +START SLAVE SQL_THREAD; connection con_temp2; SET @old_dbug= @@GLOBAL.debug_dbug; SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger"; diff --git a/mysql-test/suite/rpl/r/rpl_parallel_stop_slave.result b/mysql-test/suite/rpl/r/rpl_parallel_stop_slave.result index 6c9fd168e73..de4798f0cee 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_stop_slave.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_stop_slave.result @@ -35,7 +35,9 @@ connection con_temp1; BEGIN; INSERT INTO t2 VALUES (21); connection server_2; -START SLAVE; +START SLAVE IO_THREAD; +include/wait_for_slave_param.inc [Read_Master_Log_Pos] +START SLAVE SQL_THREAD; connection con_temp2; SET @old_dbug= @@GLOBAL.debug_dbug; SET GLOBAL debug_dbug="+d,rpl_parallel_wait_for_done_trigger"; diff --git a/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test b/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test index 4eeddc927e0..d6da88c3d6c 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_stop_slave.test @@ -53,6 +53,7 @@ COMMIT; INSERT INTO t3 VALUES(21, 21); INSERT INTO t3 VALUES(22, 22); --save_master_pos +--let $master_pos= query_get_value(SHOW MASTER STATUS, Position, 1) # Start a connection that will block the replicated transaction halfway. --connection con_temp1 @@ -60,7 +61,27 @@ BEGIN; INSERT INTO t2 VALUES (21); --connection server_2 -START SLAVE; + +# +# Parallel replication will complete any in-progress event group at STOP SLAVE, +# but only if the event group is already queued up for the worker thread. If +# the SQL driver thread is delayed in queueing up events, the parallel worker +# thread can abort the event group, leaving the non-transactional update to the +# MyISAM table that cannot be rolled back (MDEV-7432). If this happens the test +# would fail with duplicate key error after slave restart. +# +# To avoid this, we here wait for the IO thread to read all master events, and +# for the SQL driver thread to queue all the events for workers. This wait +# should be removed if/when MDEV-7432 is fixed. +# +START SLAVE IO_THREAD; +--let $slave_param= Read_Master_Log_Pos +--let $slave_param_value= $master_pos +--source include/wait_for_slave_param.inc +START SLAVE SQL_THREAD; +--let $wait_condition= SELECT COUNT(*)=1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State LIKE '%Slave has read all relay log; waiting for more updates%' +--source include/wait_condition.inc + # Wait for the MyISAM change to be visible, after which replication will wait # for con_temp1 to roll back. --let $wait_condition= SELECT COUNT(*) = 1 FROM t1 WHERE a=20 From 1fb00f37ae9db1af4ff910262fb2c51a009ead61 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 8 Mar 2024 11:26:45 +0100 Subject: [PATCH 079/106] MDEV-33303: slave_parallel_mode=optimistic should not report the mode's specific temporary errors An earlier patch for MDEV-13577 fixed the most common instances of this, but missed one case for tables without primary key when the scan reaches the end of the table. This patch adds similar code to handle this case, converting the error to HA_ERR_RECORD_CHANGED when doing optimistic parallel apply. Signed-off-by: Kristian Nielsen --- .../suite/rpl/r/rpl_parallel_retry.result | 22 +++++++++++ .../suite/rpl/t/rpl_parallel_retry.test | 38 +++++++++++++++++++ sql/log_event_server.cc | 11 ++++++ 3 files changed, 71 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_parallel_retry.result b/mysql-test/suite/rpl/r/rpl_parallel_retry.result index 2cc4044a2cd..4c7effd737a 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_retry.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_retry.result @@ -339,6 +339,28 @@ connection server_1; DROP TABLE t1, t2, t3, t4; DROP function foo; connection server_2; +connection server_2; +include/stop_slave.inc +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=4; +connection server_1; +CREATE TABLE t1 (a INT, b VARCHAR(123)) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1, 'asdf'); +UPDATE t1 SET b='zxf1' WHERE a=1; +UPDATE t1 SET b='\n' WHERE a=1; +connection server_2; +SET @old_dbug=@@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,write_row_inject_sleep_before_ha_write_row"; +include/start_slave.inc +connection server_1; +connection server_2; +connection server_1; +DROP TABLE t1; +connection server_2; +include/stop_slave.inc +SET GLOBAL debug_dbug=@old_dbug; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +include/start_slave.inc connection server_1; CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; INSERT INTO t1 VALUES(100, 100); diff --git a/mysql-test/suite/rpl/t/rpl_parallel_retry.test b/mysql-test/suite/rpl/t/rpl_parallel_retry.test index fe6f40d2c85..1e87c85cd6c 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_retry.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_retry.test @@ -410,6 +410,44 @@ DROP function foo; --sync_slave_with_master server_2 +# +# MDEV-33303: slave_parallel_mode=optimistic should not report the mode's +# specific temporary errors. +# + +--connection server_2 +--source include/stop_slave.inc +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=4; + +--connection server_1 +# The problem occurred in the code path for row-based updates in tables +# with no primary/unique key, where a scan is needed. +CREATE TABLE t1 (a INT, b VARCHAR(123)) ENGINE=InnoDB; +INSERT INTO t1 VALUES(1, 'asdf'); +UPDATE t1 SET b='zxf1' WHERE a=1; +UPDATE t1 SET b='\n' WHERE a=1; + +--connection server_2 +# Inject a small sleep in the code that makes the race easier to hit. +SET @old_dbug=@@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,write_row_inject_sleep_before_ha_write_row"; +--source include/start_slave.inc + +--connection server_1 +# Here, we would get errors in the slave's error log: +# [ERROR] mariadbd: Can't find record in 't1' +--sync_slave_with_master server_2 + +--connection server_1 +DROP TABLE t1; +--sync_slave_with_master server_2 +--source include/stop_slave.inc +SET GLOBAL debug_dbug=@old_dbug; +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + + # # MDEV-12746 rpl.rpl_parallel_optimistic_nobinlog fails committing out of order at retry # diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index cafac67a51d..77856cde6f1 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -7401,6 +7401,8 @@ Rows_log_event::write_row(rpl_group_info *rgi, TODO: Add safety measures against infinite looping. */ + DBUG_EXECUTE_IF("write_row_inject_sleep_before_ha_write_row", + my_sleep(20000);); if (table->s->sequence) error= update_sequence(); else while (unlikely(error= table->file->ha_write_row(table->record[0]))) @@ -7898,6 +7900,12 @@ static int row_not_found_error(rpl_group_info *rgi) ? HA_ERR_KEY_NOT_FOUND : HA_ERR_RECORD_CHANGED; } +static int end_of_file_error(rpl_group_info *rgi) +{ + return rgi->speculation != rpl_group_info::SPECULATE_OPTIMISTIC + ? HA_ERR_END_OF_FILE : HA_ERR_RECORD_CHANGED; +} + /** Locate the current row in event's table. @@ -8145,6 +8153,8 @@ int Rows_log_event::find_row(rpl_group_info *rgi) while ((error= table->file->ha_index_next(table->record[0]))) { DBUG_PRINT("info",("no record matching the given row found")); + if (error == HA_ERR_END_OF_FILE) + error= end_of_file_error(rgi); table->file->print_error(error, MYF(0)); table->file->ha_index_end(); goto end; @@ -8181,6 +8191,7 @@ int Rows_log_event::find_row(rpl_group_info *rgi) break; case HA_ERR_END_OF_FILE: + error= end_of_file_error(rgi); DBUG_PRINT("info", ("Record not found")); table->file->ha_rnd_end(); goto end; From 77b9b28a59cc7ee0bf18cb8131dce3490ae25e9d Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Fri, 8 Mar 2024 22:43:26 +0100 Subject: [PATCH 080/106] MDEV-24622: Replication does not support bulk insert into empty table Remove work-around that disables bulk insert optimization in replication The root cause of the original problem is now fixed (MDEV-33475). Though the bulk insert optimization will still be disabled in replication, as it is only enabled in special circumstances meant for loading a mysqldump. Signed-off-by: Kristian Nielsen --- sql/sql_class.cc | 8 -------- storage/innobase/row/row0ins.cc | 9 +-------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 2228d8017e5..85fd68bf9a9 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5317,14 +5317,6 @@ extern "C" enum enum_server_command thd_current_command(MYSQL_THD thd) return thd->get_command(); } -#ifdef HAVE_REPLICATION /* Working around MDEV-24622 */ -/** @return whether the current thread is for applying binlog in a replica */ -extern "C" int thd_is_slave(const MYSQL_THD thd) -{ - return thd && thd->slave_thread; -} -#endif /* HAVE_REPLICATION */ - /* Returns high resolution timestamp for the start of the current query. */ extern "C" unsigned long long thd_start_utime(const MYSQL_THD thd) diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 5d75e88227e..990c14d1a8f 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2565,12 +2565,6 @@ row_ins_index_entry_big_rec( return(error); } -#ifdef HAVE_REPLICATION /* Working around MDEV-24622 */ -extern "C" int thd_is_slave(const MYSQL_THD thd); -#else -# define thd_is_slave(thd) 0 -#endif - #if defined __aarch64__&&defined __GNUC__&&__GNUC__==4&&!defined __clang__ /* Avoid GCC 4.8.5 internal compiler error due to srw_mutex::wr_unlock(). We would only need this for row_ins_clust_index_entry_low(), @@ -2722,8 +2716,7 @@ err_exit: && !index->table->skip_alter_undo && !index->table->n_rec_locks && !index->table->is_active_ddl() - && !index->table->versioned() - && !thd_is_slave(trx->mysql_thd) /* FIXME: MDEV-24622 */) { + && !index->table->versioned()) { DEBUG_SYNC_C("empty_root_page_insert"); if (!index->table->is_temporary()) { From 51abae5e4659eb1cf231fefe0ad5a1168337f989 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Thu, 29 Feb 2024 19:42:00 +0100 Subject: [PATCH 081/106] MDEV-25923: Aria parallel repair MY_THREAD_SPECIFIC mismatch in realloc maria_repair_parallel() clears the MY_THREAD_SPECIFIC flag for allocations since it uses different threads. But it still did one _ma_alloc_buffer() call as thread-specific which would later assert if another thread needed to extend the buffer with realloc. This patch, due to Monty, removes the MY_THREAD_SPECIFIC flag for allocations that need to realloc in different threads, and preserves it for those that are allocated/freed in the user's thread. Also fixes MDEV-33562. Reviewed-by: Monty Signed-off-by: Kristian Nielsen --- mysql-test/suite/maria/alter.result | 26 ++++++++++++++++++++++++++ mysql-test/suite/maria/alter.test | 28 ++++++++++++++++++++++++++++ storage/maria/ma_check.c | 24 +++++++++++++----------- 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/mysql-test/suite/maria/alter.result b/mysql-test/suite/maria/alter.result index cc035426745..17164343163 100644 --- a/mysql-test/suite/maria/alter.result +++ b/mysql-test/suite/maria/alter.result @@ -193,3 +193,29 @@ ALTER TABLE t1 DISABLE KEYS; INSERT INTO t1 VALUES (1, 'Nine chars or more'); ALTER TABLE t1 ENABLE KEYS; DROP TABLE t1; +# +# MDEV-25923 Memory not freed or Assertion `old_flags == ((my_flags & +# 0x10000U) ? 1 : 0)' failed in my_realloc upon ALTER on Aria table +# with GIS column +# +CREATE TABLE t1 (pk INT PRIMARY KEY, a POINT DEFAULT ST_GEOMFROMTEXT('Point(1 1)')) ENGINE=Aria; +INSERT INTO t1 (pk) SELECT seq FROM seq_1_to_100; +SET @old_threads= @@SESSION.aria_repair_threads; +SET SESSION aria_repair_threads= 2; +ALTER TABLE t1 ROW_FORMAT=DYNAMIC; +DROP TABLE t1; +# +# MDEV-33562: Assertion `(old_flags & 1) == ((my_flags & 0x10000U) ? +# 1 : 0)' failed in my_realloc from sort_get_next_record on INSERT +# +SET @old_mode= @@SESSION.sql_mode; +SET sql_mode=''; +CREATE TEMPORARY TABLE t (b TEXT, INDEX s(b(300))) ROW_FORMAT=DYNAMIC ENGINE=Aria; +INSERT INTO t VALUES (REPEAT ('a',10000000)); +Warnings: +Warning 1265 Data truncated for column 'b' at row 1 +CREATE TABLE ti LIKE t; +INSERT INTO ti SELECT * FROM t; +DROP TABLE t, ti; +SET SESSION aria_repair_threads= @old_threads; +SET SESSION sql_mode= @old_mode; diff --git a/mysql-test/suite/maria/alter.test b/mysql-test/suite/maria/alter.test index 525cd80f3d9..a68b5f2e0d7 100644 --- a/mysql-test/suite/maria/alter.test +++ b/mysql-test/suite/maria/alter.test @@ -203,3 +203,31 @@ ALTER TABLE t1 DISABLE KEYS; INSERT INTO t1 VALUES (1, 'Nine chars or more'); ALTER TABLE t1 ENABLE KEYS; DROP TABLE t1; + +--echo # +--echo # MDEV-25923 Memory not freed or Assertion `old_flags == ((my_flags & +--echo # 0x10000U) ? 1 : 0)' failed in my_realloc upon ALTER on Aria table +--echo # with GIS column +--echo # + +CREATE TABLE t1 (pk INT PRIMARY KEY, a POINT DEFAULT ST_GEOMFROMTEXT('Point(1 1)')) ENGINE=Aria; +INSERT INTO t1 (pk) SELECT seq FROM seq_1_to_100; +SET @old_threads= @@SESSION.aria_repair_threads; +SET SESSION aria_repair_threads= 2; +ALTER TABLE t1 ROW_FORMAT=DYNAMIC; +DROP TABLE t1; + +--echo # +--echo # MDEV-33562: Assertion `(old_flags & 1) == ((my_flags & 0x10000U) ? +--echo # 1 : 0)' failed in my_realloc from sort_get_next_record on INSERT +--echo # + +SET @old_mode= @@SESSION.sql_mode; +SET sql_mode=''; +CREATE TEMPORARY TABLE t (b TEXT, INDEX s(b(300))) ROW_FORMAT=DYNAMIC ENGINE=Aria; +INSERT INTO t VALUES (REPEAT ('a',10000000)); +CREATE TABLE ti LIKE t; +INSERT INTO ti SELECT * FROM t; +DROP TABLE t, ti; +SET SESSION aria_repair_threads= @old_threads; +SET SESSION sql_mode= @old_mode; diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index 1f5f494ca65..044be038607 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -125,6 +125,7 @@ void maria_chk_init(HA_CHECK *param) param->max_stage= 1; param->stack_end_ptr= &my_thread_var->stack_ends_here; param->max_allowed_lsn= (LSN) ~0ULL; + /* Flag when initializing buffers possible used by parallel repair threads */ param->malloc_flags= MY_THREAD_SPECIFIC; } @@ -2130,7 +2131,7 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend) if (!(record= (uchar*) my_malloc(PSI_INSTRUMENT_ME, share->base.default_rec_buff_size, - MYF(param->malloc_flags)))) + MYF(MY_THREAD_SPECIFIC)))) { _ma_check_print_error(param,"Not enough memory for record"); DBUG_RETURN(-1); @@ -2766,10 +2767,10 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info, if (!(sort_param.record= (uchar *) my_malloc(PSI_INSTRUMENT_ME, (uint) share->base.default_rec_buff_size, - MYF(param->malloc_flags))) || + MYF(MY_THREAD_SPECIFIC))) || _ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size, share->base.default_rec_buff_size, - MYF(param->malloc_flags))) + MYF(MY_THREAD_SPECIFIC))) { _ma_check_print_error(param, "Not enough memory for extra record"); goto err; @@ -3721,7 +3722,7 @@ int maria_filecopy(HA_CHECK *param, File to,File from,my_off_t start, buff_length=(ulong) MY_MIN(param->write_buffer_length,length); if (!(buff=my_malloc(PSI_INSTRUMENT_ME, buff_length, - MYF(param->malloc_flags)))) + MYF(MY_THREAD_SPECIFIC)))) { buff=tmp_buff; buff_length=IO_SIZE; } @@ -3867,10 +3868,10 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, if (!(sort_param.record= (uchar*) my_malloc(PSI_INSTRUMENT_ME, (size_t) share->base.default_rec_buff_size, - MYF(param->malloc_flags))) || + MYF(MY_THREAD_SPECIFIC))) || _ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size, share->base.default_rec_buff_size, - MYF(param->malloc_flags))) + MYF(MY_THREAD_SPECIFIC))) { _ma_check_print_error(param, "Not enough memory for extra record"); goto err; @@ -3889,7 +3890,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info, sort_param.wordlist=NULL; init_alloc_root(PSI_INSTRUMENT_ME, &sort_param.wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0, - MYF(param->malloc_flags)); + MYF(MY_THREAD_SPECIFIC)); sort_param.key_cmp=sort_key_cmp; sort_param.lock_in_memory=maria_lock_memory; @@ -4457,7 +4458,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, if (!(sort_param=(MARIA_SORT_PARAM *) my_malloc(PSI_INSTRUMENT_ME, (uint) share->base.keys * (sizeof(MARIA_SORT_PARAM) + share->base.pack_reclength), - MYF(MY_ZEROFILL | param->malloc_flags)))) + MYF(MY_ZEROFILL | MY_THREAD_SPECIFIC)))) { _ma_check_print_error(param,"Not enough memory for key!"); goto err; @@ -4515,9 +4516,10 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, sort_param[i].record= (((uchar *)(sort_param+share->base.keys))+ (share->base.pack_reclength * i)); + /* These buffers are per thread */ if (_ma_alloc_buffer(&sort_param[i].rec_buff, &sort_param[i].rec_buff_size, share->base.default_rec_buff_size, - MYF(param->malloc_flags))) + MYF(0))) { _ma_check_print_error(param,"Not enough memory!"); goto err; @@ -4546,7 +4548,7 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info, sort_param[i].key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN; init_alloc_root(PSI_INSTRUMENT_ME, &sort_param[i].wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0, - MYF(param->malloc_flags)); + MYF(MY_THREAD_SPECIFIC)); } } sort_info.total_keys=i; @@ -6105,7 +6107,7 @@ static MA_SORT_KEY_BLOCKS *alloc_key_blocks(HA_CHECK *param, uint blocks, if (!(block= (MA_SORT_KEY_BLOCKS*) my_malloc(PSI_INSTRUMENT_ME, (sizeof(MA_SORT_KEY_BLOCKS)+buffer_length+IO_SIZE)*blocks, - MYF(param->malloc_flags)))) + MYF(MY_THREAD_SPECIFIC)))) { _ma_check_print_error(param,"Not enough memory for sort-key-blocks"); return(0); From 09d991d01c47e22030879e5bf0c7a4893a598199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 18 Mar 2024 16:01:29 +0200 Subject: [PATCH 082/106] MDEV-33478: Tests massively fail with clang-18 -fsanitize=memory Starting with clang-16, MemorySanitizer appears to check that uninitialized values not be passed by value nor returned. Previously, it was allowed to copy uninitialized data in such cases. get_foreign_key_info(): Remove a local variable that was passed uninitialized to a function. DsMrr_impl: Initialize key_buffer, because DsMrr_impl::dsmrr_init() is reading it. test_bind_result_ext1(): MYSQL_TYPE_LONG is 32 bits, hence we must use a 32-bit type, such as int. sizeof(long) differs between LP64 and LLP64 targets. --- sql/debug_sync.cc | 2 +- sql/item_func.h | 2 +- sql/log.h | 11 +++++++++++ sql/multi_range_read.h | 10 +++------- sql/sql_lex.h | 2 +- storage/innobase/handler/ha_innodb.cc | 11 ++++------- storage/myisam/ft_boolean_search.c | 2 ++ tests/mysql_client_test.c | 4 ++-- 8 files changed, 25 insertions(+), 19 deletions(-) diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc index eec95bee1f2..160851ae004 100644 --- a/sql/debug_sync.cc +++ b/sql/debug_sync.cc @@ -1008,7 +1008,7 @@ static bool debug_sync_eval_action(THD *thd, char *action_str, char *action_end) st_debug_sync_action *action= NULL; const char *errmsg; char *ptr; - char *token; + char *token= nullptr; uint token_length= 0; DBUG_ENTER("debug_sync_eval_action"); DBUG_ASSERT(thd); diff --git a/sql/item_func.h b/sql/item_func.h index 0f4f8928847..13b522dc25c 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -90,7 +90,7 @@ public: static void wrong_param_count_error(const LEX_CSTRING &schema_name, const LEX_CSTRING &func_name); - table_map not_null_tables_cache; + table_map not_null_tables_cache= 0; enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC, GE_FUNC,GT_FUNC,FT_FUNC, diff --git a/sql/log.h b/sql/log.h index fbe0f30f22b..dd31081c404 100644 --- a/sql/log.h +++ b/sql/log.h @@ -426,6 +426,7 @@ struct wait_for_commit; class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG { +#ifdef HAVE_PSI_INTERFACE /** The instrumentation key to use for @ LOCK_index. */ PSI_mutex_key m_key_LOCK_index; /** The instrumentation key to use for @ COND_relay_log_updated */ @@ -440,6 +441,16 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG PSI_cond_key m_key_COND_queue_busy; /** The instrumentation key to use for LOCK_binlog_end_pos. */ PSI_mutex_key m_key_LOCK_binlog_end_pos; +#else + static constexpr PSI_mutex_key m_key_LOCK_index= 0; + static constexpr PSI_cond_key m_key_relay_log_update= 0; + static constexpr PSI_cond_key m_key_bin_log_update= 0; + static constexpr PSI_file_key m_key_file_log= 0, m_key_file_log_cache= 0; + static constexpr PSI_file_key m_key_file_log_index= 0; + static constexpr PSI_file_key m_key_file_log_index_cache= 0; + static constexpr PSI_cond_key m_key_COND_queue_busy= 0; + static constexpr PSI_mutex_key m_key_LOCK_binlog_end_pos= 0; +#endif struct group_commit_entry { diff --git a/sql/multi_range_read.h b/sql/multi_range_read.h index 57cfd21727f..5e7879d9226 100644 --- a/sql/multi_range_read.h +++ b/sql/multi_range_read.h @@ -556,10 +556,6 @@ class DsMrr_impl public: typedef void (handler::*range_check_toggle_func_t)(bool on); - DsMrr_impl() - : secondary_file(NULL), - rowid_filter(NULL) {}; - void init(handler *h_arg, TABLE *table_arg) { primary_file= h_arg; @@ -581,7 +577,7 @@ public: int dsmrr_explain_info(uint mrr_mode, char *str, size_t size); private: /* Buffer to store (key, range_id) pairs */ - Lifo_buffer *key_buffer; + Lifo_buffer *key_buffer= nullptr; /* The "owner" handler object (the one that is expected to "own" this object @@ -594,13 +590,13 @@ private: Secondary handler object. (created when needed, we need it when we need to run both index scan and rnd_pos() scan at the same time) */ - handler *secondary_file; + handler *secondary_file= nullptr; /* The rowid filter that DS-MRR has "unpushed" from the storage engine. If it's present, DS-MRR will use it. */ - Rowid_filter *rowid_filter; + Rowid_filter *rowid_filter= nullptr; uint keyno; /* index we're running the scan on */ /* TRUE <=> need range association, buffers hold {rowid, range_id} pairs */ diff --git a/sql/sql_lex.h b/sql/sql_lex.h index b6d91896142..3ab50d4aaa8 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3260,7 +3260,7 @@ public: Table_type table_type; /* Used for SHOW CREATE */ List ref_list; List users_list; - List *insert_list,field_list,value_list,update_list; + List *insert_list= nullptr,field_list,value_list,update_list; List many_values; List var_list; List stmt_var_list; //SET_STATEMENT values diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ad2e022f0b3..19cfa21c84e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12108,7 +12108,7 @@ create_table_info_t::create_foreign_keys() dict_index_t* index = NULL; fkerr_t index_error = FK_SUCCESS; dict_index_t* err_index = NULL; - ulint err_col; + ulint err_col = 0; const bool tmp_table = m_flags2 & DICT_TF2_TEMPORARY; const CHARSET_INFO* cs = thd_charset(m_thd); const char* operation = "Create "; @@ -15150,7 +15150,6 @@ get_foreign_key_info( char tmp_buff[NAME_LEN+1]; char name_buff[NAME_LEN+1]; const char* ptr; - LEX_CSTRING* referenced_key_name; LEX_CSTRING* name = NULL; if (dict_table_t::is_temporary_name(foreign->foreign_table_name)) { @@ -15255,18 +15254,16 @@ get_foreign_key_info( if (foreign->referenced_index && foreign->referenced_index->name != NULL) { - referenced_key_name = thd_make_lex_string( + f_key_info.referenced_key_name = thd_make_lex_string( thd, - f_key_info.referenced_key_name, + nullptr, foreign->referenced_index->name, strlen(foreign->referenced_index->name), 1); } else { - referenced_key_name = NULL; + f_key_info.referenced_key_name = NULL; } - f_key_info.referenced_key_name = referenced_key_name; - pf_key_info = (FOREIGN_KEY_INFO*) thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO)); diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c index f69f1869383..3d95fffacaf 100644 --- a/storage/myisam/ft_boolean_search.c +++ b/storage/myisam/ft_boolean_search.c @@ -287,6 +287,8 @@ static int ftb_parse_query_internal(MYSQL_FTPARSER_PARAM *param, uchar *end= (uchar*) query + len; FT_WORD w; + w.pos= NULL; + w.len= 0; info.prev= ' '; info.quot= 0; while (ft_get_word(cs, start, end, &w, &info)) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index fde6148f4e0..b1e40ea5c88 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -3842,7 +3842,7 @@ static void test_bind_result_ext1() short i_data; uchar b_data; int f_data; - long bData; + int bData; char d_data[20]; double szData; MYSQL_BIND my_bind[8]; @@ -3938,7 +3938,7 @@ static void test_bind_result_ext1() fprintf(stdout, "\n data (float) : %d(%lu)", f_data, length[4]); fprintf(stdout, "\n data (double) : %s(%lu)", d_data, length[5]); - fprintf(stdout, "\n data (bin) : %ld(%lu)", bData, length[6]); + fprintf(stdout, "\n data (bin) : %d(%lu)", bData, length[6]); fprintf(stdout, "\n data (str) : %g(%lu)", szData, length[7]); } From 4592af2e84dfddeb8370c0c8c3cb2d35dddc32db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 18 Mar 2024 16:01:58 +0200 Subject: [PATCH 083/106] Work around missing MSAN instrumentation Let us skip the recently added test main.mysql-interactive if an instrumented ncurses library is not available. In InnoDB, let us work around an uninstrumented libnuma, by declaring that the objects returned by numa_get_mems_allowed() are initialized. --- mysql-test/main/mysql-interactive.test | 2 ++ storage/innobase/buf/buf0buf.cc | 3 +++ 2 files changed, 5 insertions(+) diff --git a/mysql-test/main/mysql-interactive.test b/mysql-test/main/mysql-interactive.test index 2015e9d667d..0051d8e58c6 100644 --- a/mysql-test/main/mysql-interactive.test +++ b/mysql-test/main/mysql-interactive.test @@ -3,6 +3,8 @@ --echo # source include/not_embedded.inc; source include/not_windows.inc; +# this would need an instrumented ncurses library +source include/not_msan.inc; error 0,1; exec $MYSQL -V|grep -q readline; diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index c0dece69cf8..f37a96d5a7c 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -82,6 +82,8 @@ struct set_numa_interleave_t if (srv_numa_interleave) { struct bitmask *numa_mems_allowed = numa_get_mems_allowed(); + MEM_MAKE_DEFINED(numa_mems_allowed, + sizeof *numa_mems_allowed); ib::info() << "Setting NUMA memory policy to" " MPOL_INTERLEAVE"; if (set_mempolicy(MPOL_INTERLEAVE, @@ -1072,6 +1074,7 @@ inline bool buf_pool_t::chunk_t::create(size_t bytes) if (srv_numa_interleave) { struct bitmask *numa_mems_allowed= numa_get_mems_allowed(); + MEM_MAKE_DEFINED(numa_mems_allowed, sizeof *numa_mems_allowed); if (mbind(mem, mem_size(), MPOL_INTERLEAVE, numa_mems_allowed->maskp, numa_mems_allowed->size, MPOL_MF_MOVE)) From a13e521bc51d3ad9bb6e8e6481a0c8dea3b648a7 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Mon, 18 Mar 2024 17:37:13 +1100 Subject: [PATCH 084/106] MDEV-33636: RPM caps is on mariadbd exe Postfix on 51e3f1daf54309d14fe8db438024d88aa110e86a that mariadbd should be the executable name rather than capabilities on a symlink. --- cmake/cpack_rpm.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index be94a3387f1..9383ae8c13b 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -183,7 +183,7 @@ ENDMACRO(SETA) IF (CMAKE_VERSION VERSION_GREATER 3.10.0) # cmake bug #14362 SET(CPACK_RPM_server_USER_FILELIST ${CPACK_RPM_server_USER_FILELIST} - "%caps(cap_ipc_lock=pe) %{_sbindir}/mysqld" + "%caps(cap_ipc_lock=pe) %{_sbindir}/mariadbd" ) ENDIF() From 01d994b39a5e40450c0c609d103d8dd8bc7d19d1 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 18 Mar 2024 23:43:56 +0100 Subject: [PATCH 085/106] Post-fix 567c0973591eb66797bb0f982f312b516f8fe82c Do *not* check if socket is closed by another thread. This is race-condition prone, unnecessary, and harmful. VIO state was introduced to debug the errors, not to change the behavior. Rather than checking if socket is closed, add a DBUG_ASSERT that it is *not* closed, because this is an actual logic error, and can potentially lead to all sorts of funny behavior like writing error packets to Innodb files. Unlike closesocket(), shutdown(2) is not actually race-condition prone, and it breaks poll() and read(), and it worked for longer than a decade, and it does not need any state check in the code. --- vio/viosocket.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/vio/viosocket.c b/vio/viosocket.c index bb6baac571e..ffdc76a5deb 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -560,8 +560,7 @@ vio_should_retry(Vio *vio) DBUG_ENTER("vio_should_retry"); DBUG_PRINT("info", ("vio_errno: %d state: %d", vio_errno(vio), (int) vio->state)); - DBUG_RETURN(vio_errno(vio) == SOCKET_EINTR && - vio->state < VIO_STATE_SHUTDOWN); + DBUG_RETURN(vio_errno(vio) == SOCKET_EINTR); } @@ -931,14 +930,7 @@ int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout) (int) mysql_socket_getfd(vio->mysql_socket), timeout)); - if (vio->state >= VIO_STATE_SHUTDOWN) - { - DBUG_PRINT("info", ("vio deactivated. state: %ld", (int) vio->state)); - /* Socket is shutdown or closed */ - errno= EIO; - DBUG_RETURN(-1); - } - + DBUG_ASSERT(vio->state != VIO_STATE_CLOSED); memset(&pfd, 0, sizeof(pfd)); pfd.fd= sd; @@ -999,14 +991,7 @@ int vio_io_wait(Vio *vio, enum enum_vio_io_event event, int timeout) fd_set readfds, writefds, exceptfds; MYSQL_SOCKET_WAIT_VARIABLES(locker, state) /* no ';' */ DBUG_ENTER("vio_io_wait"); - - if (vio->state >= VIO_STATE_SHUTDOWN) - { - DBUG_PRINT("info", ("vio deactive. state: %ld", (int) vio->state)); - /* Socket is shutdown or closed */ - errno= EIO; - DBUG_RETURN(-1); - } + DBUG_ASSERT(vio->state != VIO_STATE_CLOSED); /* Convert the timeout, in milliseconds, to seconds and microseconds. */ if (timeout >= 0) @@ -1180,9 +1165,7 @@ my_bool vio_is_connected(Vio *vio) { uint bytes= 0; DBUG_ENTER("vio_is_connected"); - - if (vio->state >= VIO_STATE_SHUTDOWN) - DBUG_RETURN(FALSE); + DBUG_ASSERT(vio->state != VIO_STATE_CLOSED); /* The first step of detecting an EOF condition is verifying From 5b4e69c059230f4222fc68c387f02cde2f2b3958 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 19 Mar 2024 11:57:38 +0100 Subject: [PATCH 086/106] MDEV-23224 Windows threadpool - use better threadpool_max_threads default. Use max_connections in calculation, top prevent possible deadlock, if max_connection is high. --- sql/threadpool_win.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sql/threadpool_win.cc b/sql/threadpool_win.cc index ed68e31c755..65e40598135 100644 --- a/sql/threadpool_win.cc +++ b/sql/threadpool_win.cc @@ -355,10 +355,13 @@ int TP_pool_win::init() if (IS_SYSVAR_AUTOSIZE(&threadpool_max_threads)) { /* - Nr 500 comes from Microsoft documentation, - there is no API for GetThreadpoolThreadMaxThreads() + Default 500 comes from Microsoft documentation, + there is no API for GetThreadpoolThreadMaxThreads(). + + To avoid deadlocks, allow at least max_connections + safety + margin threads in the pool. */ - SYSVAR_AUTOSIZE(threadpool_max_threads,500); + SYSVAR_AUTOSIZE(threadpool_max_threads,std::max(500U,(uint)max_connections + 10)); } else { From 7d36919f4b73a2507555ed101ccd02cb266dcc52 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 22 Feb 2024 20:57:00 +0100 Subject: [PATCH 087/106] MDEV-33723 Mroonga ignored WITHOUT_DYNAMIC_PLUGINS Make WITHOUT_DYNAMIC_PLUGINS ignore mrooonga also in its own DIY version of MYSQL_ADD_PLUGIN --- storage/mroonga/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/storage/mroonga/CMakeLists.txt b/storage/mroonga/CMakeLists.txt index c048b214658..fffcd80c971 100644 --- a/storage/mroonga/CMakeLists.txt +++ b/storage/mroonga/CMakeLists.txt @@ -57,6 +57,11 @@ if(MRN_BUNDLED) "${PLUGIN_MROONGA}" STREQUAL "NO") return() endif() + if(WITHOUT_DYNAMIC_PLUGINS) + if(NOT (PLUGIN_MROONGA STREQUAL STATIC)) + return() + endif() + endif() endif() set(MRN_BUNDLED_GROONGA_RELATIVE_DIR "vendor/groonga") From c3a6248bba79c7444e86a2dd59960cfa99b7054f Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Tue, 19 Mar 2024 17:14:11 +0530 Subject: [PATCH 088/106] MDEV-33542 Inplace algorithm occupies more disk space compared to copy algorithm Problem: ======= - In case of large file size, InnoDB eagerly adds the new extent even though there are many existing unused pages of the segment. Reason is that in case of larger file size, threshold (1/8 of reserved pages) for adding new extent has been reached frequently. Solution: ========= - Try to utilise the unused pages in the segment before adding the new extent in the file segment. need_for_new_extent(): In case of larger file size, try to use the 4 * FSP_EXTENT_SIZE as threshold to allocate the new extent. fseg_alloc_free_page_low(): Rewrote the function to allocate the page in the following order. 1) Try to get the page from existing segment extent. 2) Check whether the segment needs new extent (need_for_new_extent()) and allocate the new extent, find the page. 3) Take individual page from the unused page from segment or tablespace. 4) Allocate a new extent and take first page from it. Removed FSEG_FILLFACTOR, FSEG_FRAG_LIMIT variable. --- .../suite/innodb/r/innodb_bug30113362.result | 6 +- storage/innobase/fsp/fsp0fsp.cc | 154 ++++++++---------- storage/innobase/include/fsp0fsp.h | 20 +-- storage/innobase/row/row0import.cc | 2 +- 4 files changed, 77 insertions(+), 105 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb_bug30113362.result b/mysql-test/suite/innodb/r/innodb_bug30113362.result index cb0f5091650..5d30c5c03dd 100644 --- a/mysql-test/suite/innodb/r/innodb_bug30113362.result +++ b/mysql-test/suite/innodb/r/innodb_bug30113362.result @@ -37,7 +37,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1'; CLUST_INDEX_SIZE -1856 +1792 connection con2; DELETE FROM t1 WHERE a00 = 'cnm'; COMMIT; @@ -80,7 +80,7 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1'; CLUST_INDEX_SIZE -1856 +1792 DELETE FROM t1 WHERE a00 = 'dpn'; COMMIT; INSERT INTO t1 SET a00 = 'dpn'; @@ -117,6 +117,6 @@ test.t1 analyze status Engine-independent statistics collected test.t1 analyze status OK SELECT CLUST_INDEX_SIZE FROM information_schema.INNODB_SYS_TABLESTATS WHERE NAME = 'test/t1'; CLUST_INDEX_SIZE -1856 +1792 SET DEBUG_SYNC = 'RESET'; DROP TABLE t1; diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 2c7188e4988..747a397fe92 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -271,7 +271,7 @@ inline void xdes_init(const buf_block_t &block, xdes_t *descr, mtr_t *mtr) static MY_ATTRIBUTE((nonnull, warn_unused_result)) dberr_t fseg_mark_page_used(fseg_inode_t *seg_inode, buf_block_t *iblock, - ulint page, xdes_t *descr, buf_block_t *xdes, mtr_t *mtr) + uint32_t page, xdes_t *descr, buf_block_t *xdes, mtr_t *mtr) { ut_ad(fil_page_get_type(iblock->page.frame) == FIL_PAGE_INODE); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); @@ -995,7 +995,7 @@ MY_ATTRIBUTE((nonnull, warn_unused_result)) @return error code */ static dberr_t fsp_alloc_from_free_frag(buf_block_t *header, buf_block_t *xdes, xdes_t *descr, - ulint bit, mtr_t *mtr) + uint32_t bit, mtr_t *mtr) { if (UNIV_UNLIKELY(xdes_get_state(descr) != XDES_FREE_FRAG || !xdes_is_free(descr, bit))) @@ -1987,29 +1987,42 @@ fseg_alloc_free_page_low( } } - /* In the big if-else below we look for ret_page and ret_descr */ - /*-------------------------------------------------------------*/ - if ((xdes_get_state(descr) == XDES_FSEG) - && mach_read_from_8(descr + XDES_ID) == seg_id - && xdes_is_free(descr, hint % FSP_EXTENT_SIZE)) { + const uint32_t extent_size = FSP_EXTENT_SIZE; + ret_descr = descr; + /* Try to get the page from extent which belongs to segment */ + if (xdes_get_state(descr) == XDES_FSEG + && mach_read_from_8(descr + XDES_ID) == seg_id) { + /* Get the page from the segment extent */ + if (xdes_is_free(descr, hint % extent_size)) { take_hinted_page: - /* 1. We can take the hinted page - =================================*/ - ret_descr = descr; - ret_page = hint; - /* Skip the check for extending the tablespace. If the - page hint were not within the size of the tablespace, - we would have got (descr == NULL) above and reset the hint. */ - goto got_hinted_page; - /*-----------------------------------------------------------*/ - } else if (xdes_get_state(descr) == XDES_FREE - && reserved - used < reserved / FSEG_FILLFACTOR - && used >= FSEG_FRAG_LIMIT) { + ret_page = hint; + goto got_hinted_page; + } else if (!xdes_is_full(descr)) { + /* Take the page from the same extent as the + hinted page (and the extent already belongs to + the segment) */ + ret_page = xdes_find_free(descr, hint % extent_size); + if (ret_page == FIL_NULL) { + ut_ad(!has_done_reservation); + return nullptr; + } + ret_page += xdes_get_offset(ret_descr); + goto alloc_done; + } + } - /* 2. We allocate the free extent from space and can take - ========================================================= - the hinted page - ===============*/ + /** If the number of unused but reserved pages in a segment is + esser than minimum value of 1/8 of reserved pages or + 4 * FSP_EXTENT_SIZE and there are at least half of extent size + used pages, then we allow a new empty extent to be added to + the segment in fseg_alloc_free_page_general(). Otherwise, we use + unused pages of the segment. */ + if (used < extent_size / 2 || + reserved - used >= reserved / 8 || + reserved - used >= extent_size * 4) { + } else if (xdes_get_state(descr) == XDES_FREE) { + /* Allocate the free extent from space and can + take the hinted page */ ret_descr = fsp_alloc_free_extent(space, hint, &xdes, mtr, err); @@ -2036,54 +2049,34 @@ take_hinted_page: /* Try to fill the segment free list */ *err = fseg_fill_free_list(seg_inode, iblock, space, - hint + FSP_EXTENT_SIZE, mtr); + hint + extent_size, mtr); if (UNIV_UNLIKELY(*err != DB_SUCCESS)) { return nullptr; } goto take_hinted_page; - /*-----------------------------------------------------------*/ - } else if ((direction != FSP_NO_DIR) - && ((reserved - used) < reserved / FSEG_FILLFACTOR) - && (used >= FSEG_FRAG_LIMIT) - && (ret_descr = fseg_alloc_free_extent(seg_inode, iblock, - &xdes, space, - mtr, err))) { - /* 3. We take any free extent (which was already assigned above - =============================================================== - in the if-condition to ret_descr) and take the lowest or - ======================================================== - highest page in it, depending on the direction - ==============================================*/ + } else if (direction != FSP_NO_DIR) { + + ret_descr = fseg_alloc_free_extent(seg_inode, iblock, + &xdes, space, mtr, err); + + if (!ret_descr) { + ut_ad(*err != DB_SUCCESS); + return nullptr; + } + /* Take any free extent (which was already assigned + above in the if-condition to ret_descr) and take the + lowest or highest page in it, depending on the direction */ ret_page = xdes_get_offset(ret_descr); if (direction == FSP_DOWN) { - ret_page += FSP_EXTENT_SIZE - 1; + ret_page += extent_size - 1; } - ut_ad(!has_done_reservation || ret_page != FIL_NULL); - /*-----------------------------------------------------------*/ - } else if (UNIV_UNLIKELY(*err != DB_SUCCESS)) { - return nullptr; - } else if ((xdes_get_state(descr) == XDES_FSEG) - && mach_read_from_8(descr + XDES_ID) == seg_id - && (!xdes_is_full(descr))) { + goto alloc_done; + } - /* 4. We can take the page from the same extent as the - ====================================================== - hinted page (and the extent already belongs to the - ================================================== - segment) - ========*/ - ret_descr = descr; - ret_page = xdes_find_free(ret_descr, hint % FSP_EXTENT_SIZE); - if (ret_page == FIL_NULL) { - ut_ad(!has_done_reservation); - } else { - ret_page += xdes_get_offset(ret_descr); - } - /*-----------------------------------------------------------*/ - } else if (reserved - used > 0) { - /* 5. We take any unused page from the segment - ==============================================*/ + /* Try to take individual page from the segment or tablespace */ + if (reserved - used > 0) { + /* Take any unused page from the segment */ fil_addr_t first; if (flst_get_len(seg_inode + FSEG_NOT_FULL) > 0) { @@ -2092,7 +2085,7 @@ take_hinted_page: first = flst_get_first(seg_inode + FSEG_FREE); } else { ut_ad(!has_done_reservation); - return(NULL); + return nullptr; } ret_descr = xdes_lst_get_descriptor(*space, first, mtr, &xdes); @@ -2106,10 +2099,9 @@ take_hinted_page: } else { ret_page += xdes_get_offset(ret_descr); } - /*-----------------------------------------------------------*/ - } else if (used < FSEG_FRAG_LIMIT) { - /* 6. We allocate an individual page from the space - ===================================================*/ + + } else if (used < extent_size / 2) { + /* Allocate an individual page from the space */ buf_block_t* block = fsp_alloc_free_page( space, hint, mtr, init_mtr, err); @@ -2132,13 +2124,11 @@ take_hinted_page: /* fsp_alloc_free_page() invoked fsp_init_file_page() already. */ return(block); - /*-----------------------------------------------------------*/ } else { - /* 7. We allocate a new extent and take its first page - ======================================================*/ + /* In worst case, try to allocate a new extent + and take its first page */ ret_descr = fseg_alloc_free_extent(seg_inode, iblock, &xdes, space, mtr, err); - if (!ret_descr) { ut_ad(!has_done_reservation || *err); return nullptr; @@ -2151,14 +2141,13 @@ take_hinted_page: /* Page could not be allocated */ ut_ad(!has_done_reservation); - return(NULL); + return nullptr; } - +alloc_done: if (space->size <= ret_page && !is_predefined_tablespace(space->id)) { /* It must be that we are extending a single-table tablespace whose size is still < 64 pages */ - - if (ret_page >= FSP_EXTENT_SIZE) { + if (ret_page >= extent_size) { sql_print_error("InnoDB: Trying to extend '%s'" " by single page(s) though the" " space size " UINT32PF "." @@ -2166,30 +2155,31 @@ take_hinted_page: space->chain.start->name, space->size, ret_page); ut_ad(!has_done_reservation); - return(NULL); + return nullptr; } if (!fsp_try_extend_data_file_with_pages( space, ret_page, header, mtr)) { /* No disk space left */ ut_ad(!has_done_reservation); - return(NULL); + return nullptr; } } -got_hinted_page: - /* ret_descr == NULL if the block was allocated from free_frag - (XDES_FREE_FRAG) */ + /* Skip the check for extending the tablespace. + If the page hint were not within the size of the tablespace, + descr set to nullptr above and reset the hint and the block + was allocated from free_frag (XDES_FREE_FRAG) */ if (ret_descr != NULL) { +got_hinted_page: /* At this point we know the extent and the page offset. The extent is still in the appropriate list (FSEG_NOT_FULL or FSEG_FREE), and the page is not yet marked as used. */ - ut_d(buf_block_t* xxdes); ut_ad(xdes_get_descriptor(space, ret_page, mtr, err, &xxdes) == ret_descr); ut_ad(xdes == xxdes); - ut_ad(xdes_is_free(ret_descr, ret_page % FSP_EXTENT_SIZE)); + ut_ad(xdes_is_free(ret_descr, ret_page % extent_size)); *err = fseg_mark_page_used(seg_inode, iblock, ret_page, ret_descr, xdes, mtr); diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index b73fc2b54eb..dc88375adb4 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -209,24 +209,6 @@ typedef byte fseg_inode_t; static constexpr byte FSEG_MAGIC_N_BYTES[4]={0x05,0xd6,0x69,0xd2}; -#define FSEG_FILLFACTOR 8 /* If the number of unused but reserved - pages in a segment is less than - reserved pages / FSEG_FILLFACTOR, - and there are - at least FSEG_FRAG_LIMIT used pages, - then we allow a new empty extent to - be added to the segment in - fseg_alloc_free_page_general(). - Otherwise, we - use unused pages of the segment. */ - -#define FSEG_FRAG_LIMIT FSEG_FRAG_ARR_N_SLOTS - /* If the segment has >= this many - used pages, it may be expanded by - allocating extents to the segment; - until that only individual fragment - pages are allocated from the space */ - #define FSEG_FREE_LIST_LIMIT 40 /* If the reserved size of a segment is at least this many extents, we allow extents to be put to the free @@ -294,7 +276,7 @@ Determine if a page is marked free. @param[in] descr extent descriptor @param[in] offset page offset within extent @return whether the page is free */ -inline bool xdes_is_free(const xdes_t *descr, ulint offset) +inline bool xdes_is_free(const xdes_t *descr, uint32_t offset) { ut_ad(offset < FSP_EXTENT_SIZE); ulint index= XDES_FREE_BIT + XDES_BITS_PER_PAGE * offset; diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index fb598e0597c..40b4ff47d54 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -610,7 +610,7 @@ protected: if (m_xdes != 0) { const xdes_t* xdesc = xdes(page_no, m_xdes); - ulint pos = page_no % FSP_EXTENT_SIZE; + uint32_t pos = page_no % FSP_EXTENT_SIZE; return xdes_is_free(xdesc, pos); } From ca07f62992eebd01f72274b56fa3f57170cb2ab6 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Mon, 18 Mar 2024 14:55:05 -0600 Subject: [PATCH 089/106] MDEV-33716: rpl.rpl_semi_sync_slave_enabled_consistent Fails with Error Condition Reached Though the test itself doesn't create any transactions directly, the added test suppressions are replicated, and when the SQL thread is stopped mid-execution, it is set into an error state because these are non-transactional events being aborted. This patch fixes the test by ensuring that the test suppressions are fully replicated before continuing --- .../suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result | 1 + .../suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test | 2 ++ 2 files changed, 3 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result index 11cdb965dd6..4195acb931d 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_slave_enabled_consistent.result @@ -4,6 +4,7 @@ call mtr.add_suppression("Replication event checksum verification failed"); call mtr.add_suppression("could not queue event from master"); call mtr.add_suppression("Semisync ack receiver.*error reading communication packets"); call mtr.add_suppression("Semisync ack receiver got hangup"); +connection slave; # # Set up a semisync connection connection master; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test index ed78eff52ea..ca7e788780c 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_slave_enabled_consistent.test @@ -16,6 +16,8 @@ call mtr.add_suppression("Replication event checksum verification failed"); call mtr.add_suppression("could not queue event from master"); call mtr.add_suppression("Semisync ack receiver.*error reading communication packets"); call mtr.add_suppression("Semisync ack receiver got hangup"); +--sync_slave_with_master + --echo # --echo # Set up a semisync connection --connection master From b8a671988954870b7db22e20d1a1409fd40f8e3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 20 Mar 2024 09:48:03 +0200 Subject: [PATCH 090/106] MDEV-26642/MDEV-26643/MDEV-32898 Implement innodb_snapshot_isolation https://jepsen.io/analyses/mysql-8.0.34 highlights that the transaction isolation levels in the InnoDB storage engine do not correspond to any widely accepted definitions, such as "Generalized Isolation Level Definitions" https://pmg.csail.mit.edu/papers/icde00.pdf (PL-1 = READ UNCOMMITTED, PL-2 = READ COMMITTED, PL-2.99 = REPEATABLE READ, PL-3 = SERIALIZABLE). Only READ UNCOMMITTED in InnoDB seems to match the above definition. The issue is that InnoDB does not detect write/write conflicts (Section 4.4.3, Definition 6) in the above. It appears that as soon as we implement write/write conflict detection (SET SESSION innodb_snapshot_isolation=ON), the default isolation level (SET TRANSACTION ISOLATION LEVEL REPEATABLE READ) will become Snapshot Isolation (similar to Postgres), as defined in Section 4.2 of "A Critique of ANSI SQL Isolation Levels", MSR-TR-95-51, June 1995 https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/tr-95-51.pdf Locking reads inside InnoDB used to read the latest committed version, ignoring what should actually be visible to the transaction. The added test innodb.lock_isolation illustrates this. The statement UPDATE t SET a=3 WHERE b=2; is executed in a transaction that was started before a read view or a snapshot of the current transaction was created, and committed before the current transaction attempts to execute UPDATE t SET b=3; If SET innodb_snapshot_isolation=ON is in effect when the second transaction was started, the second transaction will be aborted with the error ER_CHECKREAD. By default (innodb_snapshot_isolation=OFF), the second transaction would execute inconsistently, displaying an incorrect SELECT COUNT(*) FROM t in its read view. If innodb_snapshot_isolation=ON, if an attempt to acquire a lock on a record that does not exist in the current read view is made, an error DB_RECORD_CHANGED (HA_ERR_RECORD_CHANGED, ER_CHECKREAD) will be raised. This error will be treated in the same way as a deadlock: the transaction will be rolled back. lock_clust_rec_read_check_and_lock(): If the current transaction has a read view where the record is not visible and innodb_snapshot_isolation=ON, fail before trying to acquire the lock. row_sel_build_committed_vers_for_mysql(): If innodb_snapshot_isolation=ON, disable the "semi-consistent read" logic that had been implemented by myself on the directions of Heikki Tuuri in order to address https://bugs.mysql.com/bug.php?id=3300 that was motivated by a customer wanting UPDATE to skip locked rows that do not match the WHERE condition. It looks like my changes were included in the MySQL 5.1.5 commit ad126d90e019f223470e73e1b2b528f9007c4532; at that time, employees of Innobase Oy (a recent acquisition of Oracle) had lost write access to the repository. The only reason why we set innodb_snapshot_isolation=OFF by default is backward compatibility with applications, such as the one that motivated the implementation of "semi-consistent read" back in 2005. In a later major release, we can default to innodb_snapshot_isolation=ON. Thanks to Peter Alvaro, Kyle Kingsbury and Alexey Gotsman for their work on https://github.com/jepsen-io/ and to Kyle and Alexey for explanations and some testing of this fix. Thanks to Vladislav Lesin for the initial test for MDEV-26643, as well as reviewing these changes. --- mysql-test/include/deadlock.inc | 1 - .../include/innodb_rollback_on_timeout.inc | 1 - mysql-test/main/deadlock_innodb.result | 5 - mysql-test/main/mysqld--help.result | 2 +- .../gcol/r/innodb_virtual_debug_purge.result | 10 +- .../gcol/t/innodb_virtual_debug_purge.test | 8 +- mysql-test/suite/innodb/r/innodb_mysql.result | 12 -- .../innodb/r/innodb_timeout_rollback.result | 4 - .../suite/innodb/r/lock_isolation.result | 108 +++++++++++++++++ mysql-test/suite/innodb/t/lock_isolation.test | 110 ++++++++++++++++++ .../r/slave_transaction_retry_errors.result | 10 +- .../suite/sys_vars/r/sysvars_innodb.result | 12 ++ sql/slave.cc | 9 +- storage/innobase/handler/ha_innodb.cc | 16 ++- storage/innobase/handler/handler0alter.cc | 3 + storage/innobase/include/db0err.h | 12 +- storage/innobase/include/row0row.h | 6 + storage/innobase/include/trx0trx.h | 25 ++-- storage/innobase/lock/lock0lock.cc | 8 ++ storage/innobase/row/row0mysql.cc | 1 + storage/innobase/row/row0sel.cc | 5 + storage/innobase/row/row0umod.cc | 2 +- storage/innobase/trx/trx0trx.cc | 8 +- storage/innobase/ut/ut0ut.cc | 6 +- ...ave_transaction_retry_errors_5digit.result | 2 +- .../r/slave_transaction_retry_errors.result | 2 +- 26 files changed, 315 insertions(+), 73 deletions(-) create mode 100644 mysql-test/suite/innodb/r/lock_isolation.result create mode 100644 mysql-test/suite/innodb/t/lock_isolation.test diff --git a/mysql-test/include/deadlock.inc b/mysql-test/include/deadlock.inc index abf217aea75..362d456e3f2 100644 --- a/mysql-test/include/deadlock.inc +++ b/mysql-test/include/deadlock.inc @@ -103,7 +103,6 @@ connection con2; # The following query should hang because con1 is locking the record update t2 set a=2 where b = 0; -select * from t2; --send update t1 set x=2 where id = 0; --sleep 2 diff --git a/mysql-test/include/innodb_rollback_on_timeout.inc b/mysql-test/include/innodb_rollback_on_timeout.inc index 274bbe12566..883b0820589 100644 --- a/mysql-test/include/innodb_rollback_on_timeout.inc +++ b/mysql-test/include/innodb_rollback_on_timeout.inc @@ -22,7 +22,6 @@ select * from t1; connection con1; begin work; insert into t1 values (5); -select * from t1; # Lock wait timeout set to 2 seconds in -master.opt; this # statement will time out; in 5.0.13+, it will not roll back transaction. --error ER_LOCK_WAIT_TIMEOUT diff --git a/mysql-test/main/deadlock_innodb.result b/mysql-test/main/deadlock_innodb.result index 09958bf0413..9236f21c22b 100644 --- a/mysql-test/main/deadlock_innodb.result +++ b/mysql-test/main/deadlock_innodb.result @@ -89,11 +89,6 @@ id x 300 300 connection con2; update t2 set a=2 where b = 0; -select * from t2; -b a -0 2 -1 20 -2 30 update t1 set x=2 where id = 0; connection con1; update t1 set x=1 where id = 0; diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result index 8a60f262554..79c0d7005f2 100644 --- a/mysql-test/main/mysqld--help.result +++ b/mysql-test/main/mysqld--help.result @@ -1837,7 +1837,7 @@ slave-run-triggers-for-rbr NO slave-skip-errors OFF slave-sql-verify-checksum TRUE slave-transaction-retries 10 -slave-transaction-retry-errors 1158,1159,1160,1161,1205,1213,1429,2013,12701 +slave-transaction-retry-errors 1158,1159,1160,1161,1205,1213,1020,1429,2013,12701 slave-transaction-retry-interval 0 slave-type-conversions slow-launch-time 2 diff --git a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result index 63ea5b1d418..505afb9b923 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result @@ -96,11 +96,8 @@ a b c DROP TABLE t1; CREATE TABLE t1 (a INT, b INT, c INT GENERATED ALWAYS AS(a+b)); INSERT INTO t1(a, b) VALUES (1, 1), (2, 2), (3, 3), (4, 4); -connection con1; -# disable purge -BEGIN; -SELECT * FROM t0; -a +connect stop_purge,localhost,root,,; +START TRANSACTION WITH CONSISTENT SNAPSHOT; connection default; DELETE FROM t1 WHERE a = 1; UPDATE t1 SET a = 2, b = 2 WHERE a = 5; @@ -109,10 +106,11 @@ SET DEBUG_SYNC= 'inplace_after_index_build SIGNAL uncommitted WAIT_FOR purged'; ALTER TABLE t1 ADD INDEX idx (c), ALGORITHM=INPLACE, LOCK=NONE; connection con1; SET DEBUG_SYNC= 'now WAIT_FOR uncommitted'; +BEGIN; DELETE FROM t1 WHERE a = 3; UPDATE t1 SET a = 7, b = 7 WHERE a = 4; INSERT INTO t1(a, b) VALUES (8, 8); -# enable purge +disconnect stop_purge; COMMIT; # wait for purge to process the deleted/updated records. InnoDB 2 transactions not purged diff --git a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test index 09fba0285c7..7966953535c 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test @@ -131,9 +131,8 @@ CREATE TABLE t1 (a INT, b INT, c INT GENERATED ALWAYS AS(a+b)); INSERT INTO t1(a, b) VALUES (1, 1), (2, 2), (3, 3), (4, 4); -connection con1; ---echo # disable purge -BEGIN; SELECT * FROM t0; +connect (stop_purge,localhost,root,,); +START TRANSACTION WITH CONSISTENT SNAPSHOT; connection default; DELETE FROM t1 WHERE a = 1; @@ -148,13 +147,14 @@ send ALTER TABLE t1 ADD INDEX idx (c), ALGORITHM=INPLACE, LOCK=NONE; connection con1; SET DEBUG_SYNC= 'now WAIT_FOR uncommitted'; +BEGIN; DELETE FROM t1 WHERE a = 3; UPDATE t1 SET a = 7, b = 7 WHERE a = 4; INSERT INTO t1(a, b) VALUES (8, 8); ---echo # enable purge +disconnect stop_purge; COMMIT; --echo # wait for purge to process the deleted/updated records. diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index d142c0e499e..9d8ead7a165 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -431,10 +431,6 @@ a connection con1; begin work; insert into t1 values (5); -select * from t1; -a -1 -5 insert into t1 values (2); ERROR HY000: Lock wait timeout exceeded; try restarting transaction select * from t1; @@ -509,10 +505,6 @@ a connection con1; begin work; insert into t1 values (5); -select * from t1; -a -1 -5 insert into t1 values (2); ERROR HY000: Lock wait timeout exceeded; try restarting transaction select * from t1; @@ -1217,10 +1209,6 @@ a connection con1; begin work; insert into t1 values (5); -select * from t1; -a -1 -5 insert into t1 values (2); ERROR HY000: Lock wait timeout exceeded; try restarting transaction select * from t1; diff --git a/mysql-test/suite/innodb/r/innodb_timeout_rollback.result b/mysql-test/suite/innodb/r/innodb_timeout_rollback.result index 30db5a21a4d..e8fc89e55ba 100644 --- a/mysql-test/suite/innodb/r/innodb_timeout_rollback.result +++ b/mysql-test/suite/innodb/r/innodb_timeout_rollback.result @@ -17,10 +17,6 @@ a connection con1; begin work; insert into t1 values (5); -select * from t1; -a -1 -5 insert into t1 values (2); ERROR HY000: Lock wait timeout exceeded; try restarting transaction select * from t1; diff --git a/mysql-test/suite/innodb/r/lock_isolation.result b/mysql-test/suite/innodb/r/lock_isolation.result new file mode 100644 index 00000000000..88a2ad9326e --- /dev/null +++ b/mysql-test/suite/innodb/r/lock_isolation.result @@ -0,0 +1,108 @@ +# +# MDEV-26642 Weird SELECT view when a record is +# modified to the same value by two transactions +# MDEV-32898 Phantom rows caused by updates of PRIMARY KEY +# +CREATE TABLE t(a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t VALUES (1,1),(2,2); +BEGIN; +SELECT * FROM t LOCK IN SHARE MODE; +a b +1 1 +2 2 +connect con_weird,localhost,root; +BEGIN; +SELECT * FROM t; +a b +1 1 +2 2 +connect consistent,localhost,root; +SET innodb_snapshot_isolation=ON; +BEGIN; +SELECT * FROM t; +a b +1 1 +2 2 +connection default; +UPDATE t SET a=3 WHERE b=2; +COMMIT; +connection consistent; +UPDATE t SET b=3; +ERROR HY000: Record has changed since last read in table 't' +SELECT * FROM t; +a b +1 1 +3 2 +COMMIT; +connection con_weird; +UPDATE t SET b=3; +SELECT * FROM t; +a b +1 3 +2 2 +3 3 +COMMIT; +connection default; +SELECT * FROM t; +a b +1 3 +3 3 +DROP TABLE t; +# +# MDEV-26643 Inconsistent behaviors of UPDATE under +# READ UNCOMMITTED and READ COMMITTED isolation level +# +CREATE TABLE t(a INT, b INT) ENGINE=InnoDB; +INSERT INTO t VALUES(NULL, 1), (2, 2); +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +BEGIN; +UPDATE t SET a = 10; +connection consistent; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +UPDATE t SET b = 20 WHERE a; +connection default; +COMMIT; +connection consistent; +SELECT * FROM t; +a b +10 20 +10 20 +connection default; +TRUNCATE TABLE t; +INSERT INTO t VALUES(NULL, 1), (2, 2); +BEGIN; +UPDATE t SET a = 10; +connection consistent; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +UPDATE t SET b = 20 WHERE a; +connection default; +COMMIT; +connection consistent; +SELECT * FROM t; +a b +10 20 +10 20 +disconnect consistent; +connection default; +TRUNCATE TABLE t; +INSERT INTO t VALUES(NULL, 1), (2, 2); +BEGIN; +UPDATE t SET a = 10; +connection con_weird; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +UPDATE t SET b = 20 WHERE a; +connection default; +SELECT * FROM t; +a b +10 1 +10 2 +COMMIT; +connection con_weird; +COMMIT; +disconnect con_weird; +connection default; +SELECT * FROM t; +a b +10 1 +10 20 +DROP TABLE t; diff --git a/mysql-test/suite/innodb/t/lock_isolation.test b/mysql-test/suite/innodb/t/lock_isolation.test new file mode 100644 index 00000000000..30d2978f4f2 --- /dev/null +++ b/mysql-test/suite/innodb/t/lock_isolation.test @@ -0,0 +1,110 @@ +--source include/have_innodb.inc + +--echo # +--echo # MDEV-26642 Weird SELECT view when a record is +--echo # modified to the same value by two transactions +--echo # MDEV-32898 Phantom rows caused by updates of PRIMARY KEY +--echo # + +CREATE TABLE t(a INT PRIMARY KEY, b INT) ENGINE=InnoDB; +INSERT INTO t VALUES (1,1),(2,2); +BEGIN; SELECT * FROM t LOCK IN SHARE MODE; +--connect con_weird,localhost,root +BEGIN; +SELECT * FROM t; +--connect consistent,localhost,root +SET innodb_snapshot_isolation=ON; +BEGIN; +SELECT * FROM t; +--connection default +UPDATE t SET a=3 WHERE b=2; +COMMIT; +--connection consistent +--error ER_CHECKREAD +UPDATE t SET b=3; +SELECT * FROM t; +COMMIT; +--connection con_weird +UPDATE t SET b=3; +SELECT * FROM t; +COMMIT; +--connection default +SELECT * FROM t; +DROP TABLE t; + +--echo # +--echo # MDEV-26643 Inconsistent behaviors of UPDATE under +--echo # READ UNCOMMITTED and READ COMMITTED isolation level +--echo # + +CREATE TABLE t(a INT, b INT) ENGINE=InnoDB; +INSERT INTO t VALUES(NULL, 1), (2, 2); +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +BEGIN; UPDATE t SET a = 10; + +--connection consistent +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +--send UPDATE t SET b = 20 WHERE a + +--connection default +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = 'Updating' + and info = 'UPDATE t SET b = 20 WHERE a'; +--source include/wait_condition.inc + +COMMIT; + +--connection consistent +--reap +SELECT * FROM t; + +--connection default +TRUNCATE TABLE t; +INSERT INTO t VALUES(NULL, 1), (2, 2); +BEGIN; UPDATE t SET a = 10; + +--connection consistent +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +--send UPDATE t SET b = 20 WHERE a + +--connection default +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where info = 'UPDATE t SET b = 20 WHERE a'; +--source include/wait_condition.inc + +COMMIT; + +--connection consistent +--reap +SELECT * FROM t; +--disconnect consistent + +--connection default +TRUNCATE TABLE t; +INSERT INTO t VALUES(NULL, 1), (2, 2); +BEGIN; UPDATE t SET a = 10; + +--connection con_weird +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +send UPDATE t SET b = 20 WHERE a; + +--connection default +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = 'Updating' + and info = 'UPDATE t SET b = 20 WHERE a'; +--source include/wait_condition.inc + +SELECT * FROM t; +COMMIT; + +--connection con_weird +--reap +COMMIT; +--disconnect con_weird + +--connection default +SELECT * FROM t; +DROP TABLE t; diff --git a/mysql-test/suite/sys_vars/r/slave_transaction_retry_errors.result b/mysql-test/suite/sys_vars/r/slave_transaction_retry_errors.result index 72b4041599a..43988a81f4f 100644 --- a/mysql-test/suite/sys_vars/r/slave_transaction_retry_errors.result +++ b/mysql-test/suite/sys_vars/r/slave_transaction_retry_errors.result @@ -1,20 +1,20 @@ select @@global.slave_transaction_retry_errors; @@global.slave_transaction_retry_errors -1158,1159,1160,1161,1205,1213,1429,2013,12701,10,20,5000,400 +1158,1159,1160,1161,1205,1213,1020,1429,2013,12701,10,20,5000,400 select @@session.slave_transaction_retry_errors; ERROR HY000: Variable 'slave_transaction_retry_errors' is a GLOBAL variable show global variables like 'slave_transaction_retry_errors'; Variable_name Value -slave_transaction_retry_errors 1158,1159,1160,1161,1205,1213,1429,2013,12701,10,20,5000,400 +slave_transaction_retry_errors 1158,1159,1160,1161,1205,1213,1020,1429,2013,12701,10,20,5000,400 show session variables like 'slave_transaction_retry_errors'; Variable_name Value -slave_transaction_retry_errors 1158,1159,1160,1161,1205,1213,1429,2013,12701,10,20,5000,400 +slave_transaction_retry_errors 1158,1159,1160,1161,1205,1213,1020,1429,2013,12701,10,20,5000,400 select * from information_schema.global_variables where variable_name='slave_transaction_retry_errors'; VARIABLE_NAME VARIABLE_VALUE -SLAVE_TRANSACTION_RETRY_ERRORS 1158,1159,1160,1161,1205,1213,1429,2013,12701,10,20,5000,400 +SLAVE_TRANSACTION_RETRY_ERRORS 1158,1159,1160,1161,1205,1213,1020,1429,2013,12701,10,20,5000,400 select * from information_schema.session_variables where variable_name='slave_transaction_retry_errors'; VARIABLE_NAME VARIABLE_VALUE -SLAVE_TRANSACTION_RETRY_ERRORS 1158,1159,1160,1161,1205,1213,1429,2013,12701,10,20,5000,400 +SLAVE_TRANSACTION_RETRY_ERRORS 1158,1159,1160,1161,1205,1213,1020,1429,2013,12701,10,20,5000,400 set global slave_transaction_retry_errors=1; ERROR HY000: Variable 'slave_transaction_retry_errors' is a read only variable set session slave_transaction_retry_errors=1; diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 8cc23f696b1..148ec4f9c9b 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -1411,6 +1411,18 @@ NUMERIC_BLOCK_SIZE 0 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME INNODB_SNAPSHOT_ISOLATION +SESSION_VALUE OFF +DEFAULT_VALUE OFF +VARIABLE_SCOPE SESSION +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Use snapshot isolation (write-write conflict detection). +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_SORT_BUFFER_SIZE SESSION_VALUE NULL DEFAULT_VALUE 1048576 diff --git a/sql/slave.cc b/sql/slave.cc index 1e73b9c2612..63346d29bbb 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -858,7 +858,7 @@ static void make_slave_transaction_retry_errors_printable(void) } -#define DEFAULT_SLAVE_RETRY_ERRORS 9 +static constexpr uint DEFAULT_SLAVE_RETRY_ERRORS= 10; bool init_slave_transaction_retry_errors(const char* arg) { @@ -900,9 +900,10 @@ bool init_slave_transaction_retry_errors(const char* arg) slave_transaction_retry_errors[3]= ER_NET_WRITE_INTERRUPTED; slave_transaction_retry_errors[4]= ER_LOCK_WAIT_TIMEOUT; slave_transaction_retry_errors[5]= ER_LOCK_DEADLOCK; - slave_transaction_retry_errors[6]= ER_CONNECT_TO_FOREIGN_DATA_SOURCE; - slave_transaction_retry_errors[7]= 2013; /* CR_SERVER_LOST */ - slave_transaction_retry_errors[8]= 12701; /* ER_SPIDER_REMOTE_SERVER_GONE_AWAY_NUM */ + slave_transaction_retry_errors[6]= ER_CHECKREAD; + slave_transaction_retry_errors[7]= ER_CONNECT_TO_FOREIGN_DATA_SOURCE; + slave_transaction_retry_errors[8]= 2013; /* CR_SERVER_LOST */ + slave_transaction_retry_errors[9]= 12701; /* ER_SPIDER_REMOTE_SERVER_GONE_AWAY_NUM */ /* Add user codes after this */ for (p= arg, i= DEFAULT_SLAVE_RETRY_ERRORS; *p; ) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 474e5669222..c13cb55f805 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -881,6 +881,10 @@ static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG, /* check_func */ NULL, /* update_func */ NULL, /* default */ TRUE); +static MYSQL_THDVAR_BOOL(snapshot_isolation, PLUGIN_VAR_OPCMDARG, + "Use snapshot isolation (write-write conflict detection).", + NULL, NULL, FALSE); + static MYSQL_THDVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG, "Use strict mode when evaluating create options.", NULL, NULL, TRUE); @@ -2238,6 +2242,9 @@ convert_error_code_to_mysql( return(HA_ERR_LOCK_DEADLOCK); + case DB_RECORD_CHANGED: + return HA_ERR_RECORD_CHANGED; + case DB_LOCK_WAIT_TIMEOUT: /* Starting from 5.0.13, we let MySQL just roll back the latest SQL statement in a lock wait timeout. Previously, we @@ -2881,6 +2888,8 @@ innobase_trx_init( trx->check_unique_secondary = !thd_test_options( thd, OPTION_RELAXED_UNIQUE_CHECKS); + trx->snapshot_isolation = THDVAR(thd, snapshot_isolation) & 1; + #ifdef WITH_WSREP trx->wsrep = wsrep_on(thd); #endif @@ -4431,7 +4440,7 @@ innobase_start_trx_and_assign_read_view( Do this only if transaction is using REPEATABLE READ isolation level. */ trx->isolation_level = innobase_map_isolation_level( - thd_get_trx_isolation(thd)); + thd_get_trx_isolation(thd)) & 3; if (trx->isolation_level == TRX_ISO_REPEATABLE_READ) { trx->read_view.open(trx); @@ -15376,7 +15385,7 @@ ha_innobase::check( } /* Restore the original isolation level */ - m_prebuilt->trx->isolation_level = old_isolation_level; + m_prebuilt->trx->isolation_level = old_isolation_level & 3; #ifdef BTR_CUR_HASH_ADAPT # if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG /* We validate the whole adaptive hash index for all tables @@ -16431,7 +16440,7 @@ ha_innobase::store_lock( if (lock_type != TL_IGNORE && trx->n_mysql_tables_in_use == 0) { trx->isolation_level = innobase_map_isolation_level( - (enum_tx_isolation) thd_tx_isolation(thd)); + (enum_tx_isolation) thd_tx_isolation(thd)) & 3; if (trx->isolation_level <= TRX_ISO_READ_COMMITTED) { @@ -19802,6 +19811,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(ft_server_stopword_table), MYSQL_SYSVAR(ft_user_stopword_table), MYSQL_SYSVAR(disable_sort_file_cache), + MYSQL_SYSVAR(snapshot_isolation), MYSQL_SYSVAR(stats_on_metadata), MYSQL_SYSVAR(stats_transient_sample_pages), MYSQL_SYSVAR(stats_persistent), diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index f278c428d62..96c03891679 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -864,6 +864,9 @@ my_error_innodb( case DB_DEADLOCK: my_error(ER_LOCK_DEADLOCK, MYF(0)); break; + case DB_RECORD_CHANGED: + my_error(ER_CHECKREAD, MYF(0), table); + break; case DB_LOCK_WAIT_TIMEOUT: my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0)); break; diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h index 64182aabc38..960ec3905eb 100644 --- a/storage/innobase/include/db0err.h +++ b/storage/innobase/include/db0err.h @@ -32,23 +32,25 @@ Created 5/24/1996 Heikki Tuuri enum dberr_t { DB_SUCCESS, - DB_SUCCESS_LOCKED_REC = 9, /*!< like DB_SUCCESS, but a new + DB_SUCCESS_LOCKED_REC= 9, /*!< like DB_SUCCESS, but a new explicit record lock was created */ /* The following are error codes */ - DB_ERROR = 11, + DB_RECORD_CHANGED, + DB_ERROR, DB_INTERRUPTED, DB_OUT_OF_MEMORY, DB_OUT_OF_FILE_SPACE, DB_LOCK_WAIT, DB_DEADLOCK, - DB_ROLLBACK, DB_DUPLICATE_KEY, DB_MISSING_HISTORY, /*!< required history data has been deleted due to lack of space in rollback segment */ - DB_CLUSTER_NOT_FOUND = 30, - DB_TABLE_NOT_FOUND, +#ifdef WITH_WSREP + DB_ROLLBACK, +#endif + DB_TABLE_NOT_FOUND= 31, DB_TOO_BIG_RECORD, /*!< a record in an index would not fit on a compressed page, or it would become bigger than 1/2 free space in diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h index a1350740e2a..7056c77f2e6 100644 --- a/storage/innobase/include/row0row.h +++ b/storage/innobase/include/row0row.h @@ -370,6 +370,12 @@ row_search_index_entry( mtr_t* mtr) /*!< in: mtr */ MY_ATTRIBUTE((nonnull, warn_unused_result)); +/** Get the byte offset of the DB_TRX_ID column +@param[in] rec clustered index record +@param[in] index clustered index +@return the byte offset of DB_TRX_ID, from the start of rec */ +ulint row_trx_id_offset(const rec_t* rec, const dict_index_t* index); + #define ROW_COPY_DATA 1 #define ROW_COPY_POINTERS 2 diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index d5638778079..361d58f5663 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -739,13 +739,19 @@ public: const char* op_info; /*!< English text describing the current operation, or an empty string */ - uint isolation_level;/*!< TRX_ISO_REPEATABLE_READ, ... */ - bool check_foreigns; /*!< normally TRUE, but if the user - wants to suppress foreign key checks, - (in table imports, for example) we - set this FALSE */ + /** TRX_ISO_REPEATABLE_READ, ... */ + unsigned isolation_level:2; + /** when set, REPEATABLE READ will actually be Snapshot Isolation, due to + detecting write/write conflicts and disabling "semi-consistent read" */ + unsigned snapshot_isolation:1; + /** normally set; "SET foreign_key_checks=0" can be issued to suppress + foreign key checks, in table imports, for example */ + unsigned check_foreigns:1; + /** normally set; "SET unique_checks=0, foreign_key_checks=0" + enables bulk insert into an empty table */ + unsigned check_unique_secondary:1; /** whether an insert into an empty table is active */ - bool bulk_insert; + unsigned bulk_insert:1; /*------------------------------*/ /* MySQL has a transaction coordinator to coordinate two phase commit between multiple storage engines and the binary log. When @@ -759,13 +765,6 @@ public: /** whether this is holding the prepare mutex */ bool active_commit_ordered; /*------------------------------*/ - bool check_unique_secondary; - /*!< normally TRUE, but if the user - wants to speed up inserts by - suppressing unique key checks - for secondary indexes when we decide - if we can use the insert buffer for - them, we set this FALSE */ bool flush_log_later;/* In 2PC, we hold the prepare_commit mutex across both phases. In that case, we diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index daef137db29..27209f71795 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -5949,6 +5949,14 @@ lock_clust_rec_read_check_and_lock( return DB_SUCCESS; } + if (heap_no > PAGE_HEAP_NO_SUPREMUM && gap_mode != LOCK_GAP + && trx->snapshot_isolation + && trx->read_view.is_open() + && !trx->read_view.changes_visible( + trx_read_trx_id(rec + row_trx_id_offset(rec, index)))) { + return DB_RECORD_CHANGED; + } + dberr_t err = lock_rec_lock(false, gap_mode | mode, block, heap_no, index, thr); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 6a518cddadf..b12100be7b5 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -695,6 +695,7 @@ handle_new_error: DBUG_RETURN(true); case DB_DEADLOCK: + case DB_RECORD_CHANGED: case DB_LOCK_TABLE_FULL: rollback: /* Roll back the whole transaction; this resolution was added diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 58684ebf20d..6886ca1ae5d 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -865,6 +865,11 @@ row_sel_build_committed_vers_for_mysql( column version if any */ mtr_t* mtr) /*!< in: mtr */ { + if (prebuilt->trx->snapshot_isolation) { + *old_vers = rec; + return; + } + if (prebuilt->old_vers_heap) { mem_heap_empty(prebuilt->old_vers_heap); } else { diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index a01eaea516a..52f54443911 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -190,7 +190,7 @@ row_undo_mod_clust_low( @param[in] rec clustered index record @param[in] index clustered index @return the byte offset of DB_TRX_ID, from the start of rec */ -static ulint row_trx_id_offset(const rec_t* rec, const dict_index_t* index) +ulint row_trx_id_offset(const rec_t* rec, const dict_index_t* index) { ut_ad(index->n_uniq <= MAX_REF_PARTS); ulint trx_id_offset = index->trx_id_offset; diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 58e36726bbc..59685e21cfb 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -412,12 +412,12 @@ void trx_t::free() #endif read_view.mem_noaccess(); MEM_NOACCESS(&lock, sizeof lock); - MEM_NOACCESS(&op_info, sizeof op_info); - MEM_NOACCESS(&isolation_level, sizeof isolation_level); - MEM_NOACCESS(&check_foreigns, sizeof check_foreigns); + MEM_NOACCESS(&op_info, sizeof op_info + + sizeof(unsigned) /* isolation_level, snapshot_isolation, + check_foreigns, check_unique_secondary, + bulk_insert */); MEM_NOACCESS(&is_registered, sizeof is_registered); MEM_NOACCESS(&active_commit_ordered, sizeof active_commit_ordered); - MEM_NOACCESS(&check_unique_secondary, sizeof check_unique_secondary); MEM_NOACCESS(&flush_log_later, sizeof flush_log_later); MEM_NOACCESS(&duplicates, sizeof duplicates); MEM_NOACCESS(&dict_operation, sizeof dict_operation); diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index 7f4d2da2089..3cdc49c4b32 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -312,14 +312,16 @@ ut_strerr( return("Lock wait"); case DB_DEADLOCK: return("Deadlock"); + case DB_RECORD_CHANGED: + return("Record changed"); +#ifdef WITH_WSREP case DB_ROLLBACK: return("Rollback"); +#endif case DB_DUPLICATE_KEY: return("Duplicate key"); case DB_MISSING_HISTORY: return("Required history data has been deleted"); - case DB_CLUSTER_NOT_FOUND: - return("Cluster not found"); case DB_TABLE_NOT_FOUND: return("Table not found"); case DB_TOO_BIG_RECORD: diff --git a/storage/spider/mysql-test/spider/bugfix/r/slave_transaction_retry_errors_5digit.result b/storage/spider/mysql-test/spider/bugfix/r/slave_transaction_retry_errors_5digit.result index f2cab6b0a95..c8b1de982eb 100644 --- a/storage/spider/mysql-test/spider/bugfix/r/slave_transaction_retry_errors_5digit.result +++ b/storage/spider/mysql-test/spider/bugfix/r/slave_transaction_retry_errors_5digit.result @@ -9,7 +9,7 @@ for slave1_1 connection slave1_1; SHOW VARIABLES LIKE 'slave_transaction_retry_errors'; Variable_name Value -slave_transaction_retry_errors 1158,1159,1160,1161,1205,1213,1429,2013,12701,10000,20000,30000 +slave_transaction_retry_errors 1158,1159,1160,1161,1205,1213,1020,1429,2013,12701,10000,20000,30000 connection slave1_1; for slave1_1 for master_1 diff --git a/storage/spider/mysql-test/spider/feature/r/slave_transaction_retry_errors.result b/storage/spider/mysql-test/spider/feature/r/slave_transaction_retry_errors.result index 0a147c0356a..1de1ba04528 100644 --- a/storage/spider/mysql-test/spider/feature/r/slave_transaction_retry_errors.result +++ b/storage/spider/mysql-test/spider/feature/r/slave_transaction_retry_errors.result @@ -9,7 +9,7 @@ for slave1_1 connection slave1_1; SHOW VARIABLES LIKE 'slave_transaction_retry_errors'; Variable_name Value -slave_transaction_retry_errors 1158,1159,1160,1161,1205,1213,1429,2013,12701 +slave_transaction_retry_errors 1158,1159,1160,1161,1205,1213,1020,1429,2013,12701 connection slave1_1; for slave1_1 for master_1 From 75c7c6dc39a1b622b876199aca8242bd23720844 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Tue, 27 Feb 2024 12:11:06 -0700 Subject: [PATCH 091/106] MDEV-33551: Semi-sync Wait Point AFTER_COMMIT Slow on Workloads with Heavy Concurrency When using semi-sync replication with rpl_semi_sync_master_wait_point=AFTER_COMMIT, the performance of the primary can significantly reduce compared to AFTER_SYNC's performance for workloads with many concurrent users executing transactions. This is because all connections on the primary share the same cond_wait variable/mutex pair, so any time an ACK is received from a replica, all waiting connections are awoken to check if the ACK was for itself, which is done in mutual exclusion. This patch changes this such that the waiting THD will use its own local condition variable, and the ACK receiver thread only signals connections which have been ACKed for wakeup. That is, the THD::LOCK_wakeup_ready condition variable is re-used for this purpose, and the Active_tranx queue nodes are extended to hold the waiting thread, so it can be signalled once ACKed. Additionally: 1) Removed part of MDEV-11853 additions, which allowed suspended connection threads awaiting their semi-sync ACKs to live until their ACKs had been received. This part, however, wasn't needed. That is, all that was needed was for the Ack_thread to survive. So now the connection threads are killed during phase 1. Thereby THD::is_awaiting_semisync_ack, and all its related code was removed. 2) COND_binlog_send is repurposed to signal on the condition when Active_tranx is emptied during clear_active_tranx_nodes. 3) At master shutdown (when waiting for slaves), instead of the main loop individually waiting for each ACK, await_slave_reply() (renamed await_all_slave_replies()) just waits once for the repurposed COND_binlog_send to signal it is empty. 4) Test rpl_semi_sync_shutdown_await_ack is updates as following: 4.1) Added test case (adapted from Kristian Nielsen) to ensure that if a thread awaiting its ACK is killed while SHUTDOWN WAIT FOR ALL SLAVES is issued, the primary will still wait for the ACK from the killed thread. 4.2) As connections which by-passed phase 1 of thread killing no longer are delayed for kill until phase 2, we can no longer query yes/no tx after receiving an ACK/timeout. The check for these variables is removed. 4.3) Comment descriptions are updated which mention that the connection is alive; and adjusted to be the Ack_thread. Reviewed By: ============ Kristian Nielsen --- .../r/rpl_semi_sync_cond_var_per_thd.result | 32 ++ .../r/rpl_semi_sync_shutdown_await_ack.result | 109 +++---- .../rpl/t/rpl_semi_sync_cond_var_per_thd.cnf | 10 + .../rpl/t/rpl_semi_sync_cond_var_per_thd.test | 77 +++++ .../t/rpl_semi_sync_shutdown_await_ack.inc | 13 +- .../t/rpl_semi_sync_shutdown_await_ack.test | 143 +++++++-- sql/log.cc | 16 +- sql/mysqld.cc | 31 +- sql/semisync_master.cc | 289 +++++++++++------- sql/semisync_master.h | 117 ++++--- sql/sql_class.cc | 3 +- sql/sql_class.h | 22 +- 12 files changed, 588 insertions(+), 274 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_semi_sync_cond_var_per_thd.result create mode 100644 mysql-test/suite/rpl/t/rpl_semi_sync_cond_var_per_thd.cnf create mode 100644 mysql-test/suite/rpl/t/rpl_semi_sync_cond_var_per_thd.test diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_cond_var_per_thd.result b/mysql-test/suite/rpl/r/rpl_semi_sync_cond_var_per_thd.result new file mode 100644 index 00000000000..08f601447d5 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_cond_var_per_thd.result @@ -0,0 +1,32 @@ +include/master-slave.inc +[connection master] +connection master; +call mtr.add_suppression("Got an error reading communication packets"); +set @save_bgc_count= @@global.binlog_commit_wait_count; +set @save_bgc_usec= @@global.binlog_commit_wait_usec; +set @save_debug_dbug= @@global.debug_dbug; +set @@global.binlog_commit_wait_count=3; +set @@global.binlog_commit_wait_usec=10000000; +set @@global.debug_dbug="+d,testing_cond_var_per_thd"; +# Ensure semi-sync is on +connection slave; +connection master; +# Create three transactions to binlog group commit together +connection master; +create table t1 (a int); +connection server_1; +create table t2 (a int); +connection default; +create table t3 (a int); +connection master; +connection server_1; +connection default; +include/assert_grep.inc [Check that there is no 'Thread awaiting semi-sync ACK was awoken before its ACK' warning in error log.] +# +# Cleanup +connection master; +set @@global.binlog_commit_wait_count=@save_bgc_count; +set @@global.binlog_commit_wait_usec=@save_bgc_usec; +set @@global.debug_dbug=@save_debug_dbug; +drop table t1, t2, t3; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result b/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result index ebd67c947f0..a8e158a25e4 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_shutdown_await_ack.result @@ -25,7 +25,7 @@ call mtr.add_suppression("Failed to kill the active semi-sync connection"); set @sav_enabled_server_3= @@GLOBAL.rpl_semi_sync_slave_enabled; set @sav_server_3_dbug= @@GLOBAL.debug_dbug; connection server_1; -CREATE TABLE t1 (a int); +CREATE TABLE t1 (a int) engine=innodb; connection server_2; connection server_3; connect server_1_con2, localhost, root,,; @@ -34,8 +34,8 @@ connect server_1_con2, localhost, root,,; ############################# # # Test Case 1) If both replicas simulate a delay that is within the -# allowed timeout, the primary should delay killing the suspended thread -# until an ACK is received (Rpl_semi_sync_master_yes_tx should be 1). +# allowed timeout, the primary should delay killing the Ack_thread +# until an ACK is received. # connection server_1; #-- @@ -78,8 +78,6 @@ SET @@GLOBAL.debug_dbug= "+d,simulate_delay_semisync_slave_reply"; #-- #-- Test begins connection server_1_con2; -#-- Give enough time after timeout/ack received to query yes_tx/no_tx -SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; connection server_1; #-- Begin semi-sync transaction INSERT INTO t1 VALUES (1); @@ -88,14 +86,7 @@ connection server_1_con2; #-- Begin master shutdown SHUTDOWN WAIT FOR ALL SLAVES; connection server_1; -#-- Ensure either ACK was received (yes_tx=1) or timeout (no_tx=1) -show status like 'Rpl_semi_sync_master_yes_tx'; -Variable_name Value -Rpl_semi_sync_master_yes_tx 1 -show status like 'Rpl_semi_sync_master_no_tx'; -Variable_name Value -Rpl_semi_sync_master_no_tx 0 -connection server_1_con2; +ERROR HY000: Lost connection to server during query # Check logs to ensure shutdown was delayed FOUND 1 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err # Validate slave data is in correct state @@ -144,8 +135,8 @@ COUNT(*)=0 1 # # Test Case 2) If both replicas simulate an error before sending an ACK, -# the primary should delay killing the suspended thread until the -# timeout is reached (Rpl_semi_sync_master_no_tx should be 1). +# the primary should delay killing the Ack_thread until the +# timeout is reached. # connection server_1; #-- @@ -188,8 +179,6 @@ SET @@GLOBAL.debug_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_ #-- #-- Test begins connection server_1_con2; -#-- Give enough time after timeout/ack received to query yes_tx/no_tx -SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; connection server_1; #-- Begin semi-sync transaction INSERT INTO t1 VALUES (1); @@ -198,14 +187,7 @@ connection server_1_con2; #-- Begin master shutdown SHUTDOWN WAIT FOR ALL SLAVES; connection server_1; -#-- Ensure either ACK was received (yes_tx=1) or timeout (no_tx=1) -show status like 'Rpl_semi_sync_master_yes_tx'; -Variable_name Value -Rpl_semi_sync_master_yes_tx 0 -show status like 'Rpl_semi_sync_master_no_tx'; -Variable_name Value -Rpl_semi_sync_master_no_tx 1 -connection server_1_con2; +ERROR HY000: Lost connection to server during query # Check logs to ensure shutdown was delayed FOUND 2 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err # Validate slave data is in correct state @@ -267,8 +249,8 @@ COUNT(*)=0 # # Test Case 3) If one replica simulates a delay within the allowed # timeout and the other simulates an error before sending an ACK, the -# primary should delay killing the suspended thread until it receives an -# ACK from the delayed slave (Rpl_semi_sync_master_yes_tx should be 1). +# primary should delay killing the Ack_thread until it receives an +# ACK from the delayed slave. # connection server_1; #-- @@ -311,8 +293,6 @@ SET @@GLOBAL.debug_dbug= "+d,simulate_delay_semisync_slave_reply"; #-- #-- Test begins connection server_1_con2; -#-- Give enough time after timeout/ack received to query yes_tx/no_tx -SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; connection server_1; #-- Begin semi-sync transaction INSERT INTO t1 VALUES (1); @@ -321,14 +301,7 @@ connection server_1_con2; #-- Begin master shutdown SHUTDOWN WAIT FOR ALL SLAVES; connection server_1; -#-- Ensure either ACK was received (yes_tx=1) or timeout (no_tx=1) -show status like 'Rpl_semi_sync_master_yes_tx'; -Variable_name Value -Rpl_semi_sync_master_yes_tx 1 -show status like 'Rpl_semi_sync_master_no_tx'; -Variable_name Value -Rpl_semi_sync_master_no_tx 0 -connection server_1_con2; +ERROR HY000: Lost connection to server during query # Check logs to ensure shutdown was delayed FOUND 3 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err # Validate slave data is in correct state @@ -391,8 +364,7 @@ COUNT(*)=0 # active semi-sync connection in-tact. The slave should notice this, and # not issue a `QUIT` command to the primary, which would otherwise be # sent to kill an active connection. This test case validates that the -# slave does not send a `QUIT` in this case (Rpl_semi_sync_master_yes_tx -# should be 1 because server_3 will send the ACK within a valid timeout). +# slave does not send a `QUIT` in this case. # connection server_1; #-- @@ -435,8 +407,6 @@ SET @@GLOBAL.debug_dbug= "+d,simulate_delay_semisync_slave_reply"; #-- #-- Test begins connection server_1_con2; -#-- Give enough time after timeout/ack received to query yes_tx/no_tx -SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; connection server_1; #-- Begin semi-sync transaction INSERT INTO t1 VALUES (1); @@ -445,14 +415,7 @@ connection server_1_con2; #-- Begin master shutdown SHUTDOWN WAIT FOR ALL SLAVES; connection server_1; -#-- Ensure either ACK was received (yes_tx=1) or timeout (no_tx=1) -show status like 'Rpl_semi_sync_master_yes_tx'; -Variable_name Value -Rpl_semi_sync_master_yes_tx 1 -show status like 'Rpl_semi_sync_master_no_tx'; -Variable_name Value -Rpl_semi_sync_master_no_tx 0 -connection server_1_con2; +ERROR HY000: Lost connection to server during query # Check logs to ensure shutdown was delayed FOUND 4 /Delaying shutdown to await semi-sync ACK/ in mysqld.1.err # Validate slave data is in correct state @@ -506,16 +469,60 @@ Rpl_semi_sync_slave_status OFF SELECT COUNT(*)=0 from t1; COUNT(*)=0 1 +# +# Test Case 5) If a waiting-for-ACK user thread is killed (disconnected) +# during SHUTDOWN WAIT FOR ALL SLAVES, ensure the primary will still +# await the ACK from the replica before killing the Ack_receiver thread +# +connection server_1; +insert into t1 values (1); +include/save_master_gtid.inc +connection server_2; +include/sync_with_master_gtid.inc +include/stop_slave.inc +SET GLOBAL rpl_semi_sync_slave_enabled= 1; +include/start_slave.inc +connection server_1; +SET GLOBAL rpl_semi_sync_master_enabled= 1; +SET GLOBAL rpl_semi_sync_master_timeout= 2000; +show status like 'Rpl_semi_sync_master_status'; +Variable_name Value +Rpl_semi_sync_master_status ON +show status like 'Rpl_semi_sync_master_clients'; +Variable_name Value +Rpl_semi_sync_master_clients 1 +connection server_2; +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,simulate_delay_semisync_slave_reply"; +connect con1, localhost, root,,; +connect con2, localhost, root,,; +connection con1; +insert into t1 values (2); +connection server_1; +# Wait for thd to begin semi-sync wait.. +# ..done +disconnect con1; +connection default; +connection con2; +SHUTDOWN WAIT FOR ALL SLAVES; +connection server_2; +include/assert_grep.inc [Ensure the primary waited for the ACK of the killed thread] +connection default; +connection server_1; +connection server_2; +include/stop_slave.inc +connection server_3; +include/stop_slave.inc +connection default; +connection server_1; ############################# # Cleanup ############################# connection server_2; -include/stop_slave.inc SET @@GLOBAL.rpl_semi_sync_slave_enabled = @sav_enabled_server_2; SET @@GLOBAL.debug_dbug= @sav_server_2_dbug; include/start_slave.inc connection server_3; -include/stop_slave.inc SET @@GLOBAL.rpl_semi_sync_slave_enabled = @sav_enabled_server_3; SET @@GLOBAL.debug_dbug= @sav_server_3_dbug; include/start_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_cond_var_per_thd.cnf b/mysql-test/suite/rpl/t/rpl_semi_sync_cond_var_per_thd.cnf new file mode 100644 index 00000000000..e8e03e71ec8 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_cond_var_per_thd.cnf @@ -0,0 +1,10 @@ +!include ../my.cnf + +[mysqld.1] +log-warnings=9 +rpl_semi_sync_master_enabled=1 +rpl_semi_sync_master_wait_point=AFTER_COMMIT + +[mysqld.2] +log-warnings=9 +rpl_semi_sync_slave_enabled=1 diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_cond_var_per_thd.test b/mysql-test/suite/rpl/t/rpl_semi_sync_cond_var_per_thd.test new file mode 100644 index 00000000000..65b6e8b4f7b --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_cond_var_per_thd.test @@ -0,0 +1,77 @@ +# +# This test ensures that, when using semi-sync with the wait_point +# AFTER_COMMIT, each thread awaiting an ACK is only woken up when its ACK (or +# an ACK for a later commit in binlog) has been received from the slave. +# +# Prior to MDEV-33551, all threads would be woken up for each ACK received, +# leading to large slowdowns, as each thread would check if the ACK was for it +# in mutual exclusion from the others. +# +# To ensure this, a debug-build-only log warning is added into +# Repl_semi_sync_master::commit_trx() at wakeup time, which will complain if +# the awoken thread's binlog wait coordinates are after the coordinate of the +# last ACK coordinates. Then, we use binlog group commit to commit a series of +# transactions, such that each will await an ACK concurrently. After all +# transactions have been finished (i.e. ACKed and committed), we check the log +# for the expected absence of the added debug warning message. +# +# +# References: +# MDEV-33551: Semi-sync Wait Point AFTER_COMMIT Slow on Workloads with Heavy +# Concurrency +# +--source include/have_binlog_format_row.inc +--source include/have_debug.inc +--source include/master-slave.inc + +--connection master +call mtr.add_suppression("Got an error reading communication packets"); +set @save_bgc_count= @@global.binlog_commit_wait_count; +set @save_bgc_usec= @@global.binlog_commit_wait_usec; +set @save_debug_dbug= @@global.debug_dbug; +set @@global.binlog_commit_wait_count=3; +set @@global.binlog_commit_wait_usec=10000000; +set @@global.debug_dbug="+d,testing_cond_var_per_thd"; + +--echo # Ensure semi-sync is on +--connection slave +let $status_var= rpl_semi_sync_slave_status; +let $status_var_value= ON; +source include/wait_for_status_var.inc; + +--connection master +let $status_var= rpl_semi_sync_master_status; +let $status_var_value= ON; +source include/wait_for_status_var.inc; + +--echo # Create three transactions to binlog group commit together +--connection master +--send create table t1 (a int) +--connection server_1 +--send create table t2 (a int) +--connection default +--send create table t3 (a int) + +--connection master +--reap +--connection server_1 +--reap +--connection default +--reap + +--let $assert_text= Check that there is no 'Thread awaiting semi-sync ACK was awoken before its ACK' warning in error log. +--let $assert_select=Thread awaiting semi-sync ACK was awoken before its ACK +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $assert_count= 0 +--let $assert_only_after=CURRENT_TEST +--source include/assert_grep.inc + +--echo # +--echo # Cleanup +--connection master +set @@global.binlog_commit_wait_count=@save_bgc_count; +set @@global.binlog_commit_wait_usec=@save_bgc_usec; +set @@global.debug_dbug=@save_debug_dbug; +drop table t1, t2, t3; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc index a41ef2756d1..d20ef628327 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.inc @@ -64,9 +64,6 @@ show status like 'Rpl_semi_sync_master_clients'; --echo #-- Test begins --connection server_1_con2 ---echo #-- Give enough time after timeout/ack received to query yes_tx/no_tx -SET @@GLOBAL.debug_dbug= "+d,delay_shutdown_phase_2_after_semisync_wait"; - --write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect wait EOF @@ -82,15 +79,11 @@ let $status_var_value= 1; source include/wait_for_status_var.inc; --echo #-- Begin master shutdown ---send SHUTDOWN WAIT FOR ALL SLAVES +SHUTDOWN WAIT FOR ALL SLAVES; +--source include/wait_until_disconnected.inc --connection server_1 ---reap ---echo #-- Ensure either ACK was received (yes_tx=1) or timeout (no_tx=1) -show status like 'Rpl_semi_sync_master_yes_tx'; -show status like 'Rpl_semi_sync_master_no_tx'; - ---connection server_1_con2 +--error 2013 --reap --source include/wait_until_disconnected.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test index fca6de4c209..c321f2bf72f 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_shutdown_await_ack.test @@ -5,7 +5,7 @@ # This test validates that data is consistent between a primary and replica # in semi-sync mode when the primary is issued `SHUTDOWN WAIT FOR SLAVES` # during an active communication. More specifically, the primary should not -# kill the connection until it is sure a replica has received all binlog +# kill the Ack_thread until it is sure a replica has received all binlog # data, i.e. once the primary receives the ACK. If a primary is issued a # shutdown before receiving an ACK, it should wait until either 1) the ACK is # received, or 2) the configured timeout (rpl_semi_sync_master_timeout) is @@ -15,23 +15,18 @@ # Using a topology consisting of one primary with two replicas, all in # semi-sync mode, we use DEBUG_DBUG to simulate an error or delay on the # replicas during an active communication while the primary is issued -# `SHUTDOWN WAIT FOR SLAVES`. We create four test cases to ensure the primary -# will correctly wait for the communication to finish, and use the semi-sync -# status variables Rpl_semi_sync_master_yes_tx and Rpl_semi_sync_master_no_tx -# to ensure the connection was not prematurely killed due to the shutdown. +# `SHUTDOWN WAIT FOR SLAVES`. We create four test cases to ensure the +# Ack_thread is not prematurely killed due to the shutdown. # Test Case 1) If both replicas simulate a delay that is within the allowed -# timeout, the primary should delay killing the suspended thread -# until an ACK is received (Rpl_semi_sync_master_yes_tx should -# be 1). +# timeout, the primary should delay killing the Ack_thread +# until an ACK is received. # Test Case 2) If both replicas simulate an error before sending an ACK, the -# primary should delay killing the suspended thread until the -# the timeout is reached (Rpl_semi_sync_master_no_tx should be -# 1). +# primary should delay killing the Ack_thread until the +# the timeout is reached. # Test Case 3) If one replica simulates a delay within the allowed timeout # and the other simulates an error before sending an ACK, the -# primary should delay killing the suspended thread until it -# receives an ACK from the delayed slave -# (Rpl_semi_sync_master_yes_tx should be 1). +# primary should delay killing the Ack_thread until it +# receives an ACK from the delayed slave. # Test Case 4) If a replica errors before sending an ACK, it will cause the # IO thread to stop and handle the error. During error handling, # if semi-sync is active, the replica will form a new connection @@ -41,9 +36,11 @@ # slave should notice this, and not issue a `QUIT` command to # the primary, which would otherwise be sent to kill an active # connection. This test case validates that the slave does not -# send a `QUIT` in this case (Rpl_semi_sync_master_yes_tx should -# be 1 because server_3 will send the ACK within a valid -# timeout). +# send a `QUIT` in this case. +# Test Case 5) If a waiting-for-ACK user thread is killed (disconnected) +# during SHUTDOWN WAIT FOR ALL SLAVES, ensure the primary will +# still await the ACK from the replica before killing the +# Ack_thread. # # References: # MDEV-11853: semisync thread can be killed after sync binlog but before ACK @@ -58,6 +55,7 @@ --echo # Note: Simulated slave delay is hardcoded to 800 milliseconds --echo # Note: Simulated master shutdown delay is hardcoded to 500 milliseconds +--source include/have_innodb.inc --source include/have_debug.inc --let $rpl_topology=1->2, 1->3 --source include/rpl_init.inc @@ -90,7 +88,7 @@ set @sav_enabled_server_3= @@GLOBAL.rpl_semi_sync_slave_enabled; set @sav_server_3_dbug= @@GLOBAL.debug_dbug; --connection server_1 -CREATE TABLE t1 (a int); +CREATE TABLE t1 (a int) engine=innodb; --save_master_pos --let i= 2 @@ -112,8 +110,8 @@ while (`SELECT $i <= $slave_last`) --echo # --echo # Test Case 1) If both replicas simulate a delay that is within the ---echo # allowed timeout, the primary should delay killing the suspended thread ---echo # until an ACK is received (Rpl_semi_sync_master_yes_tx should be 1). +--echo # allowed timeout, the primary should delay killing the Ack_thread +--echo # until an ACK is received. --echo # --let server_2_dbug= "+d,simulate_delay_semisync_slave_reply" --let server_3_dbug= "+d,simulate_delay_semisync_slave_reply" @@ -124,8 +122,8 @@ while (`SELECT $i <= $slave_last`) --echo # --echo # Test Case 2) If both replicas simulate an error before sending an ACK, ---echo # the primary should delay killing the suspended thread until the ---echo # timeout is reached (Rpl_semi_sync_master_no_tx should be 1). +--echo # the primary should delay killing the Ack_thread until the +--echo # timeout is reached. --echo # --let server_2_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141" --let server_3_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141" @@ -137,8 +135,8 @@ while (`SELECT $i <= $slave_last`) --echo # --echo # Test Case 3) If one replica simulates a delay within the allowed --echo # timeout and the other simulates an error before sending an ACK, the ---echo # primary should delay killing the suspended thread until it receives an ---echo # ACK from the delayed slave (Rpl_semi_sync_master_yes_tx should be 1). +--echo # primary should delay killing the Ack_thread until it receives an +--echo # ACK from the delayed slave. --echo # --let server_2_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141" --let server_3_dbug= "+d,simulate_delay_semisync_slave_reply" @@ -156,8 +154,7 @@ while (`SELECT $i <= $slave_last`) --echo # active semi-sync connection in-tact. The slave should notice this, and --echo # not issue a `QUIT` command to the primary, which would otherwise be --echo # sent to kill an active connection. This test case validates that the ---echo # slave does not send a `QUIT` in this case (Rpl_semi_sync_master_yes_tx ---echo # should be 1 because server_3 will send the ACK within a valid timeout). +--echo # slave does not send a `QUIT` in this case. --echo # --let server_2_dbug= "+d,corrupt_queue_event,delay_semisync_kill_connection_for_mdev_28141" --let server_3_dbug= "+d,simulate_delay_semisync_slave_reply" @@ -166,18 +163,108 @@ while (`SELECT $i <= $slave_last`) --let server_3_expect_row_count= 1 --source rpl_semi_sync_shutdown_await_ack.inc +# +# Added with MDEV-33551 +# +--echo # +--echo # Test Case 5) If a waiting-for-ACK user thread is killed (disconnected) +--echo # during SHUTDOWN WAIT FOR ALL SLAVES, ensure the primary will still +--echo # await the ACK from the replica before killing the Ack_receiver thread +--echo # +--connection server_1 +insert into t1 values (1); +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +--source include/stop_slave.inc +SET GLOBAL rpl_semi_sync_slave_enabled= 1; +--source include/start_slave.inc + +--connection server_1 +SET GLOBAL rpl_semi_sync_master_enabled= 1; +SET GLOBAL rpl_semi_sync_master_timeout= 2000; + +--let $status_var= Rpl_semi_sync_master_clients +--let $status_var_value= 1 +source include/wait_for_status_var.inc; + +show status like 'Rpl_semi_sync_master_status'; +show status like 'Rpl_semi_sync_master_clients'; + +--connection server_2 +SET @old_dbug= @@GLOBAL.debug_dbug; +SET GLOBAL debug_dbug="+d,simulate_delay_semisync_slave_reply"; + +--connect(con1, localhost, root,,) +--connect(con2, localhost, root,,) + +--connection con1 +--send insert into t1 values (2) + +--connection server_1 +--echo # Wait for thd to begin semi-sync wait.. +--let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = 'Waiting for semi-sync ACK from slave' +--source include/wait_condition.inc +--source include/wait_condition.inc +--echo # ..done + +--disconnect con1 + +--connection default +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +wait +EOF + +--connection con2 +SHUTDOWN WAIT FOR ALL SLAVES; +--source include/wait_until_disconnected.inc + +# Run assert_grep on server_2 as it uses SQL commands for verification, but +# server_1 has gone away +--connection server_2 +--let $assert_text= Ensure the primary waited for the ACK of the killed thread +--let $assert_select= Delaying shutdown to await semi-sync ACK +--let $assert_file= $MYSQLTEST_VARDIR/log/mysqld.1.err +--let $assert_count= 5 +--let $assert_only_after=CURRENT_TEST +--source include/assert_grep.inc + +--connection default +--source include/wait_until_disconnected.inc + +--connection server_1 +--source include/wait_until_disconnected.inc + +--connection server_2 +--let $rpl_allow_error= 1 +source include/stop_slave.inc; +--connection server_3 +source include/stop_slave.inc; +--let $rpl_allow_error= + +--connection default +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect +restart +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc + +--connection server_1 +--enable_reconnect +--source include/wait_until_connected_again.inc + + --echo ############################# --echo # Cleanup --echo ############################# --connection server_2 -source include/stop_slave.inc; SET @@GLOBAL.rpl_semi_sync_slave_enabled = @sav_enabled_server_2; SET @@GLOBAL.debug_dbug= @sav_server_2_dbug; source include/start_slave.inc; --connection server_3 -source include/stop_slave.inc; SET @@GLOBAL.rpl_semi_sync_slave_enabled = @sav_enabled_server_3; SET @@GLOBAL.debug_dbug= @sav_server_3_dbug; source include/start_slave.inc; diff --git a/sql/log.cc b/sql/log.cc index c91f82211d3..281bb3eecde 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -6870,8 +6870,8 @@ err: mysql_mutex_assert_not_owner(&LOCK_after_binlog_sync); mysql_mutex_assert_not_owner(&LOCK_commit_ordered); #ifdef HAVE_REPLICATION - if (repl_semisync_master.report_binlog_update(thd, log_file_name, - file->pos_in_file)) + if (repl_semisync_master.report_binlog_update( + thd, thd, log_file_name, file->pos_in_file)) { sql_print_error("Failed to run 'after_flush' hooks"); error= 1; @@ -8465,9 +8465,19 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader) for (current= queue; current != NULL; current= current->next) { #ifdef HAVE_REPLICATION + /* + The thread which will await the ACK from the replica can change + depending on the wait-point. If AFTER_COMMIT, then the user thread + will perform the wait. If AFTER_SYNC, the binlog group commit leader + will perform the wait on behalf of the user thread. + */ + THD *waiter_thd= (repl_semisync_master.wait_point() == + SEMI_SYNC_MASTER_WAIT_POINT_AFTER_STORAGE_COMMIT) + ? current->thd + : leader->thd; if (likely(!current->error) && unlikely(repl_semisync_master. - report_binlog_update(current->thd, + report_binlog_update(current->thd, waiter_thd, current->cache_mngr-> last_commit_pos_file, current->cache_mngr-> diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fe44f657a13..c29bfc2ed50 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1538,15 +1538,12 @@ static void kill_thread(THD *thd) /** First shutdown everything but slave threads and binlog dump connections */ -static my_bool kill_thread_phase_1(THD *thd, int *n_threads_awaiting_ack) +static my_bool kill_thread_phase_1(THD *thd, void *) { DBUG_PRINT("quit", ("Informing thread %ld that it's time to die", (ulong) thd->thread_id)); - if (thd->slave_thread || thd->is_binlog_dump_thread() || - (shutdown_wait_for_slaves && - repl_semisync_master.is_thd_awaiting_semisync_ack(thd) && - ++(*n_threads_awaiting_ack))) + if (thd->slave_thread || thd->is_binlog_dump_thread()) return 0; if (DBUG_EVALUATE_IF("only_kill_system_threads", !thd->system_thread, 0)) @@ -1745,29 +1742,18 @@ static void close_connections(void) This will give the threads some time to gracefully abort their statements and inform their clients that the server is about to die. */ - int n_threads_awaiting_ack= 0; - server_threads.iterate(kill_thread_phase_1, &n_threads_awaiting_ack); + server_threads.iterate(kill_thread_phase_1); /* If we are waiting on any ACKs, delay killing the thread until either an ACK is received or the timeout is hit. - - Allow at max the number of sessions to await a timeout; however, if all - ACKs have been received in less iterations, then quit early */ if (shutdown_wait_for_slaves && repl_semisync_master.get_master_enabled()) { - int waiting_threads= repl_semisync_master.sync_get_master_wait_sessions(); - if (waiting_threads) - sql_print_information("Delaying shutdown to await semi-sync ACK"); - - while (waiting_threads-- > 0) - repl_semisync_master.await_slave_reply(); + repl_semisync_master.await_all_slave_replies( + "Delaying shutdown to await semi-sync ACK"); } - DBUG_EXECUTE_IF("delay_shutdown_phase_2_after_semisync_wait", - my_sleep(500000);); - Events::deinit(); slave_prepare_for_shutdown(); ack_receiver.stop(); @@ -1788,7 +1774,7 @@ static void close_connections(void) */ DBUG_PRINT("info", ("THD_count: %u", THD_count::value())); - for (int i= 0; THD_count::connection_thd_count() - n_threads_awaiting_ack + for (int i= 0; THD_count::connection_thd_count() && i < 1000 && DBUG_EVALUATE_IF("only_kill_system_threads_no_loop", 0, 1); i++) @@ -1806,10 +1792,9 @@ static void close_connections(void) #endif /* All threads has now been aborted */ DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)", - THD_count::value() - binlog_dump_thread_count - - n_threads_awaiting_ack)); + THD_count::value() - binlog_dump_thread_count)); - while (THD_count::connection_thd_count() - n_threads_awaiting_ack && + while (THD_count::connection_thd_count() && DBUG_EVALUATE_IF("only_kill_system_threads_no_loop", 0, 1)) { my_sleep(1000); diff --git a/sql/semisync_master.cc b/sql/semisync_master.cc index 8cc721e5737..aa1056c8c8f 100644 --- a/sql/semisync_master.cc +++ b/sql/semisync_master.cc @@ -68,6 +68,19 @@ static ulonglong timespec_to_usec(const struct timespec *ts) return (ulonglong) ts->tv_sec * TIME_MILLION + ts->tv_nsec / TIME_THOUSAND; } +int signal_waiting_transaction(THD *waiting_thd, const char *binlog_file, + my_off_t binlog_pos) +{ + /* + It is possible that the connection thd waiting for an ACK was killed. In + such circumstance, the connection thread will nullify the thd member of its + Active_tranx node. So before we try to signal, ensure the THD exists. + */ + if (waiting_thd) + mysql_cond_signal(&waiting_thd->COND_wakeup_ready); + return 0; +} + /******************************************************************************* * * class : manage all active transaction nodes @@ -75,12 +88,14 @@ static ulonglong timespec_to_usec(const struct timespec *ts) ******************************************************************************/ Active_tranx::Active_tranx(mysql_mutex_t *lock, + mysql_cond_t *cond, ulong trace_level) : Trace(trace_level), m_allocator(max_connections), m_num_entries(max_connections << 1), /* Transaction hash table size * is set to double the size * of max_connections */ - m_lock(lock) + m_lock(lock), + m_cond_empty(cond) { /* No transactions are in the list initially. */ m_trx_front = NULL; @@ -142,7 +157,8 @@ int Active_tranx::compare(const char *log_file_name1, my_off_t log_file_pos1, return 0; } -int Active_tranx::insert_tranx_node(const char *log_file_name, +int Active_tranx::insert_tranx_node(THD *thd_to_wait, + const char *log_file_name, my_off_t log_file_pos) { Tranx_node *ins_node; @@ -165,6 +181,7 @@ int Active_tranx::insert_tranx_node(const char *log_file_name, strncpy(ins_node->log_name, log_file_name, FN_REFLEN-1); ins_node->log_name[FN_REFLEN-1] = 0; /* make sure it ends properly */ ins_node->log_pos = log_file_pos; + ins_node->thd= thd_to_wait; if (!m_trx_front) { @@ -232,28 +249,22 @@ bool Active_tranx::is_tranx_end_pos(const char *log_file_name, DBUG_RETURN(entry != NULL); } -void Active_tranx::clear_active_tranx_nodes(const char *log_file_name, - my_off_t log_file_pos) +void Active_tranx::clear_active_tranx_nodes( + const char *log_file_name, my_off_t log_file_pos, + active_tranx_action pre_delete_hook) { Tranx_node *new_front; DBUG_ENTER("Active_tranx::::clear_active_tranx_nodes"); - if (log_file_name != NULL) + new_front= m_trx_front; + while (new_front) { - new_front = m_trx_front; - - while (new_front) - { - if (compare(new_front, log_file_name, log_file_pos) > 0) - break; - new_front = new_front->next; - } - } - else - { - /* If log_file_name is NULL, clear everything. */ - new_front = NULL; + if ((log_file_name != NULL) && + compare(new_front, log_file_name, log_file_pos) > 0) + break; + pre_delete_hook(new_front->thd, new_front->log_name, new_front->log_pos); + new_front = new_front->next; } if (new_front == NULL) @@ -315,9 +326,66 @@ void Active_tranx::clear_active_tranx_nodes(const char *log_file_name, m_trx_front->log_name, (ulong)m_trx_front->log_pos)); } + /* + m_cond_empty aliases Repl_semi_sync_master::COND_binlog, which holds the + condition variable to notify that we have cleared all nodes, e.g. used by + SHUTDOWN WAIT FOR ALL SLAVES. + */ + if (is_empty()) + mysql_cond_signal(m_cond_empty); + DBUG_VOID_RETURN; } +void Active_tranx::unlink_thd_as_waiter(const char *log_file_name, + my_off_t log_file_pos) +{ + DBUG_ENTER("Active_tranx::unlink_thd_as_waiter"); + mysql_mutex_assert_owner(m_lock); + + unsigned int hash_val = get_hash_value(log_file_name, log_file_pos); + Tranx_node *entry = m_trx_htb[hash_val]; + + while (entry != NULL) + { + if (compare(entry, log_file_name, log_file_pos) == 0) + break; + + entry = entry->hash_next; + } + + if (entry) + entry->thd= NULL; + + DBUG_VOID_RETURN; +} + +#ifndef DBUG_OFF +void Active_tranx::assert_thd_is_waiter(THD *thd_to_check, + const char *log_file_name, + my_off_t log_file_pos) +{ + DBUG_ENTER("Active_tranx::assert_thd_is_waiter"); + mysql_mutex_assert_owner(m_lock); + + unsigned int hash_val = get_hash_value(log_file_name, log_file_pos); + Tranx_node *entry = m_trx_htb[hash_val]; + + while (entry != NULL) + { + if (compare(entry, log_file_name, log_file_pos) == 0) + break; + + entry = entry->hash_next; + } + + DBUG_ASSERT(entry); + DBUG_ASSERT(entry->thd); + DBUG_ASSERT(entry->thd->thread_id == thd_to_check->thread_id); + + DBUG_VOID_RETURN; +} +#endif /******************************************************************************* * @@ -397,7 +465,8 @@ int Repl_semi_sync_master::enable_master() if (!get_master_enabled()) { - m_active_tranxs = new Active_tranx(&LOCK_binlog, m_trace_level); + m_active_tranxs= + new Active_tranx(&LOCK_binlog, &COND_binlog_send, m_trace_level); if (m_active_tranxs != NULL) { m_commit_file_name_inited = false; @@ -459,15 +528,6 @@ void Repl_semi_sync_master::cleanup() delete m_active_tranxs; } -int Repl_semi_sync_master::sync_get_master_wait_sessions() -{ - int wait_sessions; - lock(); - wait_sessions= rpl_semi_sync_master_wait_sessions; - unlock(); - return wait_sessions; -} - void Repl_semi_sync_master::create_timeout(struct timespec *out, struct timespec *start_arg) { @@ -500,23 +560,6 @@ void Repl_semi_sync_master::unlock() mysql_mutex_unlock(&LOCK_binlog); } -void Repl_semi_sync_master::cond_broadcast() -{ - mysql_cond_broadcast(&COND_binlog_send); -} - -int Repl_semi_sync_master::cond_timewait(struct timespec *wait_time) -{ - int wait_res; - - DBUG_ENTER("Repl_semi_sync_master::cond_timewait()"); - - wait_res= mysql_cond_timedwait(&COND_binlog_send, - &LOCK_binlog, wait_time); - - DBUG_RETURN(wait_res); -} - void Repl_semi_sync_master::add_slave() { lock(); @@ -533,7 +576,8 @@ void Repl_semi_sync_master::remove_slave() Signal transactions waiting in commit_trx() that they do not have to wait anymore. */ - cond_broadcast(); + m_active_tranxs->clear_active_tranx_nodes(NULL, 0, + signal_waiting_transaction); } unlock(); } @@ -616,7 +660,6 @@ int Repl_semi_sync_master::report_reply_binlog(uint32 server_id, my_off_t log_file_pos) { int cmp; - bool can_release_threads = false; bool need_copy_send_pos = true; DBUG_ENTER("Repl_semi_sync_master::report_reply_binlog"); @@ -668,45 +711,26 @@ int Repl_semi_sync_master::report_reply_binlog(uint32 server_id, /* Remove all active transaction nodes before this point. */ DBUG_ASSERT(m_active_tranxs != NULL); - m_active_tranxs->clear_active_tranx_nodes(log_file_name, log_file_pos); + m_active_tranxs->clear_active_tranx_nodes(log_file_name, log_file_pos, + signal_waiting_transaction); + if (m_active_tranxs->is_empty()) + m_wait_file_name_inited= false; DBUG_PRINT("semisync", ("%s: Got reply at (%s, %lu)", "Repl_semi_sync_master::report_reply_binlog", log_file_name, (ulong)log_file_pos)); } - if (rpl_semi_sync_master_wait_sessions > 0) - { - /* Let us check if some of the waiting threads doing a trx - * commit can now proceed. - */ - cmp = Active_tranx::compare(m_reply_file_name, m_reply_file_pos, - m_wait_file_name, m_wait_file_pos); - if (cmp >= 0) - { - /* Yes, at least one waiting thread can now proceed: - * let us release all waiting threads with a broadcast - */ - can_release_threads = true; - m_wait_file_name_inited = false; - } - } l_end: unlock(); - if (can_release_threads) - { - DBUG_PRINT("semisync", ("%s: signal all waiting threads.", - "Repl_semi_sync_master::report_reply_binlog")); - - cond_broadcast(); - } DBUG_RETURN(0); } -int Repl_semi_sync_master::wait_after_sync(const char *log_file, my_off_t log_pos) +int Repl_semi_sync_master::wait_after_sync(const char *log_file, + my_off_t log_pos) { if (!get_master_enabled()) return 0; @@ -762,24 +786,27 @@ int Repl_semi_sync_master::wait_after_rollback(THD *thd, bool all) /** The method runs after flush to binary log is done. */ -int Repl_semi_sync_master::report_binlog_update(THD* thd, const char *log_file, +int Repl_semi_sync_master::report_binlog_update(THD *trans_thd, + THD *waiter_thd, + const char *log_file, my_off_t log_pos) { if (get_master_enabled()) { Trans_binlog_info *log_info; - if (!(log_info= thd->semisync_info)) + if (!(log_info= trans_thd->semisync_info)) { if(!(log_info= (Trans_binlog_info*)my_malloc(PSI_INSTRUMENT_ME, sizeof(Trans_binlog_info), MYF(0)))) return 1; - thd->semisync_info= log_info; + trans_thd->semisync_info= log_info; } strcpy(log_info->log_file, log_file + dirname_length(log_file)); log_info->log_pos = log_pos; - return write_tranx_in_binlog(log_info->log_file, log_pos); + return write_tranx_in_binlog(waiter_thd, log_info->log_file, + log_pos); } return 0; @@ -825,7 +852,7 @@ void Repl_semi_sync_master::dump_end(THD* thd) ack_receiver.remove_slave(thd); } -int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, +int Repl_semi_sync_master::commit_trx(const char *trx_wait_binlog_name, my_off_t trx_wait_binlog_pos) { bool success= 0; @@ -852,9 +879,8 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, lock(); /* This must be called after acquired the lock */ - THD_ENTER_COND(thd, &COND_binlog_send, &LOCK_binlog, - & stage_waiting_for_semi_sync_ack_from_slave, - & old_stage); + THD_ENTER_COND(thd, &thd->COND_wakeup_ready, &LOCK_binlog, + &stage_waiting_for_semi_sync_ack_from_slave, &old_stage); /* This is the real check inside the mutex. */ if (!get_master_enabled() || !is_on()) @@ -865,7 +891,7 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, trx_wait_binlog_name, (ulong)trx_wait_binlog_pos, (int)is_on())); - while (is_on() && !thd_killed(thd)) + while (is_on() && !(aborted= thd_killed(thd))) { /* We have to check these again as things may have changed */ if (!rpl_semi_sync_master_clients && !rpl_semi_sync_master_wait_no_slave) @@ -902,7 +928,7 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, trx_wait_binlog_pos, m_wait_file_name, m_wait_file_pos); if (cmp <= 0) - { + { /* This thd has a lower position, let's update the minimum info. */ strmake_buf(m_wait_file_name, trx_wait_binlog_name); m_wait_file_pos = trx_wait_binlog_pos; @@ -934,20 +960,18 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, */ rpl_semi_sync_master_wait_sessions++; - /* We keep track of when this thread is awaiting an ack to ensure it is - * not killed while awaiting an ACK if a shutdown is issued. - */ - set_thd_awaiting_semisync_ack(thd, TRUE); - DBUG_PRINT("semisync", ("%s: wait %lu ms for binlog sent (%s, %lu)", "Repl_semi_sync_master::commit_trx", m_wait_timeout, m_wait_file_name, (ulong)m_wait_file_pos)); +#ifndef DBUG_OFF + m_active_tranxs->assert_thd_is_waiter(thd, trx_wait_binlog_name, + trx_wait_binlog_pos); +#endif create_timeout(&abstime, &start_ts); - wait_result = cond_timewait(&abstime); - - set_thd_awaiting_semisync_ack(thd, FALSE); + wait_result= mysql_cond_timedwait(&thd->COND_wakeup_ready, &LOCK_binlog, + &abstime); rpl_semi_sync_master_wait_sessions--; if (wait_result != 0) @@ -979,17 +1003,49 @@ int Repl_semi_sync_master::commit_trx(const char* trx_wait_binlog_name, { rpl_semi_sync_master_trx_wait_num++; rpl_semi_sync_master_trx_wait_time += wait_time; + + DBUG_EXECUTE_IF("testing_cond_var_per_thd", { + /* + DBUG log warning to ensure we have either recieved our ACK; or + have timed out and are awoken in an off state. Test + rpl.rpl_semi_sync_cond_var_per_thd scans the logs to ensure this + warning is not present. + */ + bool valid_wakeup= + (!get_master_enabled() || !is_on() || thd->is_killed() || + 0 <= Active_tranx::compare( + m_reply_file_name, m_reply_file_pos, + trx_wait_binlog_name, trx_wait_binlog_pos)); + if (!valid_wakeup) + { + sql_print_warning( + "Thread awaiting semi-sync ACK was awoken before its " + "ACK. THD (%llu), Wait coord: (%s, %llu), ACK coord: (%s, " + "%llu)", + thd->thread_id, trx_wait_binlog_name, trx_wait_binlog_pos, + m_reply_file_name, m_reply_file_pos); + } + }); } } } + /* + If our THD was killed (rather than awoken from an ACK) notify the + Active_tranx cache that we are no longer waiting for the ACK, so nobody + signals our COND var invalidly. + */ + if (aborted) + m_active_tranxs->unlink_thd_as_waiter(trx_wait_binlog_name, + trx_wait_binlog_pos); + /* At this point, the binlog file and position of this transaction must have been removed from Active_tranx. m_active_tranxs may be NULL if someone disabled semi sync during - cond_timewait() + mysql_cond_timedwait */ - DBUG_ASSERT(thd_killed(thd) || !m_active_tranxs || aborted || + DBUG_ASSERT(aborted || !m_active_tranxs || m_active_tranxs->is_empty() || !m_active_tranxs->is_tranx_end_pos(trx_wait_binlog_name, trx_wait_binlog_pos)); @@ -1030,20 +1086,21 @@ void Repl_semi_sync_master::switch_off() { DBUG_ENTER("Repl_semi_sync_master::switch_off"); + /* Clear the active transaction list. */ + if (m_active_tranxs) + m_active_tranxs->clear_active_tranx_nodes(NULL, 0, + signal_waiting_transaction); + if (m_state) { m_state = false; - /* Clear the active transaction list. */ - DBUG_ASSERT(m_active_tranxs != NULL); - m_active_tranxs->clear_active_tranx_nodes(NULL, 0); rpl_semi_sync_master_off_times++; m_wait_file_name_inited = false; m_reply_file_name_inited = false; sql_print_information("Semi-sync replication switched OFF."); } - cond_broadcast(); /* wake up all waiting threads */ DBUG_VOID_RETURN; } @@ -1190,7 +1247,8 @@ int Repl_semi_sync_master::update_sync_header(THD* thd, unsigned char *packet, DBUG_RETURN(0); } -int Repl_semi_sync_master::write_tranx_in_binlog(const char* log_file_name, +int Repl_semi_sync_master::write_tranx_in_binlog(THD *thd, + const char *log_file_name, my_off_t log_file_pos) { int result = 0; @@ -1233,7 +1291,7 @@ int Repl_semi_sync_master::write_tranx_in_binlog(const char* log_file_name, if (is_on()) { DBUG_ASSERT(m_active_tranxs != NULL); - if(m_active_tranxs->insert_tranx_node(log_file_name, log_file_pos)) + if(m_active_tranxs->insert_tranx_node(thd, log_file_name, log_file_pos)) { /* if insert tranx_node failed, print a warning message @@ -1362,21 +1420,34 @@ void Repl_semi_sync_master::set_export_stats() unlock(); } -void Repl_semi_sync_master::await_slave_reply() +void Repl_semi_sync_master::await_all_slave_replies(const char *msg) { - struct timespec abstime; + struct timespec timeout; + int wait_result= 0; + bool first= true; + DBUG_ENTER("Repl_semi_sync_master::::await_all_slave_replies"); - DBUG_ENTER("Repl_semi_sync_master::::await_slave_reply"); + /* + Wait for all transactions that need ACKS to have received them; or timeout. + If it is a timeout, the connection thread should attempt to turn off + semi-sync and broadcast to all other waiting threads to move on. + + COND_binlog_send is only signalled after the Active_tranx cache has been + emptied. + */ + create_timeout(&timeout, NULL); lock(); + while (get_master_enabled() && is_on() && !m_active_tranxs->is_empty() && !wait_result) + { + if (msg && first) + { + first= false; + sql_print_information(msg); + } - /* Just return if there is nothing to wait for */ - if (!rpl_semi_sync_master_wait_sessions) - goto end; - - create_timeout(&abstime, NULL); - cond_timewait(&abstime); - -end: + wait_result= + mysql_cond_timedwait(&COND_binlog_send, &LOCK_binlog, &timeout); + } unlock(); DBUG_VOID_RETURN; } diff --git a/sql/semisync_master.h b/sql/semisync_master.h index 99f46869354..3978d21a61d 100644 --- a/sql/semisync_master.h +++ b/sql/semisync_master.h @@ -31,6 +31,7 @@ extern PSI_cond_key key_COND_binlog_send; struct Tranx_node { char log_name[FN_REFLEN]; my_off_t log_pos; + THD *thd; /* The thread awaiting an ACK */ struct Tranx_node *next; /* the next node in the sorted list */ struct Tranx_node *hash_next; /* the next node during hash collision */ }; @@ -288,6 +289,18 @@ private: } }; +/** + Function pointer type to run on the contents of an Active_tranx node. + + Return 0 for success, 1 for error. + + Note Repl_semi_sync_master::LOCK_binlog is not guaranteed to be held for + its invocation. See the context in which it is called to know. +*/ + +typedef int (*active_tranx_action)(THD *trx_thd, const char *log_file_name, + my_off_t trx_log_file_pos); + /** This class manages memory for active transaction list. @@ -308,6 +321,7 @@ private: int m_num_entries; /* maximum hash table entries */ mysql_mutex_t *m_lock; /* mutex lock */ + mysql_cond_t *m_cond_empty; /* signalled when cleared all Tranx_node */ inline void assert_lock_owner(); @@ -330,7 +344,8 @@ private: } public: - Active_tranx(mysql_mutex_t *lock, unsigned long trace_level); + Active_tranx(mysql_mutex_t *lock, mysql_cond_t *cond, + unsigned long trace_level); ~Active_tranx(); /* Insert an active transaction node with the specified position. @@ -338,15 +353,38 @@ public: * Return: * 0: success; non-zero: error */ - int insert_tranx_node(const char *log_file_name, my_off_t log_file_pos); + int insert_tranx_node(THD *thd_to_wait, const char *log_file_name, + my_off_t log_file_pos); /* Clear the active transaction nodes until(inclusive) the specified * position. * If log_file_name is NULL, everything will be cleared: the sorted * list and the hash table will be reset to empty. + * + * The pre_delete_hook parameter is a function pointer that will be invoked + * for each Active_tranx node, in order, from m_trx_front to m_trx_rear, + * e.g. to signal their wakeup condition. Repl_semi_sync_binlog::LOCK_binlog + * is held while this is invoked. */ void clear_active_tranx_nodes(const char *log_file_name, - my_off_t log_file_pos); + my_off_t log_file_pos, + active_tranx_action pre_delete_hook); + + /* Unlinks a thread from a Tranx_node, so it will not be referenced/signalled + * if it is separately killed. Note that this keeps the Tranx_node itself in + * the cache so it can still be awaited by await_all_slave_replies(), e.g. + * as is done by SHUTDOWN WAIT FOR ALL SLAVES. + */ + void unlink_thd_as_waiter(const char *log_file_name, my_off_t log_file_pos); + +#ifndef DBUG_OFF + /* Uses DBUG_ASSERT statements to ensure that the argument thd_to_check + * matches the thread of the respective Tranx_node::thd of the passed in + * log_file_name and log_file_pos. + */ + void assert_thd_is_waiter(THD *thd_to_check, const char *log_file_name, + my_off_t log_file_pos); +#endif /* Given a position, check to see whether the position is an active * transaction's ending position by probing the hash table. @@ -359,6 +397,12 @@ public: static int compare(const char *log_file_name1, my_off_t log_file_pos1, const char *log_file_name2, my_off_t log_file_pos2); + + /* Check if there are no transactions actively awaiting ACKs. Returns true + * if the internal linked list has no entries, false otherwise. + */ + bool is_empty() { return m_trx_front == NULL; } + }; /** @@ -433,8 +477,6 @@ class Repl_semi_sync_master void lock(); void unlock(); - void cond_broadcast(); - int cond_timewait(struct timespec *wait_time); /* Is semi-sync replication on? */ bool is_on() { @@ -472,8 +514,6 @@ class Repl_semi_sync_master m_wait_timeout = wait_timeout; } - int sync_get_master_wait_sessions(); - /* Calculates a timeout that is m_wait_timeout after start_arg and saves it in out. If start_arg is NULL, the timeout is m_wait_timeout after the @@ -482,10 +522,15 @@ class Repl_semi_sync_master void create_timeout(struct timespec *out, struct timespec *start_arg); /* - Blocks the calling thread until the ack_receiver either receives an ACK - or times out (from rpl_semi_sync_master_timeout) + Blocks the calling thread until the ack_receiver either receives ACKs for + all transactions awaiting ACKs, or times out (from + rpl_semi_sync_master_timeout). + + If info_msg is provided, it will be output via sql_print_information when + there are transactions awaiting ACKs; info_msg is not output if there are + no transasctions to await. */ - void await_slave_reply(); + void await_all_slave_replies(const char *msg); /*set the ACK point, after binlog sync or after transaction commit*/ void set_wait_point(unsigned long ack_point) @@ -561,9 +606,23 @@ class Repl_semi_sync_master /*Wait after the transaction is rollback*/ int wait_after_rollback(THD *thd, bool all); - /*Store the current binlog position in m_active_tranxs. This position should - * be acked by slave*/ - int report_binlog_update(THD *thd, const char *log_file,my_off_t log_pos); + /* Store the current binlog position in m_active_tranxs. This position should + * be acked by slave. + * + * Inputs: + * trans_thd Thread of the transaction which is executing the + * transaction. + * waiter_thd Thread that will wait for the ACK from the replica, + * which depends on the semi-sync wait point. If AFTER_SYNC, + * and also using binlog group commit, this will be the leader + * thread of the binlog commit. Otherwise, it is the thread that + * is executing the transaction, i.e. the same as trans_thd. + * log_file Name of the binlog file that the transaction is written into + * log_pos Offset within the binlog file that the transaction is written + * at + */ + int report_binlog_update(THD *trans_thd, THD *waiter_thd, + const char *log_file, my_off_t log_pos); int dump_start(THD* thd, const char *log_file, @@ -609,13 +668,19 @@ class Repl_semi_sync_master * semi-sync is on * * Input: (the transaction events' ending binlog position) + * THD - (IN) thread that will wait for an ACK. This can be the + * binlog leader thread when using wait_point + * AFTER_SYNC with binlog group commit. In all other + * cases, this is the user thread executing the + * transaction. * log_file_name - (IN) transaction ending position's file name * log_file_pos - (IN) transaction ending position's file offset * * Return: * 0: success; non-zero: error */ - int write_tranx_in_binlog(const char* log_file_name, my_off_t log_file_pos); + int write_tranx_in_binlog(THD *thd, const char *log_file_name, + my_off_t log_file_pos); /* Read the slave's reply so that we know how much progress the slave makes * on receive replication events. @@ -633,30 +698,6 @@ class Repl_semi_sync_master /*called before reset master*/ int before_reset_master(); - /* - Determines if the given thread is currently awaiting a semisync_ack. Note - that the thread's value is protected by this class's LOCK_binlog, so this - function (indirectly) provides safe access. - */ - my_bool is_thd_awaiting_semisync_ack(THD *thd) - { - lock(); - my_bool ret= thd->is_awaiting_semisync_ack; - unlock(); - return ret; - } - - /* - Update the thread's value for is_awaiting_semisync_ack. LOCK_binlog (from - this class) should be acquired before calling this function. - */ - void set_thd_awaiting_semisync_ack(THD *thd, - my_bool _is_awaiting_semisync_ack) - { - mysql_mutex_assert_owner(&LOCK_binlog); - thd->is_awaiting_semisync_ack= _is_awaiting_semisync_ack; - } - mysql_mutex_t LOCK_rpl_semi_sync_master_enabled; }; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 85fd68bf9a9..35ab93cc8ba 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -681,8 +681,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) #ifdef HAVE_REPLICATION , current_linfo(0), - slave_info(0), - is_awaiting_semisync_ack(0) + slave_info(0) #endif #ifdef WITH_WSREP , diff --git a/sql/sql_class.h b/sql/sql_class.h index 93ee1c8bcb9..0aa2aef72c2 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5320,8 +5320,18 @@ public: Flag, mutex and condition for a thread to wait for a signal from another thread. - Currently used to wait for group commit to complete, can also be used for - other purposes. + Currently used to wait for group commit to complete, and COND_wakeup_ready + is used for threads to wait on semi-sync ACKs (though is protected by + Repl_semi_sync_master::LOCK_binlog). Note the following relationships + between these two use-cases when using + rpl_semi_sync_master_wait_point=AFTER_SYNC during group commit: + 1) Non-leader threads use COND_wakeup_ready to wait for the leader thread + to complete binlog commit. + 2) The leader thread uses COND_wakeup_ready to await ACKs from the + replica before signalling the non-leader threads to wake up. + + With wait_point=AFTER_COMMIT, there is no overlap as binlogging has + finished, so COND_wakeup_ready is safe to re-use. */ bool wakeup_ready; mysql_mutex_t LOCK_wakeup_ready; @@ -5449,14 +5459,6 @@ public: bool is_binlog_dump_thread(); #endif - /* - Indicates if this thread is suspended due to awaiting an ACK from a - replica. True if suspended, false otherwise. - - Note that this variable is protected by Repl_semi_sync_master::LOCK_binlog - */ - bool is_awaiting_semisync_ack; - inline ulong wsrep_binlog_format(ulong binlog_format) const { #ifdef WITH_WSREP From fa8a46eb68299776589e769844372813ebb16a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 22 Mar 2024 14:17:39 +0200 Subject: [PATCH 092/106] MDEV-33613 InnoDB may still hang when temporarily running out of buffer pool By design, InnoDB has always hung when permanently running out of buffer pool, for example when several threads are waiting to allocate a block, and all of the buffer pool is buffer-fixed by the active threads. The hang that we are fixing here occurs when the buffer pool is only temporarily running out and the situation could be rescued by writing out some dirty pages or evicting some clean pages. buf_LRU_get_free_block(): Simplify the way how we wait for the buf_flush_page_cleaner thread. This fixes occasional hangs of the test encryption.innochecksum that were introduced by commit a55b951e6082a4ce9a1f2ed5ee176ea7dbbaf1f2 (MDEV-26827). To play it safe, we use a timed wait when waiting for the buf_flush_page_cleaner() thread to perform its job. Should that thread get stuck, we will invoke buf_pool.LRU_warn() in order to display a message that pages could not be freed, and keep trying to wake up the buf_flush_page_cleaner() thread. The INFORMATION_SCHEMA.INNODB_METRICS counters buffer_LRU_single_flush_failure_count and buffer_LRU_get_free_waits will be removed. The latter is represented by buffer_pool_wait_free. Also removed will be the message "InnoDB: Difficult to find free blocks in the buffer pool" because in d34479dc664d4cbd4e9dad6b0f92d7c8e55595d1 we introduced a more precise message "InnoDB: Could not free any blocks in the buffer pool" in the buf_flush_page_cleaner thread. buf_pool_t::LRU_warn(): Issue the warning message that we could not free any blocks in the buffer pool. This may also be invoked by buf_LRU_get_free_block() if buf_flush_page_cleaner() appears to be stuck. buf_pool_t::n_flush_dec(): Remove. buf_pool_t::n_flush_dec_holding_mutex(): Rename to n_flush_dec(). buf_flush_LRU_list_batch(): Increment the eviction counter for blocks of temporary, discarded or dropped tablespaces. buf_flush_LRU(): Make static, and remove the constant parameter evict=false. The only caller will be the buf_flush_page_cleaner() thread. IORequest::is_LRU(): Remove. The only case of evicting pages on write completion will be when we are writing out pages of the temporary tablespace. Those pages are not in buf_pool.flush_list, only in buf_pool.LRU. buf_page_t::flush(): Remove the parameter evict. buf_page_t::write_complete(): Change the parameter "bool temporary" to "bool persistent" and add a parameter for an already read state(). Reviewed by: Debarun Banerjee --- mysql-test/suite/innodb/r/alter_copy.result | 2 +- .../r/innodb-lru-force-no-free-page.result | 9 - .../r/innodb_skip_innodb_is_tables.result | 2 - mysql-test/suite/innodb/r/monitor.result | 2 - mysql-test/suite/innodb/t/alter_copy.test | 2 +- .../t/innodb-lru-force-no-free-page.test | 22 --- .../suite/innodb/t/purge_secondary.test | 4 - .../suite/innodb_zip/t/innochecksum_2.test | 5 - storage/innobase/buf/buf0buf.cc | 23 +-- storage/innobase/buf/buf0flu.cc | 180 +++++++----------- storage/innobase/buf/buf0lru.cc | 180 ++++++------------ storage/innobase/include/buf0buf.h | 20 +- storage/innobase/include/buf0flu.h | 10 - storage/innobase/include/os0file.h | 9 +- storage/innobase/include/srv0mon.h | 2 - storage/innobase/srv/srv0mon.cc | 10 - .../r/innodb_i_s_tables_disabled.result | 2 - 17 files changed, 147 insertions(+), 337 deletions(-) delete mode 100644 mysql-test/suite/innodb/r/innodb-lru-force-no-free-page.result delete mode 100644 mysql-test/suite/innodb/t/innodb-lru-force-no-free-page.test diff --git a/mysql-test/suite/innodb/r/alter_copy.result b/mysql-test/suite/innodb/r/alter_copy.result index 8c9e5966b2e..72ae28e9652 100644 --- a/mysql-test/suite/innodb/r/alter_copy.result +++ b/mysql-test/suite/innodb/r/alter_copy.result @@ -51,7 +51,7 @@ ADD INDEX(a,b,d), ADD INDEX(a,d,b), ADD INDEX(b,c,d), ADD INDEX(b,d,c), ALGORITHM=COPY; connection default; SET DEBUG_SYNC='now WAIT_FOR hung'; -# restart: --innodb-force-recovery=3 --debug_dbug=+d,recv_ran_out_of_buffer +# restart: --innodb-force-recovery=3 disconnect hang; FTS_INDEX_1.ibd FTS_INDEX_2.ibd diff --git a/mysql-test/suite/innodb/r/innodb-lru-force-no-free-page.result b/mysql-test/suite/innodb/r/innodb-lru-force-no-free-page.result deleted file mode 100644 index ac3010a101a..00000000000 --- a/mysql-test/suite/innodb/r/innodb-lru-force-no-free-page.result +++ /dev/null @@ -1,9 +0,0 @@ -SET @saved_debug = @@SESSION.debug_dbug; -SET SESSION debug_dbug="+d,ib_lru_force_no_free_page"; -CREATE TABLE t1 (j LONGBLOB) ENGINE = InnoDB; -BEGIN; -INSERT INTO t1 VALUES (repeat('abcdefghijklmnopqrstuvwxyz',200)); -COMMIT; -SET debug_dbug = @saved_debug; -DROP TABLE t1; -FOUND 1 /InnoDB: Difficult to find free blocks / in mysqld.1.err diff --git a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result index 6c10b4bad5f..a8b30bee31d 100644 --- a/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result +++ b/mysql-test/suite/innodb/r/innodb_skip_innodb_is_tables.result @@ -88,7 +88,6 @@ buffer_flush_n_to_flush_by_age buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NUL buffer_flush_adaptive_avg_time buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Avg time (ms) spent for adaptive flushing recently. buffer_flush_adaptive_avg_pass buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of adaptive flushes passed during the recent Avg period. buffer_LRU_get_free_loops buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Total loops in LRU get free. -buffer_LRU_get_free_waits buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Total sleep waits in LRU get free. buffer_flush_avg_page_rate buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Average number of pages at which flushing is happening buffer_flush_lsn_avg_rate buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Average redo generation rate buffer_flush_pct_for_dirty buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Percent of IO capacity used to avoid max dirty page limit @@ -108,7 +107,6 @@ buffer_LRU_batch_num_scan buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NUL buffer_LRU_batch_scanned_per_call buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 set_member Pages scanned per LRU batch call buffer_LRU_batch_flush_total_pages buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Total pages flushed as part of LRU batches buffer_LRU_batch_evict_total_pages buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Total pages evicted as part of LRU batches -buffer_LRU_single_flush_failure_count Buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times attempt to flush a single page from LRU failed buffer_LRU_get_free_search Buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of searches performed for a clean page buffer_LRU_search_scanned buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 set_owner Total pages scanned as part of LRU search buffer_LRU_search_num_scan buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 set_member Number of times LRU search is performed diff --git a/mysql-test/suite/innodb/r/monitor.result b/mysql-test/suite/innodb/r/monitor.result index c45462f418c..3d500609524 100644 --- a/mysql-test/suite/innodb/r/monitor.result +++ b/mysql-test/suite/innodb/r/monitor.result @@ -53,7 +53,6 @@ buffer_flush_n_to_flush_by_age disabled buffer_flush_adaptive_avg_time disabled buffer_flush_adaptive_avg_pass disabled buffer_LRU_get_free_loops disabled -buffer_LRU_get_free_waits disabled buffer_flush_avg_page_rate disabled buffer_flush_lsn_avg_rate disabled buffer_flush_pct_for_dirty disabled @@ -73,7 +72,6 @@ buffer_LRU_batch_num_scan disabled buffer_LRU_batch_scanned_per_call disabled buffer_LRU_batch_flush_total_pages enabled buffer_LRU_batch_evict_total_pages enabled -buffer_LRU_single_flush_failure_count disabled buffer_LRU_get_free_search disabled buffer_LRU_search_scanned disabled buffer_LRU_search_num_scan disabled diff --git a/mysql-test/suite/innodb/t/alter_copy.test b/mysql-test/suite/innodb/t/alter_copy.test index b62f812f4b7..90f2171d10b 100644 --- a/mysql-test/suite/innodb/t/alter_copy.test +++ b/mysql-test/suite/innodb/t/alter_copy.test @@ -57,7 +57,7 @@ ALTER TABLE t ADD INDEX(b,c,d,a),ADD INDEX(b,c,a,d),ADD INDEX(b,a,c,d),ADD INDEX connection default; SET DEBUG_SYNC='now WAIT_FOR hung'; let $shutdown_timeout=0; ---let $restart_parameters= --innodb-force-recovery=3 --debug_dbug="+d,recv_ran_out_of_buffer" +--let $restart_parameters= --innodb-force-recovery=3 --source include/restart_mysqld.inc disconnect hang; let $shutdown_timeout=; diff --git a/mysql-test/suite/innodb/t/innodb-lru-force-no-free-page.test b/mysql-test/suite/innodb/t/innodb-lru-force-no-free-page.test deleted file mode 100644 index bbf0e1757c3..00000000000 --- a/mysql-test/suite/innodb/t/innodb-lru-force-no-free-page.test +++ /dev/null @@ -1,22 +0,0 @@ ---source include/have_innodb.inc ---source include/have_debug.inc ---source include/not_embedded.inc - -SET @saved_debug = @@SESSION.debug_dbug; -SET SESSION debug_dbug="+d,ib_lru_force_no_free_page"; - -CREATE TABLE t1 (j LONGBLOB) ENGINE = InnoDB; -BEGIN; -INSERT INTO t1 VALUES (repeat('abcdefghijklmnopqrstuvwxyz',200)); -COMMIT; - -SET debug_dbug = @saved_debug; - -DROP TABLE t1; - -# -# There should be only one message -# -let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; ---let SEARCH_PATTERN=InnoDB: Difficult to find free blocks ---source include/search_pattern_in_file.inc diff --git a/mysql-test/suite/innodb/t/purge_secondary.test b/mysql-test/suite/innodb/t/purge_secondary.test index 8a38a418877..ec02c726891 100644 --- a/mysql-test/suite/innodb/t/purge_secondary.test +++ b/mysql-test/suite/innodb/t/purge_secondary.test @@ -4,10 +4,6 @@ SET @save_stats_persistent = @@GLOBAL.innodb_stats_persistent; SET GLOBAL innodb_stats_persistent = 0; ---disable_query_log -call mtr.add_suppression("InnoDB: Difficult to find free blocks in the buffer pool"); ---enable_query_log - CREATE TABLE t1 ( a SERIAL, b CHAR(255) NOT NULL DEFAULT '', c BOOLEAN DEFAULT false, l LINESTRING NOT NULL DEFAULT ST_linefromtext('linestring(448 -689, diff --git a/mysql-test/suite/innodb_zip/t/innochecksum_2.test b/mysql-test/suite/innodb_zip/t/innochecksum_2.test index 62e792c1ce4..57926d921f4 100644 --- a/mysql-test/suite/innodb_zip/t/innochecksum_2.test +++ b/mysql-test/suite/innodb_zip/t/innochecksum_2.test @@ -9,11 +9,6 @@ --source include/not_embedded.inc -- source include/big_test.inc ---disable_query_log -# This warning occurs due to small buffer pool size(i.e. 8MB). It doesn't occur -# with --mysqld=--innodb_buffer_pool_size=10MB -call mtr.add_suppression("\\[Warning\\] InnoDB: Difficult to find free blocks in the buffer pool.*"); ---enable_query_log let MYSQLD_BASEDIR= `SELECT @@basedir`; let MYSQLD_DATADIR= `SELECT @@datadir`; let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err; diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 6abbda1f45c..90f47f1fbf0 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -1397,17 +1397,14 @@ inline bool buf_pool_t::withdraw_blocks() /* reserve free_list length */ if (UT_LIST_GET_LEN(withdraw) < withdraw_target) { - buf_flush_LRU( - std::max(withdraw_target - - UT_LIST_GET_LEN(withdraw), - srv_LRU_scan_depth), - true); - mysql_mutex_unlock(&buf_pool.mutex); - buf_dblwr.flush_buffered_writes(); - mysql_mutex_lock(&buf_pool.flush_list_mutex); - buf_flush_wait_LRU_batch_end(); - mysql_mutex_unlock(&buf_pool.flush_list_mutex); - mysql_mutex_lock(&buf_pool.mutex); + try_LRU_scan = false; + mysql_mutex_unlock(&mutex); + mysql_mutex_lock(&flush_list_mutex); + page_cleaner_wakeup(true); + my_cond_wait(&done_flush_list, + &flush_list_mutex.m_mutex); + mysql_mutex_unlock(&flush_list_mutex); + mysql_mutex_lock(&mutex); } /* relocate blocks/buddies in withdrawn area */ @@ -2003,7 +2000,10 @@ buf_page_t *buf_pool_t::watch_set(const page_id_t id, got_block: bpage->fix(); if (watch_is_sentinel(*bpage)) + { + ut_ad(!bpage->oldest_modification()); bpage= nullptr; + } page_hash.lock_get(chain).unlock(); return bpage; } @@ -2075,6 +2075,7 @@ void buf_pool_t::watch_unset(const page_id_t id, buf_pool_t::hash_chain &chain) } else { + ut_ad(!w->oldest_modification()); const auto state= w->state(); ut_ad(~buf_page_t::LRU_MASK & state); ut_ad(state >= buf_page_t::UNFIXED + 1); diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 696a09f60d4..d7e4e19c672 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -311,30 +311,22 @@ buf_flush_relocate_on_flush_list( ut_d(buf_flush_validate_low()); } -/** Note that a block is no longer dirty, while not removing -it from buf_pool.flush_list -@param temporary whether the page belongs to the temporary tablespace -@param error whether an error may have occurred while writing */ -inline void buf_page_t::write_complete(bool temporary, bool error) +void buf_page_t::write_complete(bool persistent, bool error, uint32_t state) { - ut_ad(temporary == fsp_is_system_temporary(id().space())); - if (UNIV_UNLIKELY(error)); - else if (temporary) - { - ut_ad(oldest_modification() == 2); - oldest_modification_= 0; - } - else + ut_ad(!persistent == fsp_is_system_temporary(id().space())); + ut_ad(state >= WRITE_FIX); + + if (UNIV_LIKELY(!error)) { + ut_d(lsn_t om= oldest_modification()); + ut_ad(om >= 2); + ut_ad(persistent == (om > 2)); /* We use release memory order to guarantee that callers of oldest_modification_acquire() will observe the block as being detached from buf_pool.flush_list, after reading the value 0. */ - ut_ad(oldest_modification() > 2); - oldest_modification_.store(1, std::memory_order_release); + oldest_modification_.store(persistent, std::memory_order_release); } - const auto s= state(); - ut_ad(s >= WRITE_FIX); - zip.fix.fetch_sub((s >= WRITE_FIX_REINIT) + zip.fix.fetch_sub((state >= WRITE_FIX_REINIT) ? (WRITE_FIX_REINIT - UNFIXED) : (WRITE_FIX - UNFIXED)); lock.u_unlock(true); @@ -348,18 +340,10 @@ inline void buf_pool_t::n_flush_inc() inline void buf_pool_t::n_flush_dec() { - mysql_mutex_lock(&flush_list_mutex); + mysql_mutex_assert_owner(&flush_list_mutex); ut_ad(page_cleaner_status >= LRU_FLUSH); if ((page_cleaner_status-= LRU_FLUSH) < LRU_FLUSH) pthread_cond_broadcast(&done_flush_LRU); - mysql_mutex_unlock(&flush_list_mutex); -} - -inline void buf_pool_t::n_flush_dec_holding_mutex() -{ - mysql_mutex_assert_owner(&flush_list_mutex); - ut_ad(page_cleaner_status >= LRU_FLUSH); - page_cleaner_status-= LRU_FLUSH; } /** Complete write of a file page from buf_pool. @@ -389,28 +373,26 @@ void buf_page_write_complete(const IORequest &request, bool error) mysql_mutex_assert_not_owner(&buf_pool.mutex); mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex); - if (request.is_LRU()) + const bool persistent= bpage->oldest_modification() != 2; + + if (UNIV_UNLIKELY(!persistent) && UNIV_LIKELY(!error)) { - const bool temp= bpage->oldest_modification() == 2; - if (!temp && state < buf_page_t::WRITE_FIX_REINIT && - request.node->space->use_doublewrite()) - buf_dblwr.write_completed(); /* We must hold buf_pool.mutex while releasing the block, so that no other thread can access it before we have freed it. */ mysql_mutex_lock(&buf_pool.mutex); - bpage->write_complete(temp, error); - if (!error) - buf_LRU_free_page(bpage, true); + bpage->write_complete(persistent, error, state); + buf_LRU_free_page(bpage, true); mysql_mutex_unlock(&buf_pool.mutex); - - buf_pool.n_flush_dec(); } else { + bpage->write_complete(persistent, error, state); if (state < buf_page_t::WRITE_FIX_REINIT && request.node->space->use_doublewrite()) + { + ut_ad(persistent); buf_dblwr.write_completed(); - bpage->write_complete(false, error); + } } } @@ -778,17 +760,15 @@ ATTRIBUTE_COLD void buf_pool_t::release_freed_page(buf_page_t *bpage) } /** Write a flushable page to a file or free a freeable block. -@param evict whether to evict the page on write completion @param space tablespace @return whether a page write was initiated and buf_pool.mutex released */ -bool buf_page_t::flush(bool evict, fil_space_t *space) +bool buf_page_t::flush(fil_space_t *space) { mysql_mutex_assert_not_owner(&buf_pool.flush_list_mutex); ut_ad(in_file()); ut_ad(in_LRU_list); ut_ad((space->purpose == FIL_TYPE_TEMPORARY) == (space == fil_system.temp_space)); - ut_ad(evict || space != fil_system.temp_space); ut_ad(space->referenced()); const auto s= state(); @@ -835,22 +815,11 @@ bool buf_page_t::flush(bool evict, fil_space_t *space) mysql_mutex_unlock(&buf_pool.mutex); IORequest::Type type= IORequest::WRITE_ASYNC; - if (UNIV_UNLIKELY(evict)) - { - type= IORequest::WRITE_LRU; - mysql_mutex_lock(&buf_pool.flush_list_mutex); - buf_pool.n_flush_inc(); - mysql_mutex_unlock(&buf_pool.flush_list_mutex); - } /* Apart from the U-lock, this block will also be protected by is_write_fixed() and oldest_modification()>1. Thus, it cannot be relocated or removed. */ - DBUG_PRINT("ib_buf", ("%s %u page %u:%u", - evict ? "LRU" : "flush_list", - id().space(), id().page_no())); - buf_block_t *block= reinterpret_cast(this); page_t *write_frame= zip.data; @@ -902,10 +871,7 @@ bool buf_page_t::flush(bool evict, fil_space_t *space) { switch (space->chain.start->punch_hole) { case 1: - static_assert(IORequest::PUNCH_LRU - IORequest::PUNCH == - IORequest::WRITE_LRU - IORequest::WRITE_ASYNC, ""); - type= - IORequest::Type(type + (IORequest::PUNCH - IORequest::WRITE_ASYNC)); + type= IORequest::PUNCH; break; case 2: size= orig_size; @@ -932,10 +898,8 @@ bool buf_page_t::flush(bool evict, fil_space_t *space) /** Check whether a page can be flushed from the buf_pool. @param id page identifier @param fold id.fold() -@param evict true=buf_pool.LRU; false=buf_pool.flush_list @return whether the page can be flushed */ -static bool buf_flush_check_neighbor(const page_id_t id, ulint fold, - bool evict) +static bool buf_flush_check_neighbor(const page_id_t id, ulint fold) { mysql_mutex_assert_owner(&buf_pool.mutex); ut_ad(fold == id.fold()); @@ -944,26 +908,16 @@ static bool buf_flush_check_neighbor(const page_id_t id, ulint fold, const buf_page_t *bpage= buf_pool.page_hash.get(id, buf_pool.page_hash.cell_get(fold)); - if (!bpage || buf_pool.watch_is_sentinel(*bpage)) - return false; - - /* We avoid flushing 'non-old' blocks in an eviction flush, because the - flushed blocks are soon freed */ - if (evict && !bpage->is_old()) - return false; - - return bpage->oldest_modification() > 1 && !bpage->is_io_fixed(); + return bpage && bpage->oldest_modification() > 1 && !bpage->is_io_fixed(); } /** Check which neighbors of a page can be flushed from the buf_pool. @param space tablespace @param id page identifier of a dirty page @param contiguous whether to consider contiguous areas of pages -@param evict true=buf_pool.LRU; false=buf_pool.flush_list @return last page number that can be flushed */ static page_id_t buf_flush_check_neighbors(const fil_space_t &space, - page_id_t &id, bool contiguous, - bool evict) + page_id_t &id, bool contiguous) { ut_ad(id.page_no() < space.size + (space.physical_size() == 2048 ? 1 @@ -996,7 +950,7 @@ static page_id_t buf_flush_check_neighbors(const fil_space_t &space, for (page_id_t i= id - 1;; --i) { fold--; - if (!buf_flush_check_neighbor(i, fold, evict)) + if (!buf_flush_check_neighbor(i, fold)) { low= i + 1; break; @@ -1012,7 +966,7 @@ static page_id_t buf_flush_check_neighbors(const fil_space_t &space, while (++i < high) { ++fold; - if (!buf_flush_check_neighbor(i, fold, evict)) + if (!buf_flush_check_neighbor(i, fold)) break; } @@ -1089,14 +1043,13 @@ and also write zeroes or punch the hole for the freed ranges of pages. @param page_id page identifier @param bpage buffer page @param contiguous whether to consider contiguous areas of pages -@param evict true=buf_pool.LRU; false=buf_pool.flush_list @param n_flushed number of pages flushed so far in this batch @param n_to_flush maximum number of pages we are allowed to flush @return number of pages flushed */ static ulint buf_flush_try_neighbors(fil_space_t *space, const page_id_t page_id, buf_page_t *bpage, - bool contiguous, bool evict, + bool contiguous, ulint n_flushed, ulint n_to_flush) { ut_ad(space->id == page_id.space()); @@ -1110,7 +1063,7 @@ static ulint buf_flush_try_neighbors(fil_space_t *space, ut_ad(lsn >= bpage->oldest_modification()); if (UNIV_UNLIKELY(lsn < space->get_create_lsn())) { - ut_a(!bpage->flush(evict, space)); + ut_a(!bpage->flush(space)); mysql_mutex_unlock(&buf_pool.mutex); return 0; } @@ -1120,7 +1073,7 @@ static ulint buf_flush_try_neighbors(fil_space_t *space, ulint count= 0; page_id_t id= page_id; - page_id_t high= buf_flush_check_neighbors(*space, id, contiguous, evict); + page_id_t high= buf_flush_check_neighbors(*space, id, contiguous); ut_ad(page_id >= id); ut_ad(page_id < high); @@ -1157,7 +1110,7 @@ static ulint buf_flush_try_neighbors(fil_space_t *space, ut_ad(!buf_pool.watch_is_sentinel(*b)); ut_ad(b->oldest_modification() > 1); flush: - if (b->flush(evict, space)) + if (b->flush(space)) { ++count; continue; @@ -1165,9 +1118,10 @@ static ulint buf_flush_try_neighbors(fil_space_t *space, } /* We avoid flushing 'non-old' blocks in an eviction flush, because the flushed blocks are soon freed */ - else if ((!evict || b->is_old()) && !buf_pool.watch_is_sentinel(*b) && - b->oldest_modification() > 1 && b->lock.u_lock_try(true)) + else if (b->oldest_modification() > 1 && b->lock.u_lock_try(true)) { + /* For the buf_pool.watch[] sentinels, oldest_modification() == 0 */ + ut_ad(!buf_pool.watch_is_sentinel(*b)); if (b->oldest_modification() < 2) b->lock.u_unlock(true); else @@ -1289,10 +1243,8 @@ static void buf_flush_discard_page(buf_page_t *bpage) /** Flush dirty blocks from the end buf_pool.LRU, and move clean blocks to buf_pool.free. @param max maximum number of blocks to flush -@param evict whether dirty pages are to be evicted after flushing them @param n counts of flushed and evicted pages */ -static void buf_flush_LRU_list_batch(ulint max, bool evict, - flush_counters_t *n) +static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n) { ulint scanned= 0; ulint free_limit= srv_LRU_scan_depth; @@ -1340,8 +1292,12 @@ static void buf_flush_LRU_list_batch(ulint max, bool evict, if (state < buf_page_t::READ_FIX && bpage->lock.u_lock_try(true)) { ut_ad(!bpage->is_io_fixed()); - bool do_evict= evict; switch (bpage->oldest_modification()) { + case 2: + /* LRU flushing will always evict pages of the temporary tablespace, + in buf_page_write_complete(). */ + ++n->evicted; + break; case 1: mysql_mutex_lock(&buf_pool.flush_list_mutex); if (ut_d(lsn_t lsn=) bpage->oldest_modification()) @@ -1354,12 +1310,8 @@ static void buf_flush_LRU_list_batch(ulint max, bool evict, case 0: bpage->lock.u_unlock(true); goto evict; - case 2: - /* LRU flushing will always evict pages of the temporary tablespace. */ - do_evict= true; } - /* Block is ready for flush. Dispatch an IO request. - If do_evict, the page may be evicted by buf_page_write_complete(). */ + /* Block is ready for flush. Dispatch an IO request. */ const page_id_t page_id(bpage->id()); const uint32_t space_id= page_id.space(); if (!space || space->id != space_id) @@ -1394,6 +1346,7 @@ static void buf_flush_LRU_list_batch(ulint max, bool evict, no_space: mysql_mutex_lock(&buf_pool.flush_list_mutex); buf_flush_discard_page(bpage); + ++n->evicted; continue; } @@ -1406,8 +1359,8 @@ static void buf_flush_LRU_list_batch(ulint max, bool evict, if (neighbors && space->is_rotational()) n->flushed+= buf_flush_try_neighbors(space, page_id, bpage, neighbors == 1, - do_evict, n->flushed, max); - else if (bpage->flush(do_evict, space)) + n->flushed, max); + else if (bpage->flush(space)) ++n->flushed; else continue; @@ -1434,15 +1387,14 @@ static void buf_flush_LRU_list_batch(ulint max, bool evict, /** Flush and move pages from LRU or unzip_LRU list to the free list. Whether LRU or unzip_LRU is used depends on the state of the system. @param max maximum number of blocks to flush -@param evict whether dirty pages are to be evicted after flushing them @param n counts of flushed and evicted pages */ -static void buf_do_LRU_batch(ulint max, bool evict, flush_counters_t *n) +static void buf_do_LRU_batch(ulint max, flush_counters_t *n) { if (buf_LRU_evict_from_unzip_LRU()) buf_free_from_unzip_LRU_list_batch(); n->evicted= 0; n->flushed= 0; - buf_flush_LRU_list_batch(max, evict, n); + buf_flush_LRU_list_batch(max, n); mysql_mutex_assert_owner(&buf_pool.mutex); buf_lru_freed_page_count+= n->evicted; @@ -1554,8 +1506,8 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn) { if (neighbors && space->is_rotational()) count+= buf_flush_try_neighbors(space, page_id, bpage, - neighbors == 1, false, count, max_n); - else if (bpage->flush(false, space)) + neighbors == 1, count, max_n); + else if (bpage->flush(space)) ++count; else continue; @@ -1721,7 +1673,7 @@ bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed) goto was_freed; } mysql_mutex_unlock(&buf_pool.flush_list_mutex); - if (bpage->flush(false, space)) + if (bpage->flush(space)) { ++n_flush; if (!--max_n_flush) @@ -1779,27 +1731,22 @@ and move clean blocks to buf_pool.free. The caller must invoke buf_dblwr.flush_buffered_writes() after releasing buf_pool.mutex. @param max_n wished maximum mumber of blocks flushed -@param evict whether to evict pages after flushing -@return evict ? number of processed pages : number of pages written */ -ulint buf_flush_LRU(ulint max_n, bool evict) +@return number of pages written */ +static ulint buf_flush_LRU(ulint max_n) { mysql_mutex_assert_owner(&buf_pool.mutex); flush_counters_t n; - buf_do_LRU_batch(max_n, evict, &n); + buf_do_LRU_batch(max_n, &n); ulint pages= n.flushed; if (n.evicted) { - if (evict) - pages+= n.evicted; buf_pool.try_LRU_scan= true; pthread_cond_broadcast(&buf_pool.done_free); } - else if (!pages && !buf_pool.try_LRU_scan && - !buf_pool.LRU_warned.test_and_set(std::memory_order_acquire)) - { + else if (!pages && !buf_pool.try_LRU_scan) /* For example, with the minimum innodb_buffer_pool_size=5M and the default innodb_page_size=16k there are only a little over 316 pages in the buffer pool. The buffer pool can easily be exhausted @@ -1813,12 +1760,7 @@ ulint buf_flush_LRU(ulint max_n, bool evict) (3) This thread is the only one that could make progress, but we fail to do so because all the pages that we scanned are buffer-fixed or latched by some thread. */ - sql_print_warning("InnoDB: Could not free any blocks in the buffer pool!" - " %zu blocks are in use and %zu free." - " Consider increasing innodb_buffer_pool_size.", - UT_LIST_GET_LEN(buf_pool.LRU), - UT_LIST_GET_LEN(buf_pool.free)); - } + buf_pool.LRU_warn(); return pages; } @@ -2437,12 +2379,12 @@ static void buf_flush_page_cleaner() n= srv_max_io_capacity; mysql_mutex_lock(&buf_pool.mutex); LRU_flush: - n= buf_flush_LRU(n, false); + n= buf_flush_LRU(n); mysql_mutex_unlock(&buf_pool.mutex); last_pages+= n; check_oldest_and_set_idle: mysql_mutex_lock(&buf_pool.flush_list_mutex); - buf_pool.n_flush_dec_holding_mutex(); + buf_pool.n_flush_dec(); oldest_lsn= buf_pool.get_oldest_modification(0); if (!oldest_lsn) goto fully_unemployed; @@ -2575,6 +2517,16 @@ static void buf_flush_page_cleaner() #endif } +ATTRIBUTE_COLD void buf_pool_t::LRU_warn() +{ + mysql_mutex_assert_owner(&mutex); + if (!LRU_warned.test_and_set(std::memory_order_acquire)) + sql_print_warning("InnoDB: Could not free any blocks in the buffer pool!" + " %zu blocks are in use and %zu free." + " Consider increasing innodb_buffer_pool_size.", + UT_LIST_GET_LEN(LRU), UT_LIST_GET_LEN(free)); +} + /** Initialize page_cleaner. */ ATTRIBUTE_COLD void buf_flush_page_cleaner_init() { diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index ce37209f154..3fa0cf9002e 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -385,144 +385,76 @@ we put it to free list to be used. @return the free control block, in state BUF_BLOCK_MEMORY */ buf_block_t *buf_LRU_get_free_block(bool have_mutex) { - ulint n_iterations = 0; - ulint flush_failures = 0; - MONITOR_INC(MONITOR_LRU_GET_FREE_SEARCH); - if (have_mutex) { - mysql_mutex_assert_owner(&buf_pool.mutex); - goto got_mutex; - } - DBUG_EXECUTE_IF("recv_ran_out_of_buffer", - if (recv_recovery_is_on() - && recv_sys.apply_log_recs) { - mysql_mutex_lock(&buf_pool.mutex); - goto flush_lru; - }); -get_mutex: - mysql_mutex_lock(&buf_pool.mutex); -got_mutex: - buf_LRU_check_size_of_non_data_objects(); - buf_block_t* block; + bool waited= false; + MONITOR_INC(MONITOR_LRU_GET_FREE_SEARCH); + if (!have_mutex) + mysql_mutex_lock(&buf_pool.mutex); - IF_DBUG(static bool buf_lru_free_blocks_error_printed,); - DBUG_EXECUTE_IF("ib_lru_force_no_free_page", - if (!buf_lru_free_blocks_error_printed) { - n_iterations = 21; - goto not_found;}); + buf_LRU_check_size_of_non_data_objects(); + + buf_block_t *block; retry: - /* If there is a block in the free list, take it */ - if ((block = buf_LRU_get_free_only()) != nullptr) { + /* If there is a block in the free list, take it */ + block= buf_LRU_get_free_only(); + if (block) + { got_block: - const ulint LRU_size = UT_LIST_GET_LEN(buf_pool.LRU); - const ulint available = UT_LIST_GET_LEN(buf_pool.free); - const ulint scan_depth = srv_LRU_scan_depth / 2; - ut_ad(LRU_size <= BUF_LRU_MIN_LEN || available >= scan_depth - || buf_pool.need_LRU_eviction()); + const ulint LRU_size= UT_LIST_GET_LEN(buf_pool.LRU); + const ulint available= UT_LIST_GET_LEN(buf_pool.free); + const ulint scan_depth= srv_LRU_scan_depth / 2; + ut_ad(LRU_size <= BUF_LRU_MIN_LEN || + available >= scan_depth || buf_pool.need_LRU_eviction()); - if (!have_mutex) { - mysql_mutex_unlock(&buf_pool.mutex); - } + if (UNIV_UNLIKELY(available < scan_depth) && LRU_size > BUF_LRU_MIN_LEN) + { + mysql_mutex_lock(&buf_pool.flush_list_mutex); + if (!buf_pool.page_cleaner_active()) + buf_pool.page_cleaner_wakeup(true); + mysql_mutex_unlock(&buf_pool.flush_list_mutex); + } - if (UNIV_UNLIKELY(available < scan_depth) - && LRU_size > BUF_LRU_MIN_LEN) { - mysql_mutex_lock(&buf_pool.flush_list_mutex); - if (!buf_pool.page_cleaner_active()) { - buf_pool.page_cleaner_wakeup(true); - } - mysql_mutex_unlock(&buf_pool.flush_list_mutex); - } + if (!have_mutex) + mysql_mutex_unlock(&buf_pool.mutex); - block->page.zip.clear(); - return block; - } + block->page.zip.clear(); + return block; + } - MONITOR_INC( MONITOR_LRU_GET_FREE_LOOPS ); - if (n_iterations || buf_pool.try_LRU_scan) { - /* If no block was in the free list, search from the - end of the LRU list and try to free a block there. - If we are doing for the first time we'll scan only - tail of the LRU list otherwise we scan the whole LRU - list. */ - if (buf_LRU_scan_and_free_block(n_iterations - ? ULINT_UNDEFINED : 100)) { - goto retry; - } + MONITOR_INC(MONITOR_LRU_GET_FREE_LOOPS); + if (waited || buf_pool.try_LRU_scan) + { + /* If no block was in the free list, search from the end of the + LRU list and try to free a block there. If we are doing for the + first time we'll scan only tail of the LRU list otherwise we scan + the whole LRU list. */ + if (buf_LRU_scan_and_free_block(waited ? ULINT_UNDEFINED : 100)) + goto retry; - /* Tell other threads that there is no point - in scanning the LRU list. */ - buf_pool.try_LRU_scan = false; - } + /* Tell other threads that there is no point in scanning the LRU + list. */ + buf_pool.try_LRU_scan= false; + } - for (;;) { - if ((block = buf_LRU_get_free_only()) != nullptr) { - goto got_block; - } - const bool wake = buf_pool.need_LRU_eviction(); - mysql_mutex_unlock(&buf_pool.mutex); - mysql_mutex_lock(&buf_pool.flush_list_mutex); - const auto n_flush = buf_pool.n_flush(); - if (wake && !buf_pool.page_cleaner_active()) { - buf_pool.page_cleaner_wakeup(true); - } - mysql_mutex_unlock(&buf_pool.flush_list_mutex); - mysql_mutex_lock(&buf_pool.mutex); - if (!n_flush) { - goto not_found; - } - if (!buf_pool.try_LRU_scan) { - my_cond_wait(&buf_pool.done_free, - &buf_pool.mutex.m_mutex); - } - } + waited= true; -not_found: - if (n_iterations > 1) { - MONITOR_INC( MONITOR_LRU_GET_FREE_WAITS ); - } + while (!(block= buf_LRU_get_free_only())) + { + buf_pool.stat.LRU_waits++; - if (n_iterations == 21 - && srv_buf_pool_old_size == srv_buf_pool_size - && buf_pool.LRU_warned.test_and_set(std::memory_order_acquire)) { - IF_DBUG(buf_lru_free_blocks_error_printed = true,); - mysql_mutex_unlock(&buf_pool.mutex); - ib::warn() << "Difficult to find free blocks in the buffer pool" - " (" << n_iterations << " search iterations)! " - << flush_failures << " failed attempts to" - " flush a page!" - " Consider increasing innodb_buffer_pool_size." - " Pending flushes (fsync) log: " - << log_sys.get_pending_flushes() - << "; buffer pool: " - << fil_n_pending_tablespace_flushes - << ". " << os_n_file_reads << " OS file reads, " - << os_n_file_writes << " OS file writes, " - << os_n_fsyncs - << " OS fsyncs."; - mysql_mutex_lock(&buf_pool.mutex); - } + timespec abstime; + set_timespec(abstime, 1); - /* No free block was found: try to flush the LRU list. - The freed blocks will be up for grabs for all threads. + mysql_mutex_lock(&buf_pool.flush_list_mutex); + if (!buf_pool.page_cleaner_active()) + buf_pool.page_cleaner_wakeup(true); + mysql_mutex_unlock(&buf_pool.flush_list_mutex); + if (my_cond_timedwait(&buf_pool.done_free, &buf_pool.mutex.m_mutex, + &abstime)) + buf_pool.LRU_warn(); + } - TODO: A more elegant way would have been to return one freed - up block to the caller here but the code that deals with - removing the block from buf_pool.page_hash and buf_pool.LRU is fairly - involved (particularly in case of ROW_FORMAT=COMPRESSED pages). We - can do that in a separate patch sometime in future. */ -#ifndef DBUG_OFF -flush_lru: -#endif - if (!buf_flush_LRU(innodb_lru_flush_size, true)) { - MONITOR_INC(MONITOR_LRU_SINGLE_FLUSH_FAILURE_COUNT); - ++flush_failures; - } - - n_iterations++; - buf_pool.stat.LRU_waits++; - mysql_mutex_unlock(&buf_pool.mutex); - buf_dblwr.flush_buffered_writes(); - goto get_mutex; + goto got_block; } /** Move the LRU_old pointer so that the length of the old blocks list diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 4986e83cfb9..51e30c88a86 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -766,17 +766,16 @@ public: @retval DB_FAIL if the page contains the wrong ID */ dberr_t read_complete(const fil_node_t &node); - /** Note that a block is no longer dirty, while not removing - it from buf_pool.flush_list - @param temporary whether the page belongs to the temporary tablespace - @param error whether an error may have occurred while writing */ - inline void write_complete(bool temporary, bool error); + /** Release a write fix after a page write was completed. + @param persistent whether the page belongs to a persistent tablespace + @param error whether an error may have occurred while writing + @param state recently read state() value with the correct io-fix */ + void write_complete(bool persistent, bool error, uint32_t state); /** Write a flushable page to a file or free a freeable block. - @param evict whether to evict the page on write completion @param space tablespace @return whether a page write was initiated and buf_pool.mutex released */ - bool flush(bool evict, fil_space_t *space); + bool flush(fil_space_t *space); /** Notify that a page in a temporary tablespace has been modified. */ void set_temp_modified() @@ -1740,10 +1739,6 @@ public: /** Decrement the number of pending LRU flush */ inline void n_flush_dec(); - /** Decrement the number of pending LRU flush - while holding flush_list_mutex */ - inline void n_flush_dec_holding_mutex(); - /** @return whether flush_list flushing is active */ bool flush_list_active() const { @@ -1893,6 +1888,9 @@ public: /** Free a page whose underlying file page has been freed. */ ATTRIBUTE_COLD void release_freed_page(buf_page_t *bpage); + /** Issue a warning that we could not free up buffer pool pages. */ + ATTRIBUTE_COLD void LRU_warn(); + private: /** Temporary memory for page_compressed and encrypted I/O */ struct io_buf_t diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index 74c79e4acc8..2e25b3aed08 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -85,16 +85,6 @@ buf_flush_init_for_writing( bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed= nullptr) MY_ATTRIBUTE((warn_unused_result)); -/** Write out dirty blocks from buf_pool.LRU, -and move clean blocks to buf_pool.free. -The caller must invoke buf_dblwr.flush_buffered_writes() -after releasing buf_pool.mutex. -@param max_n wished maximum mumber of blocks flushed -@param evict whether to evict pages after flushing -@return evict ? number of processed pages : number of pages written -@retval 0 if a buf_pool.LRU batch is already running */ -ulint buf_flush_LRU(ulint max_n, bool evict); - /** Wait until a LRU flush batch ends. */ void buf_flush_wait_LRU_batch_end(); /** Wait until all persistent pages are flushed up to a limit. diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index e0f398301e3..7c2a3950265 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -200,14 +200,10 @@ public: WRITE_ASYNC= WRITE_SYNC | 1, /** A doublewrite batch */ DBLWR_BATCH= WRITE_ASYNC | 8, - /** Write data; evict the block on write completion */ - WRITE_LRU= WRITE_ASYNC | 32, /** Write data and punch hole for the rest */ - PUNCH= WRITE_ASYNC | 64, - /** Write data and punch hole; evict the block on write completion */ - PUNCH_LRU= PUNCH | WRITE_LRU, + PUNCH= WRITE_ASYNC | 16, /** Zero out a range of bytes in fil_space_t::io() */ - PUNCH_RANGE= WRITE_SYNC | 128, + PUNCH_RANGE= WRITE_SYNC | 32, }; constexpr IORequest(buf_page_t *bpage, buf_tmp_buffer_t *slot, @@ -220,7 +216,6 @@ public: bool is_read() const { return (type & READ_SYNC) != 0; } bool is_write() const { return (type & WRITE_SYNC) != 0; } - bool is_LRU() const { return (type & (WRITE_LRU ^ WRITE_ASYNC)) != 0; } bool is_async() const { return (type & (READ_SYNC ^ READ_ASYNC)) != 0; } void write_complete(int io_error) const; diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h index 971f6363bdb..23c7edb7137 100644 --- a/storage/innobase/include/srv0mon.h +++ b/storage/innobase/include/srv0mon.h @@ -196,7 +196,6 @@ enum monitor_id_t { MONITOR_FLUSH_ADAPTIVE_AVG_PASS, MONITOR_LRU_GET_FREE_LOOPS, - MONITOR_LRU_GET_FREE_WAITS, MONITOR_FLUSH_AVG_PAGE_RATE, MONITOR_FLUSH_LSN_AVG_RATE, @@ -217,7 +216,6 @@ enum monitor_id_t { MONITOR_LRU_BATCH_SCANNED_PER_CALL, MONITOR_LRU_BATCH_FLUSH_TOTAL_PAGE, MONITOR_LRU_BATCH_EVICT_TOTAL_PAGE, - MONITOR_LRU_SINGLE_FLUSH_FAILURE_COUNT, MONITOR_LRU_GET_FREE_SEARCH, MONITOR_LRU_SEARCH_SCANNED, MONITOR_LRU_SEARCH_SCANNED_NUM_CALL, diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc index e8534318ff3..145e2b04051 100644 --- a/storage/innobase/srv/srv0mon.cc +++ b/storage/innobase/srv/srv0mon.cc @@ -376,11 +376,6 @@ static monitor_info_t innodb_counter_info[] = MONITOR_NONE, MONITOR_DEFAULT_START, MONITOR_LRU_GET_FREE_LOOPS}, - {"buffer_LRU_get_free_waits", "buffer", - "Total sleep waits in LRU get free.", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_LRU_GET_FREE_WAITS}, - {"buffer_flush_avg_page_rate", "buffer", "Average number of pages at which flushing is happening", MONITOR_NONE, @@ -484,11 +479,6 @@ static monitor_info_t innodb_counter_info[] = MONITOR_EXISTING | MONITOR_DEFAULT_ON), MONITOR_DEFAULT_START, MONITOR_LRU_BATCH_EVICT_TOTAL_PAGE}, - {"buffer_LRU_single_flush_failure_count", "Buffer", - "Number of times attempt to flush a single page from LRU failed", - MONITOR_NONE, - MONITOR_DEFAULT_START, MONITOR_LRU_SINGLE_FLUSH_FAILURE_COUNT}, - {"buffer_LRU_get_free_search", "Buffer", "Number of searches performed for a clean page", MONITOR_NONE, diff --git a/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result b/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result index 52950a41c5e..4a934ce8940 100644 --- a/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result +++ b/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result @@ -70,7 +70,6 @@ buffer_flush_n_to_flush_by_age buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NUL buffer_flush_adaptive_avg_time buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Avg time (ms) spent for adaptive flushing recently. buffer_flush_adaptive_avg_pass buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of adaptive flushes passed during the recent Avg period. buffer_LRU_get_free_loops buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Total loops in LRU get free. -buffer_LRU_get_free_waits buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Total sleep waits in LRU get free. buffer_flush_avg_page_rate buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Average number of pages at which flushing is happening buffer_flush_lsn_avg_rate buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Average redo generation rate buffer_flush_pct_for_dirty buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Percent of IO capacity used to avoid max dirty page limit @@ -90,7 +89,6 @@ buffer_LRU_batch_num_scan buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NUL buffer_LRU_batch_scanned_per_call buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 set_member Pages scanned per LRU batch call buffer_LRU_batch_flush_total_pages buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Total pages flushed as part of LRU batches buffer_LRU_batch_evict_total_pages buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Total pages evicted as part of LRU batches -buffer_LRU_single_flush_failure_count Buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of times attempt to flush a single page from LRU failed buffer_LRU_get_free_search Buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of searches performed for a clean page buffer_LRU_search_scanned buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 set_owner Total pages scanned as part of LRU search buffer_LRU_search_num_scan buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 set_member Number of times LRU search is performed From 17e59ed3aad481918f1a01d8afbc071c316d5930 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 22 Mar 2024 14:33:48 +0200 Subject: [PATCH 093/106] MDEV-33454 release row locks for non-modified rows at XA PREPARE From the correctness point of view, it should be safe to release all locks on index records that were not modified by the transaction. Doing so should make the locks after XA PREPARE fully compatible with what would happen if the server were restarted: InnoDB table IX locks and exclusive record locks would be resurrected based on undo log records. Concurrently running transactions that are waiting for a lock may invoke lock_rec_convert_impl_to_expl() to create an explicit record lock object on behalf of the lock-owning transaction so that they can attaching their waiting lock request on the explicit record lock object. Explicit locks would be released by trx_t::release_locks() during commit or rollback. Any clustered index record whose DB_TRX_ID belongs to a transaction that is in active or XA PREPARE state will be implicitly locked by that transaction. On XA PREPARE, we can release explicit exclusive locks on records whose DB_TRX_ID does not match the current transaction identifier. lock_rec_unlock_unmodified(): Release record locks that are not implicitly held by the current transaction. lock_release_on_prepare_try(), lock_release_on_prepare(): Invoke lock_rec_unlock_unmodified(). row_trx_id_offset(): Declare non-static. lock_rec_unlock(): Replaces lock_rec_unlock_supremum(). Reviewed by: Vladislav Lesin --- storage/innobase/lock/lock0lock.cc | 181 +++++++++++++++++++++-------- 1 file changed, 133 insertions(+), 48 deletions(-) diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 27209f71795..dd179ce900b 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -4182,7 +4182,7 @@ restart: ulint count= 1000; /* We will not attempt hardware lock elision (memory transaction) here. Both lock_rec_dequeue_from_page() and lock_table_dequeue() - would likely lead to a memory transaction due to a system call, to + would likely lead to a memory transaction abort due to a system call, to wake up a waiting transaction. */ lock_sys.rd_lock(SRW_LOCK_CALL); trx->mutex_lock(); @@ -4352,28 +4352,82 @@ void lock_release_on_drop(trx_t *trx) } } -/** Reset lock bit for supremum and rebuild waiting queue. +/** Reset a lock bit and rebuild waiting queue. @param cell rec hash cell of in_lock @param lock the lock with supemum bit set */ -static void lock_rec_unlock_supremum(hash_cell_t &cell, lock_t *lock) +static void lock_rec_unlock(hash_cell_t &cell, lock_t *lock, ulint heap_no) { - ut_ad(lock_rec_get_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM)); + ut_ad(lock_rec_get_nth_bit(lock, heap_no)); #ifdef SAFE_MUTEX ut_ad(!mysql_mutex_is_owner(&lock_sys.wait_mutex)); #endif /* SAFE_MUTEX */ ut_ad(!lock->is_table()); ut_ad(lock_sys.is_writer() || lock->trx->mutex_is_owner()); - lock_rec_reset_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM); + lock_rec_reset_nth_bit(lock, heap_no); - lock_t *first_lock= lock_sys_t::get_first( - cell, lock->un_member.rec_lock.page_id, PAGE_HEAP_NO_SUPREMUM); + lock_t *first_lock= + lock_sys_t::get_first(cell, lock->un_member.rec_lock.page_id, heap_no); lock_rec_rebuild_waiting_queue( #if defined(UNIV_DEBUG) || !defined(DBUG_OFF) lock->trx, #endif /* defined(UNIV_DEBUG) || !defined(DBUG_OFF) */ - cell, first_lock, PAGE_HEAP_NO_SUPREMUM); + cell, first_lock, heap_no); +} + +/** Release locks to unmodified records on a clustered index page. +@param cell lock_sys.rec_hash cell of lock +@param lock record lock +@param offsets storage for rec_get_offsets() +@param heap storage for rec_get_offsets() +@param mtr mini-transaction (will be started and committed) */ +static void lock_rec_unlock_unmodified(hash_cell_t &cell, lock_t *lock, + rec_offs *&offsets, mem_heap_t *&heap, + mtr_t &mtr) +{ + ut_ad(!lock->is_waiting()); + + dict_index_t *const index= lock->index; + + mtr.start(); + if (buf_block_t *block= + btr_block_get(*index, lock->un_member.rec_lock.page_id.page_no(), + RW_S_LATCH, true, &mtr)) + { + if (UNIV_UNLIKELY(!page_is_leaf(block->page.frame))) + { + ut_ad("corrupted lock system" == 0); + goto func_exit; + } + + for (ulint i= PAGE_HEAP_NO_USER_LOW; i < lock_rec_get_n_bits(lock); ++i) + { + if (!lock_rec_get_nth_bit(lock, i)); + else if (const rec_t *rec= + page_find_rec_with_heap_no(block->page.frame, i)) + { + if (index->is_clust()) + { + if (trx_read_trx_id(rec + row_trx_id_offset(rec, index)) == + lock->trx->id) + continue; + unlock_rec: + lock_rec_unlock(cell, lock, i); + } + else + { + offsets= rec_get_offsets(rec, index, offsets, index->n_core_fields, + ULINT_UNDEFINED, &heap); + if (lock->trx != + lock_sec_rec_some_has_impl(lock->trx, rec, index, offsets)) + goto unlock_rec; + } + } + } + } +func_exit: + mtr.commit(); } /** Release non-exclusive locks on XA PREPARE, @@ -4391,6 +4445,12 @@ static bool lock_release_on_prepare_try(trx_t *trx) DBUG_ASSERT(trx->state == TRX_STATE_PREPARED); bool all_released= true; + mtr_t mtr; + rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; + rec_offs *offsets= offsets_; + mem_heap_t *heap= nullptr; + rec_offs_init(offsets_); + lock_sys.rd_lock(SRW_LOCK_CALL); trx->mutex_lock(); @@ -4407,20 +4467,24 @@ static bool lock_release_on_prepare_try(trx_t *trx) if (!lock->is_table()) { ut_ad(!lock->index->table->is_temporary()); - bool supremum_bit = lock_rec_get_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM); - bool rec_granted_exclusive_not_gap = + bool supremum_bit= lock_rec_get_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM); + bool rec_granted_exclusive_not_gap= lock->is_rec_granted_exclusive_not_gap(); if (!supremum_bit && rec_granted_exclusive_not_gap) continue; - auto &lock_hash= lock_sys.hash_get(lock->type_mode); - auto cell= lock_hash.cell_get(lock->un_member.rec_lock.page_id.fold()); + if (UNIV_UNLIKELY(lock->type_mode & (LOCK_PREDICATE | LOCK_PRDT_PAGE))) + continue; /* SPATIAL INDEX locking is broken. */ + auto cell= + lock_sys.rec_hash.cell_get(lock->un_member.rec_lock.page_id.fold()); auto latch= lock_sys_t::hash_table::latch(cell); if (latch->try_acquire()) { if (!rec_granted_exclusive_not_gap) lock_rec_dequeue_from_page(lock, false); else if (supremum_bit) - lock_rec_unlock_supremum(*cell, lock); + lock_rec_unlock(*cell, lock, PAGE_HEAP_NO_SUPREMUM); + else + lock_rec_unlock_unmodified(*cell, lock, offsets, heap, mtr); latch->release(); } else @@ -4453,6 +4517,8 @@ static bool lock_release_on_prepare_try(trx_t *trx) lock_sys.rd_unlock(); trx->mutex_unlock(); + if (UNIV_LIKELY_NULL(heap)) + mem_heap_free(heap); return all_released; } @@ -4466,52 +4532,71 @@ void lock_release_on_prepare(trx_t *trx) if (lock_release_on_prepare_try(trx)) return; - LockMutexGuard g{SRW_LOCK_CALL}; - trx->mutex_lock(); + mtr_t mtr; + rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; + rec_offs *offsets= offsets_; + mem_heap_t *heap= nullptr; + + rec_offs_init(offsets_); - for (lock_t *prev, *lock= UT_LIST_GET_LAST(trx->lock.trx_locks); lock; - lock= prev) { - ut_ad(lock->trx == trx); - prev= UT_LIST_GET_PREV(trx_locks, lock); - if (!lock->is_table()) + LockMutexGuard g{SRW_LOCK_CALL}; + trx->mutex_lock(); + + for (lock_t *prev, *lock= UT_LIST_GET_LAST(trx->lock.trx_locks); lock; + lock= prev) { - ut_ad(!lock->index->table->is_temporary()); - if (!lock->is_rec_granted_exclusive_not_gap()) - lock_rec_dequeue_from_page(lock, false); - else if (lock_rec_get_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM)) + ut_ad(lock->trx == trx); + prev= UT_LIST_GET_PREV(trx_locks, lock); + if (!lock->is_table()) { - auto &lock_hash= lock_sys.hash_get(lock->type_mode); - auto cell= lock_hash.cell_get(lock->un_member.rec_lock.page_id.fold()); - lock_rec_unlock_supremum(*cell, lock); + ut_ad(!lock->index->table->is_temporary()); + if (!lock->is_rec_granted_exclusive_not_gap()) + lock_rec_dequeue_from_page(lock, false); + else if (UNIV_UNLIKELY(lock->type_mode & + (LOCK_PREDICATE | LOCK_PRDT_PAGE))) + /* SPATIAL INDEX locking is broken. */; + else + { + auto cell= lock_sys.rec_hash.cell_get(lock->un_member.rec_lock. + page_id.fold()); + if (lock_rec_get_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM)) + lock_rec_unlock(*cell, lock, PAGE_HEAP_NO_SUPREMUM); + else + { + ut_ad(lock->trx->isolation_level > TRX_ISO_READ_COMMITTED || + /* Insert-intention lock is valid for supremum for isolation + level > TRX_ISO_READ_COMMITTED */ + lock->mode() == LOCK_X || + !lock_rec_get_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM)); + lock_rec_unlock_unmodified(*cell, lock, offsets, heap, mtr); + } + } } else - ut_ad(lock->trx->isolation_level > TRX_ISO_READ_COMMITTED || - /* Insert-intention lock is valid for supremum for isolation - level > TRX_ISO_READ_COMMITTED */ - lock->mode() == LOCK_X || - !lock_rec_get_nth_bit(lock, PAGE_HEAP_NO_SUPREMUM)); - } - else - { - ut_d(dict_table_t *table= lock->un_member.tab_lock.table); - ut_ad(!table->is_temporary()); - switch (lock->mode()) { - case LOCK_IS: - case LOCK_S: - lock_table_dequeue(lock, false); - break; - case LOCK_IX: - case LOCK_X: - ut_ad(table->id >= DICT_HDR_FIRST_ID || trx->dict_operation); - /* fall through */ - default: - break; + { + ut_d(dict_table_t *table= lock->un_member.tab_lock.table); + ut_ad(!table->is_temporary()); + switch (lock->mode()) { + case LOCK_IS: + case LOCK_S: + lock_table_dequeue(lock, false); + break; + case LOCK_IX: + case LOCK_X: + ut_ad(table->id >= DICT_HDR_FIRST_ID || trx->dict_operation); + /* fall through */ + default: + break; + } } } } trx->mutex_unlock(); + + if (UNIV_LIKELY_NULL(heap)) + mem_heap_free(heap); } /** Release locks on a table whose creation is being rolled back */ From f0590db5c5760c8d0de41c10fb76e3c7f44358f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 22 Mar 2024 14:57:00 +0200 Subject: [PATCH 094/106] MDEV-33591 MONITOR_INC_VALUE_CUMULATIVE is executed regardless of "if" condition MONITOR_INC_VALUE_CUMULATIVE is a multiline macro, so the second statement will be executed always, regardless of "if" condition. These problems first started with commit b1ab211dee599eabd9a5b886fafa3adea29ae041 (MDEV-15053). Thanks to Yury Chaikou from ServiceNow for the report. --- storage/innobase/buf/buf0flu.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index e181d311a7c..d74ccd75521 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1389,10 +1389,12 @@ reacquire_mutex: mysql_mutex_assert_owner(&buf_pool.mutex); if (scanned) + { MONITOR_INC_VALUE_CUMULATIVE(MONITOR_LRU_BATCH_SCANNED, MONITOR_LRU_BATCH_SCANNED_NUM_CALL, MONITOR_LRU_BATCH_SCANNED_PER_CALL, scanned); + } } /** Flush and move pages from LRU or unzip_LRU list to the free list. @@ -1543,15 +1545,19 @@ static ulint buf_do_flush_list_batch(ulint max_n, lsn_t lsn) space->release(); if (scanned) + { MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_BATCH_SCANNED, MONITOR_FLUSH_BATCH_SCANNED_NUM_CALL, MONITOR_FLUSH_BATCH_SCANNED_PER_CALL, scanned); + } if (count) + { MONITOR_INC_VALUE_CUMULATIVE(MONITOR_FLUSH_BATCH_TOTAL_PAGE, MONITOR_FLUSH_BATCH_COUNT, MONITOR_FLUSH_BATCH_PAGES, count); + } mysql_mutex_assert_owner(&buf_pool.mutex); return count; } From 70b907724e1c5185be8c5722c417dcbc051520f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 22 Mar 2024 15:07:31 +0200 Subject: [PATCH 095/106] MDEV-32364 fixup: crash in ut_dontdump() --- storage/innobase/include/ut0new.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/storage/innobase/include/ut0new.h b/storage/innobase/include/ut0new.h index 01bf34dc856..f359610bfbd 100644 --- a/storage/innobase/include/ut0new.h +++ b/storage/innobase/include/ut0new.h @@ -1078,9 +1078,8 @@ static inline void *ut_malloc_dontdump(size_t n_bytes, ...) { void *ptr = my_large_malloc(&n_bytes, MYF(0)); - ut_dontdump(ptr, n_bytes, true); - if (ptr) { + ut_dontdump(ptr, n_bytes, true); os_total_large_mem_allocated += n_bytes; } return ptr; From e9d334434df20bf2da2c94c78dd0dbe7939e5ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 15 Feb 2024 09:40:50 +0200 Subject: [PATCH 096/106] MDEV-32787 : Assertion `!wsrep_has_changes(thd) || (thd->lex->sql_command == SQLCOM_CREATE_TABLE && !thd->is_current_stmt_binlog_format_row()) || thd->wsrep_cs().transaction().state() == wsrep::transaction::s_aborted' failed in void wsrep_commit_empty(THD*, bool) When we commit empty transaction we should allow wsrep transaction to be on s_must_replay state for DDL that was killed during certification. Fix is tested with RQG because deterministic mtr-testcase was not found. Signed-off-by: Julius Goryavsky --- sql/wsrep_mysqld.cc | 58 +++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index 6d7f555d479..d7066e65332 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -3468,21 +3468,11 @@ void wsrep_ready_set(bool ready_value) step is performed to leave the wsrep transaction in the state as it never existed. - This should not be an inline functions as it requires a lot of stack space - because of WSREP_DBUG() usage. It's also not a function that is - frequently called. */ void wsrep_commit_empty(THD* thd, bool all) { DBUG_ENTER("wsrep_commit_empty"); - WSREP_DEBUG("wsrep_commit_empty for %llu client_state %s client_mode" - " %s trans_state %s sql %s", - thd_get_thread_id(thd), - wsrep::to_c_string(thd->wsrep_cs().state()), - wsrep::to_c_string(thd->wsrep_cs().mode()), - wsrep::to_c_string(thd->wsrep_cs().transaction().state()), - wsrep_thd_query(thd)); if (wsrep_is_real(thd, all) && wsrep_thd_is_local(thd) && @@ -3490,14 +3480,40 @@ void wsrep_commit_empty(THD* thd, bool all) !thd->internal_transaction() && thd->wsrep_trx().state() != wsrep::transaction::s_committed) { - /* Here transaction is either empty (i.e. no changes) or - it was CREATE TABLE with no row binlog format or - we have already aborted transaction e.g. because max writeset size - has been reached. */ - DBUG_ASSERT(!wsrep_has_changes(thd) || - (thd->lex->sql_command == SQLCOM_CREATE_TABLE && - !thd->is_current_stmt_binlog_format_row()) || - thd->wsrep_cs().transaction().state() == wsrep::transaction::s_aborted); +#ifndef DBUG_OFF + const bool empty= !wsrep_has_changes(thd); + const bool create= thd->lex->sql_command == SQLCOM_CREATE_TABLE && + !thd->is_current_stmt_binlog_format_row(); + const bool aborted= thd->wsrep_cs().transaction().state() == wsrep::transaction::s_aborted; + const bool ddl_replay= ((sql_command_flags[thd->lex->sql_command] & + (CF_SCHEMA_CHANGE | CF_ADMIN_COMMAND)) && + thd->wsrep_cs().transaction().state() == wsrep::transaction::s_must_replay); + /* Here transaction is either + (1) empty (i.e. no changes) or + (2) it was CREATE TABLE with no row binlog format or + (3) we have already aborted transaction e.g. because max writeset size + has been reached or + (4) it was DDL and got BF aborted and must replay. + */ + if(!(empty || create || aborted || ddl_replay)) + { + WSREP_DEBUG("wsrep_commit_empty: thread: %llu client_state: %s client_mode:" + " %s trans_state: %s error: %s empty: %d create: %d aborted:" + " %d ddl_replay: %d sql: %s", + thd_get_thread_id(thd), + wsrep::to_c_string(thd->wsrep_cs().state()), + wsrep::to_c_string(thd->wsrep_cs().mode()), + wsrep::to_c_string(thd->wsrep_cs().transaction().state()), + wsrep::to_c_string(thd->wsrep_cs().current_error()), + empty, create, aborted, ddl_replay, + wsrep_thd_query(thd)); + + DBUG_ASSERT(empty || // 1 + create || // 2 + aborted || // 3 + ddl_replay); // 4 + } +#endif /* DBUG_OFF */ bool have_error= wsrep_current_error(thd); int ret= wsrep_before_rollback(thd, all) || wsrep_after_rollback(thd, all) || @@ -3511,10 +3527,10 @@ void wsrep_commit_empty(THD* thd, bool all) DBUG_ASSERT(wsrep_current_error(thd) == wsrep::e_deadlock_error); thd->wsrep_cs().reset_error(); } + if (ret) - { - WSREP_DEBUG("wsrep_commit_empty failed: %d", wsrep_current_error(thd)); - } + WSREP_DEBUG("wsrep_commit_empty failed: %s", + wsrep::to_c_string(thd->wsrep_cs().current_error())); } DBUG_VOID_RETURN; } From 987a266d77a894c2816c10176d102b740bbc18f9 Mon Sep 17 00:00:00 2001 From: Julius Goryavsky Date: Mon, 25 Mar 2024 12:13:57 +0100 Subject: [PATCH 097/106] galera: wsrep-lib submodule update --- wsrep-lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wsrep-lib b/wsrep-lib index a5d95f0175f..7d108eb8706 160000 --- a/wsrep-lib +++ b/wsrep-lib @@ -1 +1 @@ -Subproject commit a5d95f0175f10b6127ea039c542725f6c4aa5cb9 +Subproject commit 7d108eb8706962abc74705bedfc60cfc3f296ea6 From c1da568502a1aaa5e3b23a74e04ba23c9aba4281 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Thu, 21 Mar 2024 14:48:06 +1100 Subject: [PATCH 098/106] MDEV-33726 Moving from MariaDB 10.5 to 10.6 mysql_upgrade .. is not updating some system tables Some schema changes from MDEV-24312 master_host has 60 character limit, increase to 255 bytes failed to happen in the upgrade for tables in the mysql schema: * mysql.global_priv * mysql.procs_priv * mysql.proxies_priv * mysql.roles_mapping --- mysql-test/main/system_mysql_db_fix50030.result | 2 +- mysql-test/main/system_mysql_db_fix50117.result | 2 +- mysql-test/main/system_mysql_db_fix50568.result | 2 +- scripts/mysql_system_tables_fix.sql | 9 ++++++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/mysql-test/main/system_mysql_db_fix50030.result b/mysql-test/main/system_mysql_db_fix50030.result index 387ae31ce06..23f67e9dbe3 100644 --- a/mysql-test/main/system_mysql_db_fix50030.result +++ b/mysql-test/main/system_mysql_db_fix50030.result @@ -151,7 +151,7 @@ columns_priv CREATE TABLE `columns_priv` ( show create table procs_priv; Table Create Table procs_priv CREATE TABLE `procs_priv` ( - `Host` char(60) NOT NULL DEFAULT '', + `Host` char(255) NOT NULL DEFAULT '', `Db` char(64) NOT NULL DEFAULT '', `User` char(128) NOT NULL DEFAULT '', `Routine_name` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '', diff --git a/mysql-test/main/system_mysql_db_fix50117.result b/mysql-test/main/system_mysql_db_fix50117.result index 411c8b47f67..505223897a4 100644 --- a/mysql-test/main/system_mysql_db_fix50117.result +++ b/mysql-test/main/system_mysql_db_fix50117.result @@ -131,7 +131,7 @@ columns_priv CREATE TABLE `columns_priv` ( show create table procs_priv; Table Create Table procs_priv CREATE TABLE `procs_priv` ( - `Host` char(60) NOT NULL DEFAULT '', + `Host` char(255) NOT NULL DEFAULT '', `Db` char(64) NOT NULL DEFAULT '', `User` char(128) NOT NULL DEFAULT '', `Routine_name` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '', diff --git a/mysql-test/main/system_mysql_db_fix50568.result b/mysql-test/main/system_mysql_db_fix50568.result index 16ff841b886..14e16642bc1 100644 --- a/mysql-test/main/system_mysql_db_fix50568.result +++ b/mysql-test/main/system_mysql_db_fix50568.result @@ -152,7 +152,7 @@ columns_priv CREATE TABLE `columns_priv` ( show create table procs_priv; Table Create Table procs_priv CREATE TABLE `procs_priv` ( - `Host` char(60) NOT NULL DEFAULT '', + `Host` char(255) NOT NULL DEFAULT '', `Db` char(64) NOT NULL DEFAULT '', `User` char(128) NOT NULL DEFAULT '', `Routine_name` char(64) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT '', diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index e9068c43b96..b4d56edb06b 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -762,19 +762,22 @@ if @have_innodb then end if // DELIMITER ; -# MDEV-4332 longer user names +# MDEV-4332 longer user names, extended by MDEV-24312 to longer again. alter table user modify User char(128) binary not null default ''; alter table db modify User char(128) binary not null default ''; alter table tables_priv modify User char(128) binary not null default ''; alter table columns_priv modify User char(128) binary not null default ''; -alter table procs_priv modify User char(128) binary not null default ''; +alter table procs_priv modify User char(128) binary not null default '', modify Host char(255) binary DEFAULT ''; alter table proc modify definer varchar(384) collate utf8mb3_bin not null default ''; -alter table proxies_priv modify User char(128) COLLATE utf8mb3_bin not null default ''; +alter table proxies_priv modify User char(128) COLLATE utf8mb3_bin not null default '', modify Host char(255) binary DEFAULT ''; alter table proxies_priv modify Proxied_user char(128) COLLATE utf8mb3_bin not null default ''; alter table proxies_priv modify Grantor varchar(384) COLLATE utf8mb3_bin not null default ''; alter table servers modify Username char(128) not null default ''; alter table procs_priv modify Grantor varchar(384) COLLATE utf8mb3_bin not null default ''; alter table tables_priv modify Grantor varchar(384) COLLATE utf8mb3_bin not null default ''; +# MDEV-33726 longer names from MDEV-24312 extension +alter table if exists global_priv modify Host char(255) binary DEFAULT '', modify User char(128) binary not null default ''; +alter table if exists roles_mapping modify Host char(255) binary not null DEFAULT '', modify User char(128) binary not null default ''; # Activate the new, possible modified privilege tables # This should not be needed, but gives us some extra testing that the above From b762541dd63df8935134b477ef9473c709941737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Tue, 23 Jan 2024 08:38:19 +0200 Subject: [PATCH 099/106] MDEV-33278 : Assertion failure in thd_get_thread_id at lock_wait_wsrep Problem is that not all conflicting transactions have THD object. Therefore, it must be checked that victim has THD before it's identification is added to victim list as victim's thread identification is later requested using thd_get_thread_id function that requires that we have valid pointer to THD object in trx->mysql_thd. Victim might not have trx->mysql_thd in two cases: (1) An incomplete transaction that was recovered from undo logs on server startup (and not yet rolled back). (2) Transaction that is in XA PREPARE state and whose client connection was disconnected. Neither of these can complete before lock_wait_wsrep() releases lock_sys.latch. (1) trx_t::commit_in_memory() is clearing both trx_t::state and trx_t::is_recovered before it invokes lock_release(trx_t*) (which would be blocked by the exclusive lock_sys.latch that we are holding here). Hence, it is not possible to write a debug assertion to document this scenario. (2) If is in XA PREPARE state, it would eventually be rolled back and the lock conflict would be resolved when an XA COMMIT or XA ROLLBACK statement is executed in some other connection. Signed-off-by: Julius Goryavsky --- storage/innobase/lock/lock0lock.cc | 38 ++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index dd179ce900b..69b3dd1f5c2 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -970,8 +970,31 @@ func_exit: for (lock_t *lock= UT_LIST_GET_FIRST(table->locks); lock; lock= UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock)) { - /* if victim has also BF status, but has earlier seqno, we have to wait */ - if (lock->trx != trx && + /* Victim trx needs to be different from BF trx and it has to have a + THD so that we can kill it. Victim might not have THD in two cases: + + (1) An incomplete transaction that was recovered from undo logs + on server startup (and not yet rolled back). + + (2) Transaction that is in XA PREPARE state and whose client + connection was disconnected. + + Neither of these can complete before lock_wait_wsrep() releases + lock_sys.latch. + + (1) trx_t::commit_in_memory() is clearing both + trx_t::state and trx_t::is_recovered before it invokes + lock_release(trx_t*) (which would be blocked by the exclusive + lock_sys.latch that we are holding here). Hence, it is not + possible to write a debug assertion to document this scenario. + + (2) If is in XA PREPARE state, it would eventually be rolled + back and the lock conflict would be resolved when an XA COMMIT + or XA ROLLBACK statement is executed in some other connection. + + If victim has also BF status, but has earlier seqno, we have to wait. + */ + if (lock->trx != trx && lock->trx->mysql_thd && !(wsrep_thd_is_BF(lock->trx->mysql_thd, false) && wsrep_thd_order_before(lock->trx->mysql_thd, trx->mysql_thd))) { @@ -1003,8 +1026,11 @@ func_exit: lock= lock_rec_get_next(heap_no, lock); do { - /* if victim has also BF status, but has earlier seqno, we have to wait */ - if (lock->trx != trx && + /* This is similar case as above except here we have + record-locks instead of table locks. See details + from comment above. + */ + if (lock->trx != trx && lock->trx->mysql_thd && !(wsrep_thd_is_BF(lock->trx->mysql_thd, false) && wsrep_thd_order_before(lock->trx->mysql_thd, trx->mysql_thd))) { @@ -1030,8 +1056,12 @@ func_exit: std::vector> victim_id; for (trx_t *v : victims) + { + /* Victim must have THD */ + ut_ad(v->mysql_thd); victim_id.emplace_back(std::pair {thd_get_thread_id(v->mysql_thd), v->id}); + } DBUG_EXECUTE_IF("sync.before_wsrep_thd_abort", { From 318000cffc71b1e6ede98f9ddf1e531c6f209526 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Tue, 26 Mar 2024 00:05:07 +0100 Subject: [PATCH 100/106] MDEV-33506 Show original IP in the "aborted" message. Add "real ip:" part to the aborted message Only for proxy-protocoled connection, so it does not not to cause confusion to normal users. --- include/mysql_com.h | 1 + mysql-test/main/mysql_client_test.result | 1 + mysql-test/main/mysql_client_test.test | 6 +++++ sql/net_serv.cc | 3 +++ sql/share/errmsg-utf8.txt | 32 ++++++++++++------------ sql/sql_class.h | 20 ++++++++++++++- sql/sql_connect.cc | 2 +- tests/mysql_client_test.c | 6 ++++- 8 files changed, 52 insertions(+), 19 deletions(-) diff --git a/include/mysql_com.h b/include/mysql_com.h index 2cdda8457ea..d591a023236 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -478,6 +478,7 @@ typedef struct st_net { my_bool thread_specific_malloc; unsigned char compress; my_bool pkt_nr_can_be_reset; + my_bool using_proxy_protocol; /* Pointer to query object in query cache, do not equal NULL (0) for queries in cache that have not stored its results yet diff --git a/mysql-test/main/mysql_client_test.result b/mysql-test/main/mysql_client_test.result index dbc1feaa23b..dbd5aaeaae5 100644 --- a/mysql-test/main/mysql_client_test.result +++ b/mysql-test/main/mysql_client_test.result @@ -261,3 +261,4 @@ SET @@global.character_set_server= @save_character_set_server; SET @@global.collation_server= @save_collation_server; SET @@global.character_set_client= @save_character_set_client; SET @@global.collation_connection= @save_collation_connection; +FOUND 1 /Aborted connection.*'u' host: '192.0.2.1' real ip: '(localhost|::1)'/ in mysqld.1.err diff --git a/mysql-test/main/mysql_client_test.test b/mysql-test/main/mysql_client_test.test index bcb246a8a06..0de459bd316 100644 --- a/mysql-test/main/mysql_client_test.test +++ b/mysql-test/main/mysql_client_test.test @@ -57,3 +57,9 @@ SET @@global.character_set_server= @save_character_set_server; SET @@global.collation_server= @save_collation_server; SET @@global.character_set_client= @save_character_set_client; SET @@global.collation_connection= @save_collation_connection; + +# Search for "real ip" in Aborted message +# This is indicator for abort of the proxied connections. +let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err; +let SEARCH_PATTERN= Aborted connection.*'u' host: '192.0.2.1' real ip: '(localhost|::1)'; +source include/search_pattern_in_file.inc; diff --git a/sql/net_serv.cc b/sql/net_serv.cc index b1009b6552b..af65d92c2b9 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -163,6 +163,7 @@ my_bool my_net_init(NET *net, Vio *vio, void *thd, uint my_flags) net->net_skip_rest_factor= 0; net->last_errno=0; net->pkt_nr_can_be_reset= 0; + net->using_proxy_protocol= 0; net->thread_specific_malloc= MY_TEST(my_flags & MY_THREAD_SPECIFIC); net->thd= 0; #ifdef MYSQL_SERVER @@ -217,6 +218,7 @@ void net_end(NET *net) DBUG_ENTER("net_end"); my_free(net->buff); net->buff=0; + net->using_proxy_protocol= 0; DBUG_VOID_RETURN; } @@ -955,6 +957,7 @@ static handle_proxy_header_result handle_proxy_header(NET *net) return RETRY; /* Change peer address in THD and ACL structures.*/ uint host_errors; + net->using_proxy_protocol= 1; return (handle_proxy_header_result)thd_set_peer_addr(thd, &(peer_info.peer_addr), NULL, peer_info.port, false, &host_errors); diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 890883bcd7b..be497b2338c 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -4258,22 +4258,22 @@ ER_ERROR_DURING_CHECKPOINT swe "Fick fel %M vid CHECKPOINT" ukr "Отримано помилку %M під час CHECKPOINT" ER_NEW_ABORTING_CONNECTION 08S01 - chi "终止的连接 %lld 到数据库: '%-.192s' 用户: '%-.48s' 主机: '%-.64s' (%-.64s)" - cze "Spojení %lld do databáze: '%-.192s' uživatel: '%-.48s' stroj: '%-.64s' (%-.64s) bylo přerušeno" - dan "Afbrød forbindelsen %lld til databasen '%-.192s' bruger: '%-.48s' vært: '%-.64s' (%-.64s)" - eng "Aborted connection %lld to db: '%-.192s' user: '%-.48s' host: '%-.64s' (%-.64s)" - est "Ühendus katkestatud %lld andmebaas: '%-.192s' kasutaja: '%-.48s' masin: '%-.64s' (%-.64s)" - fre "Connection %lld avortée vers la bd: '%-.192s' utilisateur: '%-.48s' hôte: '%-.64s' (%-.64s)" - ger "Abbruch der Verbindung %lld zur Datenbank '%-.192s'. Benutzer: '%-.48s', Host: '%-.64s' (%-.64s)" - ita "Interrotta la connessione %lld al db: ''%-.192s' utente: '%-.48s' host: '%-.64s' (%-.64s)" - jpn "接続 %lld が中断されました。データベース: '%-.192s' ユーザー: '%-.48s' ホスト: '%-.64s' (%-.64s)" - nla "Afgebroken verbinding %lld naar db: '%-.192s' gebruiker: '%-.48s' host: '%-.64s' (%-.64s)" - por "Conexão %lld abortada para banco de dados '%-.192s' - usuário '%-.48s' - 'host' '%-.64s' ('%-.64s')" - rus "Прервано соединение %lld к базе данных '%-.192s' пользователя '%-.48s' с хоста '%-.64s' (%-.64s)" - serbian "Prekinuta konekcija broj %lld ka bazi: '%-.192s' korisnik je bio: '%-.48s' a host: '%-.64s' (%-.64s)" - spa "Abortada conexión %lld a la base de datos: '%-.192s' usuario: '%-.48s' equipo: '%-.64s' (%-.64s)" - swe "Avbröt länken för tråd %lld till db '%-.192s', användare '%-.48s', host '%-.64s' (%-.64s)" - ukr "Перервано з'єднання %lld до бази данних: '%-.192s' користувач: '%-.48s' хост: '%-.64s' (%-.64s)" + chi "终止的连接 %lld 到数据库: '%-.192s' 用户: '%-.48s' 主机: '%-.64s'%-.64s (%-.64s)" + cze "Spojení %lld do databáze: '%-.192s' uživatel: '%-.48s' stroj: '%-.64s'%-.64s (%-.64s) bylo přerušeno" + dan "Afbrød forbindelsen %lld til databasen '%-.192s' bruger: '%-.48s' vært: '%-.64s'%-.64s (%-.64s)" + eng "Aborted connection %lld to db: '%-.192s' user: '%-.48s' host: '%-.64s'%-.64s (%-.64s)" + est "Ühendus katkestatud %lld andmebaas: '%-.192s' kasutaja: '%-.48s' masin: '%-.64s'%-.64s (%-.64s)" + fre "Connection %lld avortée vers la bd: '%-.192s' utilisateur: '%-.48s' hôte: '%-.64s'%-.64s (%-.64s)" + ger "Abbruch der Verbindung %lld zur Datenbank '%-.192s'. Benutzer: '%-.48s', Host: '%-.64s'%-.64s (%-.64s)" + ita "Interrotta la connessione %lld al db: ''%-.192s' utente: '%-.48s' host: '%-.64s'%-.64s (%-.64s)" + jpn "接続 %lld が中断されました。データベース: '%-.192s' ユーザー: '%-.48s' ホスト: '%-.64s'%-.64s (%-.64s)" + nla "Afgebroken verbinding %lld naar db: '%-.192s' gebruiker: '%-.48s' host: '%-.64s'%-.64s (%-.64s)" + por "Conexão %lld abortada para banco de dados '%-.192s' - usuário '%-.48s' - 'host' '%-.64s'%-.64s ('%-.64s')" + rus "Прервано соединение %lld к базе данных '%-.192s' пользователя '%-.48s' с хоста '%-.64s'%-.64s (%-.64s)" + serbian "Prekinuta konekcija broj %lld ka bazi: '%-.192s' korisnik je bio: '%-.48s' a host: '%-.64s'%-.64s (%-.64s)" + spa "Abortada conexión %lld a la base de datos: '%-.192s' usuario: '%-.48s' equipo: '%-.64s'%-.64s (%-.64s)" + swe "Avbröt länken för tråd %lld till db '%-.192s', användare '%-.48s', host '%-.64s'%-.64s (%-.64s)" + ukr "Перервано з'єднання %lld до бази данних: '%-.192s' користувач: '%-.48s' хост: '%-.64s'%-.64s (%-.64s)" ER_UNUSED_10 eng "You should never see it" spa "Nunca lo debería vd de ver" diff --git a/sql/sql_class.h b/sql/sql_class.h index 0aa2aef72c2..29efb45e097 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5218,11 +5218,29 @@ public: { if (global_system_variables.log_warnings > threshold) { + char real_ip_str[64]; + real_ip_str[0]= 0; + + /* For proxied connections, add the real IP to the warning message */ + if (net.using_proxy_protocol && net.vio) + { + if(net.vio->localhost) + snprintf(real_ip_str, sizeof(real_ip_str), " real ip: 'localhost'"); + else + { + char buf[INET6_ADDRSTRLEN]; + if (!vio_getnameinfo((sockaddr *)&(net.vio->remote), buf, + sizeof(buf),NULL, 0, NI_NUMERICHOST)) + { + snprintf(real_ip_str, sizeof(real_ip_str), " real ip: '%s'",buf); + } + } + } Security_context *sctx= &main_security_ctx; sql_print_warning(ER_THD(this, ER_NEW_ABORTING_CONNECTION), thread_id, (db.str ? db.str : "unconnected"), sctx->user ? sctx->user : "unauthenticated", - sctx->host_or_ip, reason); + sctx->host_or_ip, real_ip_str, reason); } } diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 8878c722557..6149cc49ebb 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1274,7 +1274,7 @@ void prepare_new_connection_state(THD* thd) thd->thread_id, thd->db.str ? thd->db.str : "unconnected", sctx->user ? sctx->user : "unauthenticated", - sctx->host_or_ip, "init_connect command failed"); + sctx->host_or_ip, "", "init_connect command failed"); thd->server_status&= ~SERVER_STATUS_CLEAR_SET; thd->protocol->end_statement(); thd->killed = KILL_CONNECTION; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 8e2a431078a..4443319a3a9 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -20564,7 +20564,6 @@ typedef struct { #ifndef EMBEDDED_LIBRARY static void test_proxy_header_tcp(const char *ipaddr, int port) { - int rc; MYSQL_RES *result; int family = (strchr(ipaddr,':') == NULL)?AF_INET:AF_INET6; @@ -20639,6 +20638,11 @@ static void test_proxy_header_tcp(const char *ipaddr, int port) DIE_UNLESS(strncmp(row[0], normalized_addr, addrlen) == 0); DIE_UNLESS(atoi(row[0] + addrlen+1) == port); mysql_free_result(result); + if (i == 0 && !strcmp(ipaddr,"192.0.2.1")) + { + /* do "dirty" close, to get aborted message in error log.*/ + mariadb_cancel(m); + } mysql_close(m); } sprintf(query,"DROP USER 'u'@'%s'",normalized_addr); From 7bf3c3124ac129c3c36bcb6dcac248c225f439ee Mon Sep 17 00:00:00 2001 From: Denis Protivensky Date: Tue, 6 Feb 2024 11:55:04 +0300 Subject: [PATCH 101/106] MDEV-33136: Properly BF-abort user transactions with explicit locks User transactions may acquire explicit MDL locks from InnoDB level when persistent statistics is re-read for a table. If such a transaction would be subject to BF-abort, it was improperly detected as a system transaction and wouldn't get aborted. The fix: Check if a transaction holding explicit MDL locks is a user transaction in the MDL conflict handling code. Signed-off-by: Julius Goryavsky --- mysql-test/suite/galera/r/MDEV-33136.result | 21 ++++++++++ mysql-test/suite/galera/t/MDEV-33136.test | 44 +++++++++++++++++++++ sql/wsrep_mysqld.cc | 4 +- storage/innobase/dict/dict0stats.cc | 4 ++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/galera/r/MDEV-33136.result create mode 100644 mysql-test/suite/galera/t/MDEV-33136.test diff --git a/mysql-test/suite/galera/r/MDEV-33136.result b/mysql-test/suite/galera/r/MDEV-33136.result new file mode 100644 index 00000000000..36159fa05cd --- /dev/null +++ b/mysql-test/suite/galera/r/MDEV-33136.result @@ -0,0 +1,21 @@ +connection node_2; +connection node_1; +connect node_1a,127.0.0.1,root,,test,$NODE_MYPORT_1; +connection node_1; +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; +connection node_1a; +TRUNCATE TABLE t1; +SET SESSION wsrep_retry_autocommit = 0; +SET DEBUG_SYNC = 'dict_stats_mdl_acquired SIGNAL may_toi WAIT_FOR bf_abort'; +INSERT INTO t1 VALUES (1); +connection node_1; +SET DEBUG_SYNC = 'now WAIT_FOR may_toi'; +TRUNCATE TABLE t1; +connection node_1a; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +connection node_1; +SET DEBUG_SYNC = 'RESET'; +DROP TABLE t1; +disconnect node_1a; +disconnect node_2; +disconnect node_1; diff --git a/mysql-test/suite/galera/t/MDEV-33136.test b/mysql-test/suite/galera/t/MDEV-33136.test new file mode 100644 index 00000000000..12765ef6dfb --- /dev/null +++ b/mysql-test/suite/galera/t/MDEV-33136.test @@ -0,0 +1,44 @@ +# +# MDEV-33136: Properly BF-abort user transactions with explicit locks +# +# User transactions may acquire explicit MDL locks from InnoDB level +# when persistent statistics is re-read for a table. +# If such a transaction would be subject to BF-abort, it was improperly +# detected as a system transaction and wouldn't get aborted. +# +# The fix: Check if a transaction holding explicit MDL locks is a user +# transaction in the MDL conflict handling code. + +--source include/galera_cluster.inc +--source include/have_debug_sync.inc +--source include/have_debug.inc + +--connect node_1a,127.0.0.1,root,,test,$NODE_MYPORT_1 + +--connection node_1 +CREATE TABLE t1 (f1 INTEGER PRIMARY KEY) ENGINE=InnoDB; + +--connection node_1a +TRUNCATE TABLE t1; +# TRUNCATE forces the next statement to re-read statistics from persistent storage, +# which will acquire MDL locks on the statistics tables in InnoDB. +SET SESSION wsrep_retry_autocommit = 0; +SET DEBUG_SYNC = 'dict_stats_mdl_acquired SIGNAL may_toi WAIT_FOR bf_abort'; +--send + INSERT INTO t1 VALUES (1); + +--connection node_1 +SET DEBUG_SYNC = 'now WAIT_FOR may_toi'; +TRUNCATE TABLE t1; + +--connection node_1a +# Local INSERT gets aborted. +--error ER_LOCK_DEADLOCK +--reap + +# Cleanup +--connection node_1 +SET DEBUG_SYNC = 'RESET'; +DROP TABLE t1; +--disconnect node_1a +--source include/galera_end.inc diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index b77cf66f6c1..6d20f60b290 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -3168,7 +3168,9 @@ void wsrep_handle_mdl_conflict(MDL_context *requestor_ctx, } } else if (granted_thd->lex->sql_command == SQLCOM_FLUSH || - granted_thd->mdl_context.has_explicit_locks()) + /* System transactions with explicit locks are BACKUP. */ + (granted_thd->system_thread != NON_SYSTEM_THREAD && + granted_thd->mdl_context.has_explicit_locks())) { WSREP_DEBUG("BF thread waiting for FLUSH"); ticket->wsrep_report(wsrep_debug); diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index b54b66c251b..3d931c4a490 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -3865,6 +3865,10 @@ release_and_exit: goto release_and_exit; } +#ifdef ENABLED_DEBUG_SYNC + DEBUG_SYNC(thd, "dict_stats_mdl_acquired"); +#endif /* ENABLED_DEBUG_SYNC */ + trx = trx_create(); trx_start_internal_read_only(trx); From c5ac9836b3fb5eabd9857056f498cc3870cf6ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 29 Jan 2024 15:04:57 +0200 Subject: [PATCH 102/106] MDEV-33039 Galera test failure on mysql-wsrep-features#165 We should not set debug sync point when holding a mutex to avoid mutex ordering failure. Signed-off-by: Julius Goryavsky --- sql/service_wsrep.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc index 17240fd4fbd..06513387ac7 100644 --- a/sql/service_wsrep.cc +++ b/sql/service_wsrep.cc @@ -201,11 +201,11 @@ extern "C" void wsrep_handle_SR_rollback(THD *bf_thd, /* Note: do not store/reset globals before wsrep_bf_abort() call to avoid losing BF thd context. */ - mysql_mutex_lock(&victim_thd->LOCK_thd_data); if (!(bf_thd && bf_thd != victim_thd)) { DEBUG_SYNC(victim_thd, "wsrep_before_SR_rollback"); } + mysql_mutex_lock(&victim_thd->LOCK_thd_data); if (bf_thd) { wsrep_bf_abort(bf_thd, victim_thd); From ee2ed1a036891239c102eab108e0b9d8d641ede0 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 20 Mar 2024 16:30:11 +1100 Subject: [PATCH 103/106] Revert "MDEV-33636: RPM caps is on mariadbd exe" This was the orginal implementation that reverted with a bunch of commits. This reverts commit a13e521bc51d3ad9bb6e8e6481a0c8dea3b648a7. Revert "cmake: append to the array correctly" This reverts commit 51e3f1daf54309d14fe8db438024d88aa110e86a. Revert "build failure with cmake < 3.10" This reverts commit 49cf702ee54040cefcab67f6758c233a6370f5d0. Revert "MDEV-33301 memlock with systemd still not working" This reverts commit 8a1904d7825f9897cd237fc6a1d8a57a9f2108de. --- cmake/cpack_rpm.cmake | 8 ------ debian/mariadb-server-core-10.5.postinst | 26 ------------------- support-files/policy/apparmor/usr.sbin.mysqld | 1 - .../policy/selinux/mariadb-server.te | 4 +-- 4 files changed, 1 insertion(+), 38 deletions(-) delete mode 100644 debian/mariadb-server-core-10.5.postinst diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index 9383ae8c13b..65a739dc03e 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -164,7 +164,6 @@ SET(CPACK_RPM_server_USER_FILELIST "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*" "%config(noreplace) ${INSTALL_SYSCONFDIR}/logrotate.d/mysql" ) - SET(CPACK_RPM_common_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONFDIR}/my.cnf") SET(CPACK_RPM_shared_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*") SET(CPACK_RPM_client_USER_FILELIST ${ignored} "%config(noreplace) ${INSTALL_SYSCONF2DIR}/*") @@ -180,13 +179,6 @@ MACRO(SETA var) ENDFOREACH() ENDMACRO(SETA) -IF (CMAKE_VERSION VERSION_GREATER 3.10.0) - # cmake bug #14362 - SET(CPACK_RPM_server_USER_FILELIST ${CPACK_RPM_server_USER_FILELIST} - "%caps(cap_ipc_lock=pe) %{_sbindir}/mariadbd" - ) -ENDIF() - SETA(CPACK_RPM_client_PACKAGE_OBSOLETES "mysql-client" "MySQL-client" diff --git a/debian/mariadb-server-core-10.5.postinst b/debian/mariadb-server-core-10.5.postinst deleted file mode 100644 index 5f79bed2402..00000000000 --- a/debian/mariadb-server-core-10.5.postinst +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/sh - -set -e - -# inspired by iputils-ping -# -# cap_ipc_lock is required if a user wants to use --memlock -# and has insufficient RLIMIT_MEMLOCK (MDEV-33301) - -PROGRAM=$(dpkg-divert --truename /usr/sbin/mysqld) - -if [ "$1" = configure ]; then - # If we have setcap installed, try setting - # which allows us to install our binaries without the setuid - # bit. - if command -v setcap > /dev/null; then - if ! setcap cap_ipc_lock+ep "$PROGRAM"; then - echo "Setcap failed on $PROGRAM, required with --memlock if insufficent RLIMIT_MEMLOCK" >&2 - fi - fi -fi - - -#DEBHELPER# - -exit 0 diff --git a/support-files/policy/apparmor/usr.sbin.mysqld b/support-files/policy/apparmor/usr.sbin.mysqld index 732f4b3a97a..c60ecd28531 100644 --- a/support-files/policy/apparmor/usr.sbin.mysqld +++ b/support-files/policy/apparmor/usr.sbin.mysqld @@ -14,7 +14,6 @@ capability chown, capability dac_override, - capability ipc_lock, capability setgid, capability setuid, capability sys_rawio, diff --git a/support-files/policy/selinux/mariadb-server.te b/support-files/policy/selinux/mariadb-server.te index ba53c97d4a8..89846063506 100644 --- a/support-files/policy/selinux/mariadb-server.te +++ b/support-files/policy/selinux/mariadb-server.te @@ -25,7 +25,7 @@ require { class lnk_file read; class process { getattr signull }; class unix_stream_socket connectto; - class capability { ipc_lock sys_resource sys_nice }; + class capability { sys_resource sys_nice }; class tcp_socket { name_bind name_connect }; class file { execute setattr read create getattr execute_no_trans write ioctl open append unlink }; class sock_file { create unlink getattr }; @@ -87,8 +87,6 @@ allow mysqld_t bin_t:file { getattr read execute open execute_no_trans ioctl }; # MariaDB additions allow mysqld_t self:process setpgid; -allow mysqld_t self:capability { ipc_lock }; - # This rule allows port tcp/4444 allow mysqld_t kerberos_port_t:tcp_socket { name_bind name_connect }; # This rule allows port tcp/4567 (tram_port_t may not be available on From 76a27155b4cd8174e900577dd01df2db1327b120 Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Wed, 20 Mar 2024 18:25:21 +1100 Subject: [PATCH 104/106] MDEV-33301 memlock with systemd still not working .. even with MDEV-9095 fix CapabilityBounding sets require filesystem setcap attributes for the executable to gain privileges during execution. A side effect of this however is the getauxvec(AT_SECURE) gets set, and the secure_getenv from OpenSSL internals on OPENSSL_CONF environment variable will get ignored (openssl gh issue 21770). According to capabilities(7), Ambient capabilities don't trigger ld.so triggering the secure execution mode. Include SELinux and Apparmor capabilities for ipc_lock --- support-files/mariadb.service.in | 2 +- support-files/mariadb@.service.in | 2 +- support-files/policy/apparmor/usr.sbin.mysqld | 1 + support-files/policy/selinux/mariadb-server.te | 4 +++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/support-files/mariadb.service.in b/support-files/mariadb.service.in index ee5b5ddc427..dce845a9f72 100644 --- a/support-files/mariadb.service.in +++ b/support-files/mariadb.service.in @@ -51,7 +51,7 @@ Group=mysql # CAP_DAC_OVERRIDE To allow auth_pam_tool (which is SUID root) to read /etc/shadow when it's chmod 0 # does nothing for non-root, not needed if /etc/shadow is u+r # CAP_AUDIT_WRITE auth_pam_tool needs it on Debian for whatever reason -CapabilityBoundingSet=CAP_IPC_LOCK CAP_DAC_OVERRIDE CAP_AUDIT_WRITE +AmbientCapabilities=CAP_IPC_LOCK CAP_DAC_OVERRIDE CAP_AUDIT_WRITE # PrivateDevices=true implies NoNewPrivileges=true and # SUID auth_pam_tool suddenly doesn't do setuid anymore diff --git a/support-files/mariadb@.service.in b/support-files/mariadb@.service.in index a2a73b41e3e..b53711ef7e0 100644 --- a/support-files/mariadb@.service.in +++ b/support-files/mariadb@.service.in @@ -181,7 +181,7 @@ PrivateNetwork=false # CAP_DAC_OVERRIDE To allow auth_pam_tool (which is SUID root) to read /etc/shadow when it's chmod 0 # does nothing for non-root, not needed if /etc/shadow is u+r # CAP_AUDIT_WRITE auth_pam_tool needs it on Debian for whatever reason -CapabilityBoundingSet=CAP_IPC_LOCK CAP_DAC_OVERRIDE CAP_AUDIT_WRITE +AmbientCapabilities=CAP_IPC_LOCK CAP_DAC_OVERRIDE CAP_AUDIT_WRITE # PrivateDevices=true implies NoNewPrivileges=true and # SUID auth_pam_tool suddenly doesn't do setuid anymore diff --git a/support-files/policy/apparmor/usr.sbin.mysqld b/support-files/policy/apparmor/usr.sbin.mysqld index c60ecd28531..732f4b3a97a 100644 --- a/support-files/policy/apparmor/usr.sbin.mysqld +++ b/support-files/policy/apparmor/usr.sbin.mysqld @@ -14,6 +14,7 @@ capability chown, capability dac_override, + capability ipc_lock, capability setgid, capability setuid, capability sys_rawio, diff --git a/support-files/policy/selinux/mariadb-server.te b/support-files/policy/selinux/mariadb-server.te index 89846063506..ba53c97d4a8 100644 --- a/support-files/policy/selinux/mariadb-server.te +++ b/support-files/policy/selinux/mariadb-server.te @@ -25,7 +25,7 @@ require { class lnk_file read; class process { getattr signull }; class unix_stream_socket connectto; - class capability { sys_resource sys_nice }; + class capability { ipc_lock sys_resource sys_nice }; class tcp_socket { name_bind name_connect }; class file { execute setattr read create getattr execute_no_trans write ioctl open append unlink }; class sock_file { create unlink getattr }; @@ -87,6 +87,8 @@ allow mysqld_t bin_t:file { getattr read execute open execute_no_trans ioctl }; # MariaDB additions allow mysqld_t self:process setpgid; +allow mysqld_t self:capability { ipc_lock }; + # This rule allows port tcp/4444 allow mysqld_t kerberos_port_t:tcp_socket { name_bind name_connect }; # This rule allows port tcp/4567 (tram_port_t may not be available on From 58df20974b56c676333fdc36c39a38ac130c9eb4 Mon Sep 17 00:00:00 2001 From: Dave Gosselin Date: Wed, 13 Mar 2024 16:56:37 -0400 Subject: [PATCH 105/106] MDEV-33460 select '123' 'x'; unexpected result Queries that select concatenated constant strings now have colname and value that match. For example, SELECT '123' 'x'; will return a result where the column name and value both are '123x'. Review: Daniel Black --- mysql-test/main/empty_string_literal.result | 25 ++++++++++++++++--- mysql-test/main/empty_string_literal.test | 12 +++++++++ mysql-test/main/func_str.result | 2 +- mysql-test/main/join.result | 2 +- .../oracle/r/empty_string_literal.result | 6 ++--- sql/item.cc | 1 + 6 files changed, 40 insertions(+), 8 deletions(-) diff --git a/mysql-test/main/empty_string_literal.result b/mysql-test/main/empty_string_literal.result index 49153d68fa5..569b9d5e9ca 100644 --- a/mysql-test/main/empty_string_literal.result +++ b/mysql-test/main/empty_string_literal.result @@ -64,7 +64,7 @@ SET sql_mode=@mode; # Test litteral concat # SELECT 'a' 'b'; -a +ab ab SELECT 'a' ''; a @@ -76,13 +76,13 @@ SELECT '' ''; NULL NULL SELECT '' 'b' 'c'; -b +bc bc SELECT '' '' 'c'; c c SELECT 'a' '' 'c'; -a +ac ac SELECT 'a' '' ''; a @@ -208,3 +208,22 @@ t1 CREATE TABLE `t1` ( KEY `a` (`a`,`b`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci drop table t1; +# +# MDEV-33460 select '123' 'x'; unexpected result +# +SELECT ''; +NULL +NULL +SELECT '' 'b' 'c'; +bc +bc +SELECT '' '' 'c'; +c +c +SELECT 'a' '' 'c'; +ac +ac +SELECT 'a' '' ''; +a +a +# End of 10.5 test diff --git a/mysql-test/main/empty_string_literal.test b/mysql-test/main/empty_string_literal.test index 9174a7714a2..3320841fb42 100644 --- a/mysql-test/main/empty_string_literal.test +++ b/mysql-test/main/empty_string_literal.test @@ -25,3 +25,15 @@ flush tables; update t1 set a = 2; show create table t1; drop table t1; + +--echo # +--echo # MDEV-33460 select '123' 'x'; unexpected result +--echo # + +SELECT ''; +SELECT '' 'b' 'c'; +SELECT '' '' 'c'; +SELECT 'a' '' 'c'; +SELECT 'a' '' ''; + +--echo # End of 10.5 test diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result index a47c149fb0d..c071b92318a 100644 --- a/mysql-test/main/func_str.result +++ b/mysql-test/main/func_str.result @@ -8,7 +8,7 @@ select 'hello',"'hello'",'""hello""','''h''e''l''l''o''',"hel""lo",'hel\'lo'; hello 'hello' ""hello"" 'h'e'l'l'o' hel"lo hel'lo hello 'hello' ""hello"" 'h'e'l'l'o' hel"lo hel'lo select 'hello' 'monty'; -hello +hellomonty hellomonty select length('\n\t\r\b\0\_\%\\'); length('\n\t\r\b\0\_\%\\') diff --git a/mysql-test/main/join.result b/mysql-test/main/join.result index 07579a065f9..ecc64b5f343 100644 --- a/mysql-test/main/join.result +++ b/mysql-test/main/join.result @@ -894,7 +894,7 @@ show status like '%cost%'; Variable_name Value Last_query_cost 4.016090 select 'The cost of accessing t1 (dont care if it changes' '^'; -The cost of accessing t1 (dont care if it changes +The cost of accessing t1 (dont care if it changes^ The cost of accessing t1 (dont care if it changes^ select 'vv: Following query must use ALL(t1), eq_ref(A), eq_ref(B): vv' Z; Z diff --git a/mysql-test/suite/compat/oracle/r/empty_string_literal.result b/mysql-test/suite/compat/oracle/r/empty_string_literal.result index 4fac736367b..a84cc81b38c 100644 --- a/mysql-test/suite/compat/oracle/r/empty_string_literal.result +++ b/mysql-test/suite/compat/oracle/r/empty_string_literal.result @@ -64,7 +64,7 @@ SET sql_mode=@mode; # Test litteral concat # SELECT 'a' 'b'; -a +ab ab SELECT 'a' ''; a @@ -76,13 +76,13 @@ SELECT '' ''; NULL NULL SELECT '' 'b' 'c'; -b +bc bc SELECT '' '' 'c'; c c SELECT 'a' '' 'c'; -a +ac ac SELECT 'a' '' ''; a diff --git a/sql/item.cc b/sql/item.cc index 0e5ed30cb91..99df4e65ac1 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6943,6 +6943,7 @@ Item_basic_constant * Item_string::make_string_literal_concat(THD *thd, const LEX_CSTRING *str) { append(str->str, (uint32) str->length); + set_name(thd, &str_value); if (!(collation.repertoire & MY_REPERTOIRE_EXTENDED)) { // If the string has been pure ASCII so far, check the new part. From 0fc123c595cd0b61ec852800012b837858e2784f Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Wed, 27 Mar 2024 15:22:58 +0400 Subject: [PATCH 106/106] MDEV-33772 Bad SEPARATOR value in GROUP_CONCAT on character set conversion Item_func_group_concat::print() did not take into account that Item_func_group_concat::separator can be of a different character set than the "String *str" (when the printing is being done to). Therefore, printing did not work correctly for: - non-ASCII separators when GROUP_CONCAT is done on 8bit data or multi-byte data with mbminlen==1. - all separators (even including simple ones like comma) when GROUP_CONCAT is done on ucs2/utf16/utf32 data (mbminlen>1). Because of this problem, VIEW definitions did not print correctly to their FRM files. This later led to a wrong SELECT and SHOW CREATE output. Fix: - Adding new String methods: bool append_for_single_quote_using_mb_wc(const char *str, size_t length, CHARSET_INFO *cs); bool append_for_single_quote_opt_convert(const char *str, size_t length, CHARSET_INFO *cs) which perform both escaping and character set conversion at the same time. - Adding a new String method escaped_wc_for_single_quote(), to reuse the code between the old and the new methods. - Fixing Item_func_group_concat::print() to use the new method append_for_single_quote_opt_convert(). --- mysql-test/main/ctype_ucs.result | 20 ++++++++++++ mysql-test/main/ctype_ucs.test | 17 +++++++++++ mysql-test/main/func_gconcat.result | 20 ++++++++++++ mysql-test/main/func_gconcat.test | 16 ++++++++++ sql/item_sum.cc | 2 +- sql/sql_string.cc | 47 ++++++++++++++++++++--------- sql/sql_string.h | 36 ++++++++++++++++++++++ 7 files changed, 143 insertions(+), 15 deletions(-) diff --git a/mysql-test/main/ctype_ucs.result b/mysql-test/main/ctype_ucs.result index eb1220f9a56..8f747dfd51e 100644 --- a/mysql-test/main/ctype_ucs.result +++ b/mysql-test/main/ctype_ucs.result @@ -6520,5 +6520,25 @@ SELECT 1 COLLATE latin1_swedish_ci; ERROR 42000: COLLATION 'latin1_swedish_ci' is not valid for CHARACTER SET 'ucs2' SET NAMES utf8; # +# MDEV-33772 Bad SEPARATOR value in GROUP_CONCAT on character set conversion +# +SET NAMES utf8mb3, @@collation_connection=ucs2_general_ci; +CREATE TABLE t1 (c VARCHAR(10)) CHARACTER SET ucs2; +INSERT INTO t1 VALUES ('a'),('A'); +CREATE OR REPLACE VIEW v1 AS +SELECT COUNT(*) AS cnt, GROUP_CONCAT(c) AS c1 FROM t1 GROUP BY c; +SELECT * FROM v1; +cnt c1 +2 a,A +SELECT HEX(c1) FROM v1; +HEX(c1) +0061002C0041 +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select count(0) AS `cnt`,group_concat(`t1`.`c` separator ',') AS `c1` from `t1` group by `t1`.`c` utf8 ucs2_general_ci +DROP VIEW v1; +DROP TABLE t1; +SET NAMES utf8mb3; +# # End of 10.5 tests # diff --git a/mysql-test/main/ctype_ucs.test b/mysql-test/main/ctype_ucs.test index 3df155c0f9d..f2fcee1dbb4 100644 --- a/mysql-test/main/ctype_ucs.test +++ b/mysql-test/main/ctype_ucs.test @@ -1189,6 +1189,23 @@ SELECT HEX(1 COLLATE ucs2_bin); SELECT 1 COLLATE latin1_swedish_ci; SET NAMES utf8; +--echo # +--echo # MDEV-33772 Bad SEPARATOR value in GROUP_CONCAT on character set conversion +--echo # + +SET NAMES utf8mb3, @@collation_connection=ucs2_general_ci; +CREATE TABLE t1 (c VARCHAR(10)) CHARACTER SET ucs2; +INSERT INTO t1 VALUES ('a'),('A'); +CREATE OR REPLACE VIEW v1 AS + SELECT COUNT(*) AS cnt, GROUP_CONCAT(c) AS c1 FROM t1 GROUP BY c; +SELECT * FROM v1; +SELECT HEX(c1) FROM v1; +SHOW CREATE VIEW v1; +DROP VIEW v1; +DROP TABLE t1; +SET NAMES utf8mb3; + + --echo # --echo # End of 10.5 tests --echo # diff --git a/mysql-test/main/func_gconcat.result b/mysql-test/main/func_gconcat.result index 7bc6441661b..e922134a9da 100644 --- a/mysql-test/main/func_gconcat.result +++ b/mysql-test/main/func_gconcat.result @@ -1517,4 +1517,24 @@ deallocate prepare stmt; set join_cache_level=default; set group_concat_max_len=default; drop table t1,t2; +# +# MDEV-33772 Bad SEPARATOR value in GROUP_CONCAT on character set conversion +# +SET NAMES utf8, @@collation_connection=latin1_swedish_ci; +CREATE TABLE t1 (c VARCHAR(10)) CHARACTER SET latin1; +INSERT INTO t1 VALUES ('a'),('A'); +CREATE OR REPLACE VIEW v1 AS +SELECT GROUP_CONCAT(c SEPARATOR 'ß') AS c1 FROM t1 GROUP BY c; +SELECT * FROM v1; +c1 +aßA +SELECT HEX(c1) FROM v1; +HEX(c1) +61DF41 +SHOW CREATE VIEW v1; +View Create View character_set_client collation_connection +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select group_concat(`t1`.`c` separator 'ß') AS `c1` from `t1` group by `t1`.`c` utf8 latin1_swedish_ci +DROP VIEW v1; +DROP TABLE t1; +SET NAMES latin1; # End of 10.5 tests diff --git a/mysql-test/main/func_gconcat.test b/mysql-test/main/func_gconcat.test index 2e09bddbb8b..c9787ce4471 100644 --- a/mysql-test/main/func_gconcat.test +++ b/mysql-test/main/func_gconcat.test @@ -1105,4 +1105,20 @@ set group_concat_max_len=default; drop table t1,t2; +--echo # +--echo # MDEV-33772 Bad SEPARATOR value in GROUP_CONCAT on character set conversion +--echo # + +SET NAMES utf8, @@collation_connection=latin1_swedish_ci; +CREATE TABLE t1 (c VARCHAR(10)) CHARACTER SET latin1; +INSERT INTO t1 VALUES ('a'),('A'); +CREATE OR REPLACE VIEW v1 AS + SELECT GROUP_CONCAT(c SEPARATOR 'ß') AS c1 FROM t1 GROUP BY c; +SELECT * FROM v1; +SELECT HEX(c1) FROM v1; +SHOW CREATE VIEW v1; +DROP VIEW v1; +DROP TABLE t1; +SET NAMES latin1; + --echo # End of 10.5 tests diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 7f39efe6c9a..4cf403c1618 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -4587,7 +4587,7 @@ void Item_func_group_concat::print(String *str, enum_query_type query_type) if (sum_func() == GROUP_CONCAT_FUNC) { str->append(STRING_WITH_LEN(" separator \'")); - str->append_for_single_quote(separator->ptr(), separator->length()); + str->append_for_single_quote_opt_convert(*separator); str->append(STRING_WITH_LEN("\'")); } diff --git a/sql/sql_string.cc b/sql/sql_string.cc index b723ac5db66..cf1ed210ca3 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -1126,26 +1126,45 @@ bool String::append_for_single_quote(const char *st, size_t len) int chlen; for (; st < end; st++) { - switch (*st) + char ch2= (char) (uchar) escaped_wc_for_single_quote((uchar) *st); + if (ch2) { - case '\\': APPEND(STRING_WITH_LEN("\\\\")); break; - case '\0': APPEND(STRING_WITH_LEN("\\0")); break; - case '\'': APPEND(STRING_WITH_LEN("\\'")); break; - case '\n': APPEND(STRING_WITH_LEN("\\n")); break; - case '\r': APPEND(STRING_WITH_LEN("\\r")); break; - case '\032': APPEND(STRING_WITH_LEN("\\Z")); break; - default: if ((chlen=charset()->charlen(st, end)) > 0) - { - APPEND(st, chlen); - st+= chlen-1; - } - else - APPEND(*st); + if (append('\\') || append(ch2)) + return true; + continue; } + if ((chlen= charset()->charlen(st, end)) > 0) + { + APPEND(st, chlen); + st+= chlen-1; + } + else + APPEND(*st); } return 0; } + +bool String::append_for_single_quote_using_mb_wc(const char *src, + size_t length, + CHARSET_INFO *cs) +{ + DBUG_ASSERT(&my_charset_bin != charset()); + DBUG_ASSERT(&my_charset_bin != cs); + const uchar *str= (const uchar *) src; + const uchar *end= (const uchar *) src + length; + int chlen; + my_wc_t wc; + for ( ; (chlen= cs->cset->mb_wc(cs, &wc, str, end)) > 0; str+= chlen) + { + my_wc_t wc2= escaped_wc_for_single_quote(wc); + if (wc2 ? (append_wc('\\') || append_wc(wc2)) : append_wc(wc)) + return true; + } + return false; +} + + void String::print(String *str) const { str->append_for_single_quote(Ptr, str_length); diff --git a/sql/sql_string.h b/sql/sql_string.h index 13820329750..3dbeb7b83cf 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -1134,6 +1134,42 @@ public: print_with_conversion(to, cs); } + static my_wc_t escaped_wc_for_single_quote(my_wc_t ch) + { + switch (ch) + { + case '\\': return '\\'; + case '\0': return '0'; + case '\'': return '\''; + case '\n': return 'n'; + case '\r': return 'r'; + case '\032': return 'Z'; + } + return 0; + } + + // Append for single quote using mb_wc/wc_mb Unicode conversion + bool append_for_single_quote_using_mb_wc(const char *str, size_t length, + CHARSET_INFO *cs); + + // Append for single quote with optional mb_wc/wc_mb conversion + bool append_for_single_quote_opt_convert(const char *str, + size_t length, + CHARSET_INFO *cs) + { + return charset() == &my_charset_bin || cs == &my_charset_bin || + my_charset_same(charset(), cs) ? + append_for_single_quote(str, length) : + append_for_single_quote_using_mb_wc(str, length, cs); + } + + bool append_for_single_quote_opt_convert(const String &str) + { + return append_for_single_quote_opt_convert(str.ptr(), + str.length(), + str.charset()); + } + bool append_for_single_quote(const char *st, size_t len); bool append_for_single_quote(const String *s) {