diff options
author | Sergei Petrunia <psergey@askmonty.org> | 2015-04-15 12:09:25 -0700 |
---|---|---|
committer | Sergei Petrunia <psergey@askmonty.org> | 2015-04-15 12:09:25 -0700 |
commit | c712b376d8189b963851db86a0bedd478aab869e (patch) | |
tree | 8d02a74357f8ba77261d79bd70ca6174e0fe5dd8 | |
parent | 25da74ce3f17a4720f4f7f06b1d694ff417d6b60 (diff) | |
parent | d051f6c36beaf6c7ea269d6c174cca7482f3e823 (diff) | |
download | mariadb-git-bb-10.1-explain-analyze.tar.gz |
Merge branch '10.1' into bb-10.1-explain-analyzebb-10.1-explain-analyze
-rw-r--r-- | debian/dist/Debian/control | 2 | ||||
-rw-r--r-- | debian/dist/Ubuntu/control | 2 | ||||
-rw-r--r-- | mysql-test/include/mtr_warnings.sql | 6 | ||||
-rwxr-xr-x | mysql-test/mysql-test-run.pl | 6 | ||||
-rw-r--r-- | mysql-test/r/create_drop_binlog.result | 2 | ||||
-rw-r--r-- | mysql-test/r/create_drop_view.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_create_drop_view.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_parallel_multilevel2.result | 52 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_parallel_temptable.result | 46 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf | 17 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test | 80 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_parallel_temptable.test | 47 | ||||
-rw-r--r-- | sql/opt_range.cc | 50 | ||||
-rw-r--r-- | sql/opt_range.h | 1 | ||||
-rw-r--r-- | sql/slave.cc | 20 | ||||
-rw-r--r-- | sql/sql_base.cc | 124 | ||||
-rw-r--r-- | sql/sql_base.h | 4 | ||||
-rw-r--r-- | sql/sql_explain.cc | 2 | ||||
-rw-r--r-- | sql/sql_table.cc | 4 | ||||
-rw-r--r-- | sql/sql_view.cc | 2 | ||||
-rw-r--r-- | sql/wsrep_sst.cc | 10 |
21 files changed, 413 insertions, 68 deletions
diff --git a/debian/dist/Debian/control b/debian/dist/Debian/control index 3ef1ee6fde7..9e8091f7158 100644 --- a/debian/dist/Debian/control +++ b/debian/dist/Debian/control @@ -195,7 +195,7 @@ Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-10.1 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-10.1 (>= ${binary:Version}), - galera (>=25.2), rsync, lsof, grep, gawk, iproute, + galera-3 (>=25.3), rsync, lsof, grep, gawk, iproute, coreutils, bsdutils, findutils, tar Provides: mariadb-server, mysql-server, virtual-mysql-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), diff --git a/debian/dist/Ubuntu/control b/debian/dist/Ubuntu/control index 2f86d671cae..1c555ecef30 100644 --- a/debian/dist/Ubuntu/control +++ b/debian/dist/Ubuntu/control @@ -189,7 +189,7 @@ Pre-Depends: mariadb-common, adduser (>= 3.40), debconf Depends: mariadb-client-10.1 (>= ${source:Version}), libdbi-perl, perl (>= 5.6), ${shlibs:Depends}, ${misc:Depends}, psmisc, passwd, lsb-base (>= 3.0-10), mariadb-server-core-10.1 (>= ${binary:Version}), - galera (>=25.2), rsync, lsof, grep, gawk, iproute, + galera-3 (>=25.3), rsync, lsof, grep, gawk, iproute, coreutils, bsdutils, findutils, tar Provides: mariadb-server, mysql-server, virtual-mysql-server Conflicts: mariadb-server (<< ${source:Version}), mysql-server (<< ${source:Version}), diff --git a/mysql-test/include/mtr_warnings.sql b/mysql-test/include/mtr_warnings.sql index fd59bf3c5f4..bc310fe0719 100644 --- a/mysql-test/include/mtr_warnings.sql +++ b/mysql-test/include/mtr_warnings.sql @@ -223,6 +223,12 @@ INSERT INTO global_suppressions VALUES ("Slave I/O: Notifying master by SET @master_binlog_checksum= @@global.binlog_checksum failed with error.*"), ("Slave I/O: Setting master-side filtering of @@skip_replication failed with error:.*"), ("Slave I/O: Setting @mariadb_slave_capability failed with error:.*"), + ("Slave I/O: Get master @@GLOBAL.gtid_domain_id failed with error.*"), + ("Slave I/O: Setting @slave_connect_state failed with error.*"), + ("Slave I/O: Setting @slave_gtid_strict_mode failed with error.*"), + ("Slave I/O: Setting @slave_gtid_ignore_duplicates failed with error.*"), + ("Slave I/O: Setting @slave_until_gtid failed with error.*"), + ("Slave I/O: Get master GTID position failed with error.*"), ("THE_LAST_SUPPRESSION")|| diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 305ab46e106..12611f387b1 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -4406,6 +4406,12 @@ sub extract_warning_lines ($$) { qr/Slave I\/O: Get master clock failed with error:.*/, qr/Slave I\/O: Get master COLLATION_SERVER failed with error:.*/, qr/Slave I\/O: Get master TIME_ZONE failed with error:.*/, + qr/Slave I\/O: Get master \@\@GLOBAL.gtid_domain_id failed with error:.*/, + qr/Slave I\/O: Setting \@slave_connect_state failed with error:.*/, + qr/Slave I\/O: Setting \@slave_gtid_strict_mode failed with error:.*/, + qr/Slave I\/O: Setting \@slave_gtid_ignore_duplicates failed with error:.*/, + qr/Slave I\/O: Setting \@slave_until_gtid failed with error:.*/, + qr/Slave I\/O: Get master GTID position failed with error:.*/, qr/Slave I\/O: error reconnecting to master '.*' - retry-time: [1-3] retries/, qr/Slave I\/0: Master command COM_BINLOG_DUMP failed/, qr/Error reading packet/, diff --git a/mysql-test/r/create_drop_binlog.result b/mysql-test/r/create_drop_binlog.result index 6db54a6997a..a1108890208 100644 --- a/mysql-test/r/create_drop_binlog.result +++ b/mysql-test/r/create_drop_binlog.result @@ -156,7 +156,7 @@ DROP VIEW v1; CREATE VIEW IF NOT EXISTS v1 AS SELECT 1; CREATE VIEW IF NOT EXISTS v1 AS SELECT 1; Warnings: -Note 1050 Table 'test' already exists +Note 1050 Table 'v1' already exists DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v1; Warnings: diff --git a/mysql-test/r/create_drop_view.result b/mysql-test/r/create_drop_view.result index fa54463f51f..a822c16ae3c 100644 --- a/mysql-test/r/create_drop_view.result +++ b/mysql-test/r/create_drop_view.result @@ -19,7 +19,7 @@ VIEW_DEFINITION select `test`.`t1`.`id` AS `id` from `test`.`t1` where (`test`.`t1`.`id` > 10) CREATE VIEW IF NOT EXISTS v1 AS SELECT * FROM t1 WHERE id>12; Warnings: -Note 1050 Table 'test' already exists +Note 1050 Table 'v1' already exists SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME='v1'; VIEW_DEFINITION select `test`.`t1`.`id` AS `id` from `test`.`t1` where (`test`.`t1`.`id` > 10) diff --git a/mysql-test/suite/rpl/r/rpl_create_drop_view.result b/mysql-test/suite/rpl/r/rpl_create_drop_view.result index 1fc30c2e89d..85731210ae8 100644 --- a/mysql-test/suite/rpl/r/rpl_create_drop_view.result +++ b/mysql-test/suite/rpl/r/rpl_create_drop_view.result @@ -30,7 +30,7 @@ CREATE VIEW v1 AS SELECT * FROM t1 WHERE id>10; ERROR 42S01: Table 'v1' already exists CREATE VIEW IF NOT EXISTS v1 AS SELECT * FROM t1 WHERE id>10; Warnings: -Note 1050 Table 'test' already exists +Note 1050 Table 'v1' already exists CREATE OR REPLACE VIEW IF NOT EXISTS v1 AS SELECT * FROM t1 WHERE id>10; ERROR HY000: Incorrect usage of OR REPLACE and IF NOT EXISTS # Syncing slave with master diff --git a/mysql-test/suite/rpl/r/rpl_parallel_multilevel2.result b/mysql-test/suite/rpl/r/rpl_parallel_multilevel2.result new file mode 100644 index 00000000000..47bf2ff887f --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_parallel_multilevel2.result @@ -0,0 +1,52 @@ +include/rpl_init.inc [topology=1->2->3] +*** MDEV-7668: Intermediate master groups CREATE with INSERT, causing parallel replication failure *** +SET @old_updates= @@GLOBAL.binlog_direct_non_transactional_updates; +SET GLOBAL binlog_direct_non_transactional_updates=OFF; +SET SESSION binlog_direct_non_transactional_updates=OFF; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +include/stop_slave.inc +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=10; +SET @old_commit_count=@@GLOBAL.binlog_commit_wait_count; +SET GLOBAL binlog_commit_wait_count=2; +SET @old_commit_usec=@@GLOBAL.binlog_commit_wait_usec; +SET GLOBAL binlog_commit_wait_usec=2000000; +SET @old_updates= @@GLOBAL.binlog_direct_non_transactional_updates; +SET GLOBAL binlog_direct_non_transactional_updates=OFF; +SET SESSION binlog_direct_non_transactional_updates=OFF; +CHANGE MASTER TO master_use_gtid=current_pos; +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; +CHANGE MASTER TO master_use_gtid=current_pos; +BEGIN; +CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY) ENGINE=MEMORY; +COMMIT; +INSERT INTO t2 VALUES (1); +INSERT INTO t1 SELECT a, a*10 FROM t2; +DROP TABLE t2; +include/save_master_gtid.inc +include/start_slave.inc +include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +a b +1 10 +include/start_slave.inc +include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; +a b +1 10 +include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +SET GLOBAL binlog_commit_wait_count=@old_commit_count; +SET GLOBAL binlog_commit_wait_usec=@old_commit_usec; +SET GLOBAL binlog_direct_non_transactional_updates= @old_updates; +include/start_slave.inc +include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +include/start_slave.inc +SET GLOBAL binlog_direct_non_transactional_updates= @old_updates; +CALL mtr.add_suppression("Statement accesses nontransactional table as well as transactional or temporary table"); +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_parallel_temptable.result b/mysql-test/suite/rpl/r/rpl_parallel_temptable.result index 61eba2cab2f..7bcd0293289 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel_temptable.result +++ b/mysql-test/suite/rpl/r/rpl_parallel_temptable.result @@ -116,6 +116,52 @@ SHOW STATUS LIKE 'Slave_open_temp_tables'; Variable_name Value Slave_open_temp_tables 0 FLUSH LOGS; +*** MDEV-7936: Assertion `!table || table->in_use == _current_thd()' failed on parallel replication in optimistic mode *** +CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB; +SET @old_dbug= @@SESSION.debug_dbug; +SET SESSION debug_dbug="+d,binlog_force_commit_id"; +SET @commit_id= 10000; +INSERT INTO t4 VALUES (30); +INSERT INTO t4 VALUES (31); +SET SESSION debug_dbug= @old_dbug; +INSERT INTO t1 SELECT a, "conservative" FROM t4; +DROP TEMPORARY TABLE t4; +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; +a b +30 conservative +31 conservative +include/save_master_pos.inc +include/sync_with_master_gtid.inc +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; +a b +30 conservative +31 conservative +include/stop_slave.inc +SET @old_mode= @@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode=optimistic; +CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t4 VALUES (32); +INSERT INTO t4 VALUES (33); +INSERT INTO t1 SELECT a, "optimistic" FROM t4; +DROP TEMPORARY TABLE t4; +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; +a b +30 conservative +31 conservative +32 optimistic +33 optimistic +include/save_master_pos.inc +include/start_slave.inc +include/sync_with_master_gtid.inc +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; +a b +30 conservative +31 conservative +32 optimistic +33 optimistic +include/stop_slave.inc +SET GLOBAL slave_parallel_mode=@old_mode; +include/start_slave.inc include/stop_slave.inc SET GLOBAL slave_parallel_threads=@old_parallel_threads; include/start_slave.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf new file mode 100644 index 00000000000..4e1d3878f03 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf @@ -0,0 +1,17 @@ +!include ../my.cnf + +[mysqld.1] +log-slave-updates +loose-innodb + +[mysqld.2] +log-slave-updates +loose-innodb + +[mysqld.3] +log-slave-updates +loose-innodb + +[ENV] +SERVER_MYPORT_3= @mysqld.3.port +SERVER_MYSOCK_3= @mysqld.3.socket diff --git a/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test new file mode 100644 index 00000000000..4125394ef80 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test @@ -0,0 +1,80 @@ +--source include/have_innodb.inc +--let $rpl_topology=1->2->3 +--source include/rpl_init.inc + +--echo *** MDEV-7668: Intermediate master groups CREATE with INSERT, causing parallel replication failure *** + +--connection server_1 +SET @old_updates= @@GLOBAL.binlog_direct_non_transactional_updates; +SET GLOBAL binlog_direct_non_transactional_updates=OFF; +SET SESSION binlog_direct_non_transactional_updates=OFF; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB; +--save_master_pos + +--connection server_2 +--sync_with_master +--save_master_pos +--source include/stop_slave.inc +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +SET GLOBAL slave_parallel_threads=10; +SET @old_commit_count=@@GLOBAL.binlog_commit_wait_count; +SET GLOBAL binlog_commit_wait_count=2; +SET @old_commit_usec=@@GLOBAL.binlog_commit_wait_usec; +SET GLOBAL binlog_commit_wait_usec=2000000; +SET @old_updates= @@GLOBAL.binlog_direct_non_transactional_updates; +SET GLOBAL binlog_direct_non_transactional_updates=OFF; +SET SESSION binlog_direct_non_transactional_updates=OFF; +CHANGE MASTER TO master_use_gtid=current_pos; + +--connection server_3 +--sync_with_master +--save_master_pos +SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=10; +CHANGE MASTER TO master_use_gtid=current_pos; + + +--connection server_1 + +BEGIN; +CREATE TEMPORARY TABLE t2 (a INT PRIMARY KEY) ENGINE=MEMORY; +COMMIT; +INSERT INTO t2 VALUES (1); +INSERT INTO t1 SELECT a, a*10 FROM t2; +DROP TABLE t2; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + +--connection server_3 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc +SELECT * FROM t1 ORDER BY a; + + +# Clean up + +--connection server_2 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +SET GLOBAL binlog_commit_wait_count=@old_commit_count; +SET GLOBAL binlog_commit_wait_usec=@old_commit_usec; +SET GLOBAL binlog_direct_non_transactional_updates= @old_updates; +--source include/start_slave.inc + +--connection server_3 +--source include/stop_slave.inc +SET GLOBAL slave_parallel_threads=@old_parallel_threads; +--source include/start_slave.inc + +--connection server_1 +SET GLOBAL binlog_direct_non_transactional_updates= @old_updates; +CALL mtr.add_suppression("Statement accesses nontransactional table as well as transactional or temporary table"); +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_parallel_temptable.test b/mysql-test/suite/rpl/t/rpl_parallel_temptable.test index b13fa5a01b1..979d613b187 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel_temptable.test +++ b/mysql-test/suite/rpl/t/rpl_parallel_temptable.test @@ -213,6 +213,53 @@ SHOW STATUS LIKE 'Slave_open_temp_tables'; FLUSH LOGS; +--echo *** MDEV-7936: Assertion `!table || table->in_use == _current_thd()' failed on parallel replication in optimistic mode *** + +--connection server_1 +CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB; +SET @old_dbug= @@SESSION.debug_dbug; +SET SESSION debug_dbug="+d,binlog_force_commit_id"; +SET @commit_id= 10000; +INSERT INTO t4 VALUES (30); +INSERT INTO t4 VALUES (31); +SET SESSION debug_dbug= @old_dbug; +INSERT INTO t1 SELECT a, "conservative" FROM t4; +DROP TEMPORARY TABLE t4; +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; +--source include/save_master_pos.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; + +--source include/stop_slave.inc +SET @old_mode= @@GLOBAL.slave_parallel_mode; +SET GLOBAL slave_parallel_mode=optimistic; + +--connection server_1 +CREATE TEMPORARY TABLE t4 (a INT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO t4 VALUES (32); +INSERT INTO t4 VALUES (33); +INSERT INTO t1 SELECT a, "optimistic" FROM t4; +DROP TEMPORARY TABLE t4; + +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; +--source include/save_master_pos.inc + +--connection server_2 +--source include/start_slave.inc +--source include/sync_with_master_gtid.inc + +SELECT * FROM t1 WHERE a >= 30 ORDER BY a; + +--source include/stop_slave.inc +SET GLOBAL slave_parallel_mode=@old_mode; +--source include/start_slave.inc + + +# Clean up. + --connection server_2 --source include/stop_slave.inc SET GLOBAL slave_parallel_threads=@old_parallel_threads; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 4bef42e82bf..49aaa1dac1e 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -14697,6 +14697,36 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_prefix() } +/** + Allocate a temporary buffer, populate the buffer using the group prefix key + and the min/max field key, and compare the result to the current key pointed + by index_info. + + @param key - the min or max field key + @param length - length of "key" +*/ +int +QUICK_GROUP_MIN_MAX_SELECT::cmp_min_max_key(const uchar *key, uint16 length) +{ + /* + Allocate a buffer. + Note, we allocate one extra byte, because some of Field_xxx::cmp(), + e.g. Field_newdate::cmp(), use uint3korr() which actually read four bytes + and then bit-and the read value with 0xFFFFFF. + See "MDEV-7920 main.group_min_max fails ... with valgrind" for details. + */ + uchar *buffer= (uchar*) my_alloca(real_prefix_len + min_max_arg_len + 1); + /* Concatenate the group prefix key and the min/max field key */ + memcpy(buffer, group_prefix, real_prefix_len); + memcpy(buffer + real_prefix_len, key, length); + /* Compare the key pointed by key_info to the created key */ + int cmp_res= key_cmp(index_info->key_part, buffer, + real_prefix_len + min_max_arg_len); + my_afree(buffer); + return cmp_res; +} + + /* Find the minimal key in a group that satisfies some range conditions for the min/max argument field. @@ -14798,15 +14828,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range() /* If there is an upper limit, check if the found key is in the range. */ if ( !(cur_range->flag & NO_MAX_RANGE) ) { - /* Compose the MAX key for the range. */ - uchar *max_key= (uchar*) my_alloca(real_prefix_len + min_max_arg_len); - memcpy(max_key, group_prefix, real_prefix_len); - memcpy(max_key + real_prefix_len, cur_range->max_key, - cur_range->max_length); - /* Compare the found key with max_key. */ - int cmp_res= key_cmp(index_info->key_part, max_key, - real_prefix_len + min_max_arg_len); - my_afree(max_key); + int cmp_res= cmp_min_max_key(cur_range->max_key, cur_range->max_length); /* The key is outside of the range if: the interval is open and the key is equal to the maximum boundry @@ -14924,15 +14946,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range() /* If there is a lower limit, check if the found key is in the range. */ if ( !(cur_range->flag & NO_MIN_RANGE) ) { - /* Compose the MIN key for the range. */ - uchar *min_key= (uchar*) my_alloca(real_prefix_len + min_max_arg_len); - memcpy(min_key, group_prefix, real_prefix_len); - memcpy(min_key + real_prefix_len, cur_range->min_key, - cur_range->min_length); - /* Compare the found key with min_key. */ - int cmp_res= key_cmp(index_info->key_part, min_key, - real_prefix_len + min_max_arg_len); - my_afree(min_key); + int cmp_res= cmp_min_max_key(cur_range->min_key, cur_range->min_length); /* The key is outside of the range if: the interval is open and the key is equal to the minimum boundry diff --git a/sql/opt_range.h b/sql/opt_range.h index a5488d6124d..df6dfe8c8a4 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -927,6 +927,7 @@ private: int next_max(); void update_min_result(); void update_max_result(); + int cmp_min_max_key(const uchar *key, uint16 length); public: QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join, bool have_min, bool have_max, bool have_agg_distinct, diff --git a/sql/slave.cc b/sql/slave.cc index af3288c5c8d..f9ddbb53b52 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2004,11 +2004,21 @@ after_set_capability: !(master_row= mysql_fetch_row(master_res))) { err_code= mysql_errno(mysql); - errmsg= "The slave I/O thread stops because master does not support " - "MariaDB global transaction id. A fatal error is encountered when " - "it tries to SELECT @@GLOBAL.gtid_domain_id."; - sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql)); - goto err; + if (is_network_error(err_code)) + { + mi->report(ERROR_LEVEL, err_code, NULL, + "Get master @@GLOBAL.gtid_domain_id failed with error: %s", + mysql_error(mysql)); + goto network_err; + } + else + { + errmsg= "The slave I/O thread stops because master does not support " + "MariaDB global transaction id. A fatal error is encountered when " + "it tries to SELECT @@GLOBAL.gtid_domain_id."; + sprintf(err_buff, "%s Error: %s", errmsg, mysql_error(mysql)); + goto err; + } } mysql_free_result(master_res); master_res= NULL; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b4c3e5ecafd..0e9f668722d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -704,20 +704,23 @@ static void mark_temp_tables_as_free_for_reuse(THD *thd) DBUG_VOID_RETURN; } - thd->lock_temporary_tables(); - for (TABLE *table= thd->temporary_tables ; table ; table= table->next) - { - if ((table->query_id == thd->query_id) && ! table->open_by_handler) - mark_tmp_table_for_reuse(table); - } - thd->unlock_temporary_tables(); - if (thd->rgi_slave) + if (thd->temporary_tables) { - /* - Temporary tables are shared with other by sql execution threads. - As a safety messure, clear the pointer to the common area. - */ - thd->temporary_tables= 0; + thd->lock_temporary_tables(); + for (TABLE *table= thd->temporary_tables ; table ; table= table->next) + { + if ((table->query_id == thd->query_id) && ! table->open_by_handler) + mark_tmp_table_for_reuse(table); + } + thd->unlock_temporary_tables(); + if (thd->rgi_slave) + { + /* + Temporary tables are shared with other by sql execution threads. + As a safety messure, clear the pointer to the common area. + */ + thd->temporary_tables= 0; + } } DBUG_VOID_RETURN; } @@ -1590,6 +1593,69 @@ TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl) } +static bool +use_temporary_table(THD *thd, TABLE *table, TABLE **out_table) +{ + *out_table= table; + if (!table) + return false; + /* + Temporary tables are not safe for parallel replication. They were + designed to be visible to one thread only, so have no table locking. + Thus there is no protection against two conflicting transactions + committing in parallel and things like that. + + So for now, anything that uses temporary tables will be serialised + with anything before it, when using parallel replication. + + ToDo: We might be able to introduce a reference count or something + on temp tables, and have slave worker threads wait for it to reach + zero before being allowed to use the temp table. Might not be worth + it though, as statement-based replication using temporary tables is + in any case rather fragile. + */ + if (thd->rgi_slave && thd->rgi_slave->is_parallel_exec && + thd->wait_for_prior_commit()) + return true; + /* + We need to set the THD as it may be different in case of + parallel replication + */ + if (table->in_use != thd) + { + table->in_use= thd; +#ifdef REMOVE_AFTER_MERGE_WITH_10 + if (thd->rgi_slave) + { + /* + We may be stealing an opened temporary tables from one slave + thread to another, we need to let the performance schema know that, + for aggregates per thread to work properly. + */ + table->file->unbind_psi(); + table->file->rebind_psi(); + } +#endif + } + return false; +} + +bool +find_and_use_temporary_table(THD *thd, const char *db, const char *table_name, + TABLE **out_table) +{ + return use_temporary_table(thd, find_temporary_table(thd, db, table_name), + out_table); +} + + +bool +find_and_use_temporary_table(THD *thd, const TABLE_LIST *tl, TABLE **out_table) +{ + return use_temporary_table(thd, find_temporary_table(thd, tl), out_table); +} + + /** Find a temporary table specified by a key in the THD::temporary_tables list. @@ -1610,26 +1676,6 @@ TABLE *find_temporary_table(THD *thd, if (table->s->table_cache_key.length == table_key_length && !memcmp(table->s->table_cache_key.str, table_key, table_key_length)) { - /* - We need to set the THD as it may be different in case of - parallel replication - */ - if (table->in_use != thd) - { - table->in_use= thd; -#ifdef REMOVE_AFTER_MERGE_WITH_10 - if (thd->rgi_slave) - { - /* - We may be stealing an opened temporary tables from one slave - thread to another, we need to let the performance schema know that, - for aggregates per thread to work properly. - */ - table->file->unbind_psi(); - table->file->rebind_psi(); - } -#endif - } result= table; break; } @@ -5622,6 +5668,14 @@ TABLE *open_table_uncached(THD *thd, handlerton *hton, (uint) thd->variables.server_id, (ulong) thd->variables.pseudo_thread_id)); + if (add_to_temporary_tables_list) + { + /* Temporary tables are not safe for parallel replication. */ + if (thd->rgi_slave && thd->rgi_slave->is_parallel_exec && + thd->wait_for_prior_commit()) + return NULL; + } + /* Create the cache_key for temporary tables */ key_length= create_tmp_table_def_key(thd, cache_key, db, table_name); @@ -5857,7 +5911,9 @@ bool open_temporary_table(THD *thd, TABLE_LIST *tl) DBUG_RETURN(FALSE); } - if (!(table= find_temporary_table(thd, tl))) + if (find_and_use_temporary_table(thd, tl, &table)) + DBUG_RETURN(TRUE); + if (!table) { if (tl->open_type == OT_TEMPORARY_ONLY && tl->open_strategy == TABLE_LIST::OPEN_NORMAL) diff --git a/sql/sql_base.h b/sql/sql_base.h index 0e492fa8cf7..876bc6e7ed7 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -143,7 +143,11 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table, const char *db_name, const char *table_name); TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name); +bool find_and_use_temporary_table(THD *thd, const char *db, + const char *table_name, TABLE **out_table); TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl); +bool find_and_use_temporary_table(THD *thd, const TABLE_LIST *tl, + TABLE **out_table); TABLE *find_temporary_table(THD *thd, const char *table_key, uint table_key_length); void close_thread_tables(THD *thd); diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc index 09ae696e78f..ccd23b8e57c 100644 --- a/sql/sql_explain.cc +++ b/sql/sql_explain.cc @@ -769,7 +769,7 @@ void Explain_select::print_explain_json(Explain_query *query, write_item(writer, exec_const_cond); } - Filesort_tracker *first_table_sort= false; + Filesort_tracker *first_table_sort= NULL; int started_objects= 0; if (is_analyze) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index b9eaee8e007..de2c40be344 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4656,7 +4656,9 @@ int create_table_impl(THD *thd, if (create_info->tmp_table()) { TABLE *tmp_table; - if ((tmp_table= find_temporary_table(thd, db, table_name))) + if (find_and_use_temporary_table(thd, db, table_name, &tmp_table)) + goto err; + if (tmp_table) { bool table_creation_was_logged= tmp_table->s->table_creation_was_logged; if (options.or_replace()) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 1c64698d983..c56cb3267b3 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -930,7 +930,7 @@ loop_out: { push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), - view->db, view->table_name); + view->table_name); DBUG_RETURN(0); } else if (mode == VIEW_CREATE_NEW) diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 512e8f23dd8..d37c6c0e96c 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -451,7 +451,7 @@ static void* sst_joiner_thread (void* a) } else { // Scan state ID first followed by wsrep_gtid_domain_id. char uuid[512]; - uint32 domain_id; + long int domain_id; size_t len= pos - out + 1; if (len > sizeof(uuid)) goto err; // safety check @@ -464,14 +464,18 @@ static void* sst_joiner_thread (void* a) } else if (wsrep_gtid_mode) { + errno= 0; /* Reset the errno */ domain_id= strtol(pos + 1, NULL, 10); - if (domain_id < 1000 || domain_id > 0xFFFF) + err= errno; + + /* Check if we received a valid gtid_domain_id. */ + if (err == EINVAL || err == ERANGE || domain_id < 0x0 || domain_id > 0xFFFF) { WSREP_ERROR("Failed to get donor wsrep_gtid_domain_id."); err= EINVAL; goto err; } else { - wsrep_gtid_domain_id= domain_id; + wsrep_gtid_domain_id= (uint32) domain_id; } } } |