summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2015-04-15 12:09:25 -0700
committerSergei Petrunia <psergey@askmonty.org>2015-04-15 12:09:25 -0700
commitc712b376d8189b963851db86a0bedd478aab869e (patch)
tree8d02a74357f8ba77261d79bd70ca6174e0fe5dd8
parent25da74ce3f17a4720f4f7f06b1d694ff417d6b60 (diff)
parentd051f6c36beaf6c7ea269d6c174cca7482f3e823 (diff)
downloadmariadb-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/control2
-rw-r--r--debian/dist/Ubuntu/control2
-rw-r--r--mysql-test/include/mtr_warnings.sql6
-rwxr-xr-xmysql-test/mysql-test-run.pl6
-rw-r--r--mysql-test/r/create_drop_binlog.result2
-rw-r--r--mysql-test/r/create_drop_view.result2
-rw-r--r--mysql-test/suite/rpl/r/rpl_create_drop_view.result2
-rw-r--r--mysql-test/suite/rpl/r/rpl_parallel_multilevel2.result52
-rw-r--r--mysql-test/suite/rpl/r/rpl_parallel_temptable.result46
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf17
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test80
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_temptable.test47
-rw-r--r--sql/opt_range.cc50
-rw-r--r--sql/opt_range.h1
-rw-r--r--sql/slave.cc20
-rw-r--r--sql/sql_base.cc124
-rw-r--r--sql/sql_base.h4
-rw-r--r--sql/sql_explain.cc2
-rw-r--r--sql/sql_table.cc4
-rw-r--r--sql/sql_view.cc2
-rw-r--r--sql/wsrep_sst.cc10
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;
}
}
}