From 6fc0a8af243befc8504676b9d7a6f6bbeafb85b1 Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Sun, 8 Mar 2015 23:12:19 +0200 Subject: [PATCH 1/7] MDEV-7187 perfschema.aggregate fails sporadically in buildbot During slow execution, e.g. under valgrind, there was a chance that Aria checkpoint would happen while P_S tables were being queried; it could cause different data in joined P_S, and thus combinations of results that the test did not expect. Fixed by disabling Aria checkpoints for the test. --- mysql-test/suite/perfschema/r/aggregate.result | 3 +++ mysql-test/suite/perfschema/t/aggregate.test | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/mysql-test/suite/perfschema/r/aggregate.result b/mysql-test/suite/perfschema/r/aggregate.result index ab927f544cf..c8fa1cc2b24 100644 --- a/mysql-test/suite/perfschema/r/aggregate.result +++ b/mysql-test/suite/perfschema/r/aggregate.result @@ -1,4 +1,6 @@ "General cleanup" +set @aria_checkpoint_interval_save= @@global.aria_checkpoint_interval; +set @@global.aria_checkpoint_interval= 0; drop table if exists t1; update performance_schema.setup_instruments set enabled = 'NO'; update performance_schema.setup_consumers set enabled = 'NO'; @@ -116,3 +118,4 @@ update performance_schema.setup_consumers set enabled = 'YES'; update performance_schema.setup_instruments set enabled = 'YES', timed = 'YES'; drop table test.t1; +set @@global.aria_checkpoint_interval= @aria_checkpoint_interval_save; diff --git a/mysql-test/suite/perfschema/t/aggregate.test b/mysql-test/suite/perfschema/t/aggregate.test index 672737ae2a7..fe30a7b8697 100644 --- a/mysql-test/suite/perfschema/t/aggregate.test +++ b/mysql-test/suite/perfschema/t/aggregate.test @@ -6,6 +6,10 @@ --echo "General cleanup" +# MDEV-7187 - test fails sporadically in buildbot +set @aria_checkpoint_interval_save= @@global.aria_checkpoint_interval; +set @@global.aria_checkpoint_interval= 0; + --disable_warnings drop table if exists t1; --enable_warnings @@ -188,3 +192,6 @@ update performance_schema.setup_instruments set enabled = 'YES', timed = 'YES'; drop table test.t1; + +set @@global.aria_checkpoint_interval= @aria_checkpoint_interval_save; + From 040027c888f9b9e1a41c82fd793e0cde289e5eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 9 Mar 2015 09:47:25 +0200 Subject: [PATCH 2/7] MDEV-7627 :Some symbols in table name can cause to Error Code: 1050 when created FK Analysis: Table name is on filename charset but foreign key identifiers are not. This lead incorrect foreign key identifier number to be used. Fix: Convert foreign key identifier to filename charset before comparing it to table name when largest foreign key identifier number is resolved. --- mysql-test/suite/innodb/r/innodb-fk.result | 75 ++++++++++++++++++++++ mysql-test/suite/innodb/t/innodb-fk.test | 63 ++++++++++++++++++ storage/innobase/dict/dict0dict.cc | 19 ++++-- storage/xtradb/dict/dict0dict.cc | 19 ++++-- 4 files changed, 166 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/innodb/r/innodb-fk.result b/mysql-test/suite/innodb/r/innodb-fk.result index 82ac412e339..956dbce58ed 100644 --- a/mysql-test/suite/innodb/r/innodb-fk.result +++ b/mysql-test/suite/innodb/r/innodb-fk.result @@ -67,3 +67,78 @@ Error 1005 Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key c Warning 1215 Cannot add foreign key constraint drop table t2; drop table t1; +CREATE TABLE `#departaments` ( +`id_depart` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +PRIMARY KEY (`id_depart`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; +CREATE TABLE `#departaments_tree` ( +`id_depart` INT(10) UNSIGNED NOT NULL, +`id_depart_in` INT(10) UNSIGNED NOT NULL, +PRIMARY KEY (`id_depart`,`id_depart_in`), +CONSTRAINT `#departaments_tree_ibfk_1` FOREIGN KEY (`id_depart`) REFERENCES `#departaments` (`id_depart`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; +ALTER TABLE `#departaments_tree` + ADD FOREIGN KEY (`id_depart_in`) REFERENCES `#departaments`(`id_depart`); +SHOW CREATE TABLE `#departaments_tree`; +Table Create Table +#departaments_tree CREATE TABLE `#departaments_tree` ( + `id_depart` int(10) unsigned NOT NULL, + `id_depart_in` int(10) unsigned NOT NULL, + PRIMARY KEY (`id_depart`,`id_depart_in`), + KEY `id_depart_in` (`id_depart_in`), + CONSTRAINT `#departaments_tree_ibfk_1` FOREIGN KEY (`id_depart`) REFERENCES `#departaments` (`id_depart`), + CONSTRAINT `#departaments_tree_ibfk_2` FOREIGN KEY (`id_depart_in`) REFERENCES `#departaments` (`id_depart`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 +DROP TABLE `#departaments_tree`; +DROP TABLE `#departaments`; +CREATE TABLE `boroda` ( +`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +`a` INT(11) UNSIGNED DEFAULT NULL, +`b` INT(11) UNSIGNED DEFAULT NULL, +PRIMARY KEY (`id`), +KEY `a` (`a`), +CONSTRAINT `boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `boroda` (`id`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; +ALTER TABLE `boroda` + ADD FOREIGN KEY (`b`) REFERENCES `boroda`(`id`); +ALTER TABLE `boroda` DROP FOREIGN KEY `boroda_ibfk_2`; +RENAME TABLE `boroda` TO `#boroda`; +ALTER TABLE `#boroda` +ADD FOREIGN KEY (`b`) REFERENCES `#boroda`(`id`); +SHOW CREATE TABLE `#boroda`; +Table Create Table +#boroda CREATE TABLE `#boroda` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `a` int(11) unsigned DEFAULT NULL, + `b` int(11) unsigned DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `a` (`a`), + KEY `b` (`b`), + CONSTRAINT `#boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `#boroda` (`id`), + CONSTRAINT `#boroda_ibfk_2` FOREIGN KEY (`b`) REFERENCES `#boroda` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 +DROP TABLE `#boroda`; +CREATE TABLE `boroda` ( +`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +`a` INT(11) UNSIGNED DEFAULT NULL, +`b` INT(11) UNSIGNED DEFAULT NULL, +PRIMARY KEY (`id`), +KEY `a` (`a`), +CONSTRAINT `boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `boroda` (`id`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; +RENAME TABLE `boroda` TO `bor#oda`; +ALTER TABLE `bor#oda` +ADD FOREIGN KEY (`b`) REFERENCES `bor#oda`(`id`); +SHOW CREATE TABLE `bor#oda`; +Table Create Table +bor#oda CREATE TABLE `bor#oda` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `a` int(11) unsigned DEFAULT NULL, + `b` int(11) unsigned DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `a` (`a`), + KEY `b` (`b`), + CONSTRAINT `bor#oda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `bor#oda` (`id`), + CONSTRAINT `bor#oda_ibfk_2` FOREIGN KEY (`b`) REFERENCES `bor#oda` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 +DROP TABLE `bor#oda`; diff --git a/mysql-test/suite/innodb/t/innodb-fk.test b/mysql-test/suite/innodb/t/innodb-fk.test index 2c2a8c76cf8..f7bcbe238dd 100644 --- a/mysql-test/suite/innodb/t/innodb-fk.test +++ b/mysql-test/suite/innodb/t/innodb-fk.test @@ -124,3 +124,66 @@ show warnings; drop table t2; drop table t1; + +# +# MDEV-7627: Some symbols in table name can cause to Error Code: 1050 when created FK +# + +CREATE TABLE `#departaments` ( + `id_depart` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id_depart`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; + +CREATE TABLE `#departaments_tree` ( + `id_depart` INT(10) UNSIGNED NOT NULL, + `id_depart_in` INT(10) UNSIGNED NOT NULL, + PRIMARY KEY (`id_depart`,`id_depart_in`), + CONSTRAINT `#departaments_tree_ibfk_1` FOREIGN KEY (`id_depart`) REFERENCES `#departaments` (`id_depart`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; + +ALTER TABLE `#departaments_tree` + ADD FOREIGN KEY (`id_depart_in`) REFERENCES `#departaments`(`id_depart`); + +SHOW CREATE TABLE `#departaments_tree`; + +DROP TABLE `#departaments_tree`; +DROP TABLE `#departaments`; + +CREATE TABLE `boroda` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `a` INT(11) UNSIGNED DEFAULT NULL, + `b` INT(11) UNSIGNED DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `a` (`a`), + CONSTRAINT `boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `boroda` (`id`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; + +ALTER TABLE `boroda` + ADD FOREIGN KEY (`b`) REFERENCES `boroda`(`id`); + +ALTER TABLE `boroda` DROP FOREIGN KEY `boroda_ibfk_2`; + +RENAME TABLE `boroda` TO `#boroda`; + +ALTER TABLE `#boroda` +ADD FOREIGN KEY (`b`) REFERENCES `#boroda`(`id`); + +SHOW CREATE TABLE `#boroda`; +DROP TABLE `#boroda`; + +CREATE TABLE `boroda` ( + `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `a` INT(11) UNSIGNED DEFAULT NULL, + `b` INT(11) UNSIGNED DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `a` (`a`), + CONSTRAINT `boroda_ibfk_1` FOREIGN KEY (`a`) REFERENCES `boroda` (`id`) +) ENGINE=INNODB DEFAULT CHARSET=utf8; + +RENAME TABLE `boroda` TO `bor#oda`; + +ALTER TABLE `bor#oda` +ADD FOREIGN KEY (`b`) REFERENCES `bor#oda`(`id`); + +SHOW CREATE TABLE `bor#oda`; +DROP TABLE `bor#oda`; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 3ae6fa032b9..7c3c4e824d5 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -4110,16 +4110,25 @@ dict_table_get_highest_foreign_id( for (dict_foreign_set::iterator it = table->foreign_set.begin(); it != table->foreign_set.end(); ++it) { + char fkid[MAX_TABLE_NAME_LEN+20]; foreign = *it; - if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len - && 0 == ut_memcmp(foreign->id, table->name, len) - && 0 == ut_memcmp(foreign->id + len, + strcpy(fkid, foreign->id); + /* Convert foreign key identifier on dictionary memory + cache to filename charset. */ + innobase_convert_to_filename_charset( + strchr(fkid, '/') + 1, + strchr(foreign->id, '/') + 1, + MAX_TABLE_NAME_LEN); + + if (ut_strlen(fkid) > ((sizeof dict_ibfk) - 1) + len + && 0 == ut_memcmp(fkid, table->name, len) + && 0 == ut_memcmp(fkid + len, dict_ibfk, (sizeof dict_ibfk) - 1) - && foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') { + && fkid[len + ((sizeof dict_ibfk) - 1)] != '0') { /* It is of the >= 4.0.18 format */ - id = strtoul(foreign->id + len + id = strtoul(fkid + len + ((sizeof dict_ibfk) - 1), &endp, 10); if (*endp == '\0') { diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc index 12d145220d1..6b628198275 100644 --- a/storage/xtradb/dict/dict0dict.cc +++ b/storage/xtradb/dict/dict0dict.cc @@ -4114,16 +4114,25 @@ dict_table_get_highest_foreign_id( for (dict_foreign_set::iterator it = table->foreign_set.begin(); it != table->foreign_set.end(); ++it) { + char fkid[MAX_TABLE_NAME_LEN+20]; foreign = *it; - if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len - && 0 == ut_memcmp(foreign->id, table->name, len) - && 0 == ut_memcmp(foreign->id + len, + strcpy(fkid, foreign->id); + /* Convert foreign key identifier on dictionary memory + cache to filename charset. */ + innobase_convert_to_filename_charset( + strchr(fkid, '/') + 1, + strchr(foreign->id, '/') + 1, + MAX_TABLE_NAME_LEN); + + if (ut_strlen(fkid) > ((sizeof dict_ibfk) - 1) + len + && 0 == ut_memcmp(fkid, table->name, len) + && 0 == ut_memcmp(fkid + len, dict_ibfk, (sizeof dict_ibfk) - 1) - && foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') { + && fkid[len + ((sizeof dict_ibfk) - 1)] != '0') { /* It is of the >= 4.0.18 format */ - id = strtoul(foreign->id + len + id = strtoul(fkid + len + ((sizeof dict_ibfk) - 1), &endp, 10); if (*endp == '\0') { From 96784eb106d9e0ab6ce717a937a9be9af714b223 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Mon, 9 Mar 2015 13:06:32 +0100 Subject: [PATCH 3/7] MDEV-7668: Intermediate master groups CREATE TEMPORARY with INSERT, causing parallel replication failure Parallel replication depends on locking (table locks, row locks, etc.) to prevent two conflicting transactions from running and committing in parallel. But temporary tables are designed to be visible only to one thread, and have no such locking. In the concrete issue, an intermediate master could commit a CREATE TEMPORARY TABLE in the same group commit as in INSERT into that table. Thus, a lower-level master could attempt to run them in parallel and get an error. More generally, we need protection from parallel replication trying to run transactions in parallel that access a common temporary table. This patch simply causes use of a temporary table from parallel replication to wait for all previous transactions to commit, serialising the replication at that point. (A more fine-grained locking could be added later, possibly. However, using temporary tables in statement-based replication is in any case normally undesirable; for example a restart of the server will lose temporary tables and can break replication). Note that row-based replication is not affected, as it does not do any temporary tables on the slave-side. This patch also cleans up the locking around protecting the list of temporary tables in Relay_log_info. This used to take the rli->data_lock at the end of every statement, which is very bad for concurrency. With this patch, the lock is not taken unless temporary tables (with statement-based binlogging) are in use on the slave. --- .../rpl/r/rpl_parallel_multilevel2.result | 52 ++++++++++++ .../suite/rpl/t/rpl_parallel_multilevel2.cnf | 17 ++++ .../suite/rpl/t/rpl_parallel_multilevel2.test | 80 +++++++++++++++++++ sql/sql_base.cc | 56 ++++++++++--- 4 files changed, 192 insertions(+), 13 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_parallel_multilevel2.result create mode 100644 mysql-test/suite/rpl/t/rpl_parallel_multilevel2.cnf create mode 100644 mysql-test/suite/rpl/t/rpl_parallel_multilevel2.test 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/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/sql/sql_base.cc b/sql/sql_base.cc index d4fb2a8b8bb..9aa9d1e0266 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -661,20 +661,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 (thd->temporary_tables) { - 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; + 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; } @@ -5586,6 +5589,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); @@ -5822,6 +5833,25 @@ bool open_temporary_table(THD *thd, TABLE_LIST *tl) DBUG_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()) + DBUG_RETURN(true); + #ifdef WITH_PARTITION_STORAGE_ENGINE if (tl->partition_names) { From ec16d1b62fb08b4dd3aa415a9bf717b5039a56cc Mon Sep 17 00:00:00 2001 From: Elena Stepanova Date: Mon, 9 Mar 2015 02:07:47 +0200 Subject: [PATCH 4/7] MDEV-7107 Sporadic test failure in multi_source.multisource Extend show_slave_status.inc to run SHOW ALL SLAVES STATUS and SHOW SLAVE 'name' STATUS on demand, and make the test use the include file instead of direct SHOW statements --- mysql-test/include/show_slave_status.inc | 52 +++++++++-- .../suite/multi_source/multisource.result | 87 +++++++++++++++---- .../suite/multi_source/multisource.test | 50 ++++++++--- 3 files changed, 155 insertions(+), 34 deletions(-) diff --git a/mysql-test/include/show_slave_status.inc b/mysql-test/include/show_slave_status.inc index 55eb83c25e5..ba2e1b0c48a 100644 --- a/mysql-test/include/show_slave_status.inc +++ b/mysql-test/include/show_slave_status.inc @@ -67,7 +67,21 @@ # # --let $slave_sql_mode= NO_BACKSLASH_ESCAPES # - +# $all_slaves_status +# If set, use SHOW ALL SLAVES STATUS instead of SHOW SLAVE STATUS +# and get the column values from all rows. Example: +# +# --let $all_slaves_status= 1 +# +# $slave_name +# If set, use SHOW SLAVE '' STATUS instead of SHOW SLAVE STATUS. +# The name must be quoted (can be a quoted empty string). +# Example: +# +# --let $slave_name= 'm1' +# +# Note: $all_slaves_status and $slave_name are mutually exclusive. +# --let $_show_slave_status_items=$status_items if (!$status_items) @@ -75,6 +89,21 @@ if (!$status_items) --die Bug in test case: The mysqltest variable $status_items is not set. } +--let $_show_query=SHOW SLAVE STATUS + +if ($all_slaves_status) +{ + if ($slave_name) + { + --die Bug in test case: Both $all_slaves_status and $slave_name are set. + } + --let $_show_query=SHOW ALL SLAVES STATUS +} +if ($slave_name) +{ + --let $_show_query=SHOW SLAVE $slave_name STATUS +} + --let $_slave_sql_mode= NO_BACKSLASH_ESCAPES if ($slave_sql_mode) @@ -86,18 +115,27 @@ if ($slave_sql_mode) eval SET sql_mode= '$_slave_sql_mode'; --enable_query_log +--let $_slave_field_result_replace= /[\\\\]/\// $slave_field_result_replace while ($_show_slave_status_items) { --let $_show_slave_status_name= `SELECT SUBSTRING_INDEX('$_show_slave_status_items', ',', 1)` --let $_show_slave_status_items= `SELECT LTRIM(SUBSTRING('$_show_slave_status_items', LENGTH('$_show_slave_status_name') + 2))` - --replace_regex /\.[\\\/]master/master/ - --let $_show_slave_status_value= query_get_value(SHOW SLAVE STATUS, $_show_slave_status_name, 1) - --let $_slave_field_result_replace= /[\\\\]/\// $slave_field_result_replace - --replace_regex $_slave_field_result_replace - --let $_show_slave_status_value= `SELECT REPLACE("$_show_slave_status_value", '$MYSQL_TEST_DIR', 'MYSQL_TEST_DIR')` - --echo $_show_slave_status_name = '$_show_slave_status_value' + --let $num= 1 + --let $_show_slave_status_value= + while ($_show_slave_status_value != 'No such row') + { + --replace_regex /\.[\\\/]master/master/ + --let $_show_slave_status_value= query_get_value($_show_query, $_show_slave_status_name, $num) + if ($_show_slave_status_value != 'No such row') + { + --replace_regex $_slave_field_result_replace + --let $_show_slave_status_value= `SELECT REPLACE("$_show_slave_status_value", '$MYSQL_TEST_DIR', 'MYSQL_TEST_DIR')` + --echo $_show_slave_status_name = '$_show_slave_status_value' + --inc $num + } + } } diff --git a/mysql-test/suite/multi_source/multisource.result b/mysql-test/suite/multi_source/multisource.result index 94677e84cc8..d9689f759bf 100644 --- a/mysql-test/suite/multi_source/multisource.result +++ b/mysql-test/suite/multi_source/multisource.result @@ -9,15 +9,36 @@ master_user='root'; start slave 'master1'; set default_master_connection = 'master1'; include/wait_for_slave_to_start.inc -show slave 'master1' status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos -Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 313 mysqld-relay-bin-master1.000002 601 master-bin.000001 Yes Yes 0 0 313 907 None 0 No 0 No 0 0 1 No -show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos -Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 313 mysqld-relay-bin-master1.000002 601 master-bin.000001 Yes Yes 0 0 313 907 None 0 No 0 No 0 0 1 No -show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos -master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 313 mysqld-relay-bin-master1.000002 601 master-bin.000001 Yes Yes 0 0 313 907 None 0 No 0 No 0 0 1 No 0 1073741824 7 0 60.000 +# +# Checking SHOW SLAVE 'master1' STATUS +# +Master_Port = 'MYPORT_1' +Relay_Log_File = 'mysqld-relay-bin-master1.000002' +Slave_IO_Running = 'Yes' +Slave_SQL_Running = 'Yes' +Last_Errno = '0' +Last_SQL_Errno = '0' +# +# Checking SHOW SLAVE STATUS +# +Master_Port = 'MYPORT_1' +Relay_Log_File = 'mysqld-relay-bin-master1.000002' +Slave_IO_Running = 'Yes' +Slave_SQL_Running = 'Yes' +Last_Errno = '0' +Last_SQL_Errno = '0' +# +# Checking SHOW ALL SLAVES STATUS +# +Connection_name = 'master1' +Master_Port = 'MYPORT_1' +Relay_Log_File = 'mysqld-relay-bin-master1.000002' +Slave_IO_Running = 'Yes' +Slave_SQL_Running = 'Yes' +Last_Errno = '0' +Last_SQL_Errno = '0' +Slave_heartbeat_period = '60.000' +# drop database if exists db1; create database db1; use db1; @@ -74,10 +95,26 @@ master_host='127.0.0.1', master_user='root'; start slave; include/wait_for_slave_to_start.inc -show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos - Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 313 mysqld-relay-bin.000002 601 master-bin.000001 Yes Yes 0 0 313 899 None 0 No 0 No 0 0 2 No 0 1073741824 7 0 60.000 0-1-4 -master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000001 988 mysqld-relay-bin-master1.000002 1276 master-bin.000001 Yes Yes 0 0 988 1582 None 0 No 0 No 0 0 1 No 0 1073741824 17 0 60.000 0-1-4 +# +# Checking SHOW ALL SLAVES STATUS +# +Connection_name = '' +Connection_name = 'master1' +Master_Port = 'MYPORT_2' +Master_Port = 'MYPORT_1' +Relay_Log_File = 'mysqld-relay-bin.000002' +Relay_Log_File = 'mysqld-relay-bin-master1.000002' +Slave_IO_Running = 'Yes' +Slave_IO_Running = 'Yes' +Slave_SQL_Running = 'Yes' +Slave_SQL_Running = 'Yes' +Last_Errno = '0' +Last_Errno = '0' +Last_SQL_Errno = '0' +Last_SQL_Errno = '0' +Slave_heartbeat_period = '60.000' +Slave_heartbeat_period = '60.000' +# insert into t1 (f1) values ('three'); drop database if exists db2; create database db2; @@ -104,10 +141,26 @@ Log_name File_size master-bin.000002 367 insert into t1 (f1) values ('four'); create table db1.t3 (f1 int) engine=InnoDB; -show all slaves status; -Connection_name Slave_SQL_State Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_SSL_Crl Master_SSL_Crlpath Using_Gtid Gtid_IO_Pos Retried_transactions Max_relay_log_size Executed_log_entries Slave_received_heartbeats Slave_heartbeat_period Gtid_Slave_Pos - Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_2 60 master-bin.000001 921 mysqld-relay-bin.000002 1209 master-bin.000001 Yes Yes 0 0 921 1507 None 0 No 0 No 0 0 2 No 0 1073741824 17 0 60.000 0-1-7 -master1 Slave has read all relay log; waiting for the slave I/O thread to update it Waiting for master to send event 127.0.0.1 root MYPORT_1 60 master-bin.000002 740 mysqld-relay-bin-master1.000004 1028 master-bin.000002 Yes Yes 0 0 740 1378 None 0 No 0 No 0 0 1 No 0 1073741824 37 0 60.000 0-1-7 +# +# Checking SHOW ALL SLAVES STATUS +# +Connection_name = '' +Connection_name = 'master1' +Master_Port = 'MYPORT_2' +Master_Port = 'MYPORT_1' +Relay_Log_File = 'mysqld-relay-bin.000002' +Relay_Log_File = 'mysqld-relay-bin-master1.000004' +Slave_IO_Running = 'Yes' +Slave_IO_Running = 'Yes' +Slave_SQL_Running = 'Yes' +Slave_SQL_Running = 'Yes' +Last_Errno = '0' +Last_Errno = '0' +Last_SQL_Errno = '0' +Last_SQL_Errno = '0' +Slave_heartbeat_period = '60.000' +Slave_heartbeat_period = '60.000' +# select * from db1.t1; i f1 1 one diff --git a/mysql-test/suite/multi_source/multisource.test b/mysql-test/suite/multi_source/multisource.test index 754dc9fa650..c99db802981 100644 --- a/mysql-test/suite/multi_source/multisource.test +++ b/mysql-test/suite/multi_source/multisource.test @@ -49,12 +49,28 @@ let $field= Slave_IO_State; let $condition= = 'Waiting for master to send event'; --source include/wait_show_condition.inc ---replace_result $SERVER_MYPORT_1 MYPORT_1 -show slave 'master1' status; ---replace_result $SERVER_MYPORT_1 MYPORT_1 -show slave status; ---replace_result $SERVER_MYPORT_1 MYPORT_1 -show all slaves status; +--echo # +--echo # Checking SHOW SLAVE 'master1' STATUS +--echo # +--let $status_items= Master_Port, Relay_Log_File, Slave_IO_Running, Slave_SQL_Running, Last_Errno, Last_SQL_Errno +--let $slave_field_result_replace= /$SERVER_MYPORT_1/MYPORT_1/ +--let $slave_name= 'master1' +--source include/show_slave_status.inc +--let $slave_name= + +--echo # +--echo # Checking SHOW SLAVE STATUS +--echo # +--source include/show_slave_status.inc + +--echo # +--echo # Checking SHOW ALL SLAVES STATUS +--echo # +--let $all_slaves_status= 1 +--let $status_items= Connection_name, Master_Port, Relay_Log_File, Slave_IO_Running, Slave_SQL_Running, Last_Errno, Last_SQL_Errno, Slave_heartbeat_period +--source include/show_slave_status.inc +--let $all_slaves_status= +--echo # # Check that replication actually works @@ -144,8 +160,15 @@ let $field= Slave_IO_State; let $condition= = 'Waiting for master to send event'; --source include/wait_show_condition.inc ---replace_result $SERVER_MYPORT_1 MYPORT_1 $SERVER_MYPORT_2 MYPORT_2 -show all slaves status; +--echo # +--echo # Checking SHOW ALL SLAVES STATUS +--echo # +--let $all_slaves_status= 1 +--let $status_items= Connection_name, Master_Port, Relay_Log_File, Slave_IO_Running, Slave_SQL_Running, Last_Errno, Last_SQL_Errno, Slave_heartbeat_period +--let $slave_field_result_replace= /$SERVER_MYPORT_1/MYPORT_1/ /$SERVER_MYPORT_2/MYPORT_2/ +--source include/show_slave_status.inc +--let $all_slaves_status= +--echo # # Check that replication from two servers actually works @@ -214,8 +237,15 @@ let $field= Slave_IO_State; let $condition= = 'Waiting for master to send event'; --source include/wait_show_condition.inc ---replace_result $SERVER_MYPORT_1 MYPORT_1 $SERVER_MYPORT_2 MYPORT_2 -show all slaves status; +--echo # +--echo # Checking SHOW ALL SLAVES STATUS +--echo # +--let $all_slaves_status= 1 +--let $status_items= Connection_name, Master_Port, Relay_Log_File, Slave_IO_Running, Slave_SQL_Running, Last_Errno, Last_SQL_Errno, Slave_heartbeat_period +--let $slave_field_result_replace= /$SERVER_MYPORT_1/MYPORT_1/ /$SERVER_MYPORT_2/MYPORT_2/ +--source include/show_slave_status.inc +--let $all_slaves_status= +--echo # --sorted_result select * from db1.t1; From a7fd11b31d52b62ef7b61783bb83a5e62271307b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Mon, 9 Mar 2015 18:21:48 +0200 Subject: [PATCH 5/7] MDEV-7685: MariaDB - server crashes when inserting more rows than available space on disk Add error handling when disk full situation happens and intentionally bring server down with stacktrace because on all cases InnoDB can't continue anyway. --- .../r/innodb-alter-table-disk-full.result | 63 ---------------- .../t/innodb-alter-table-disk-full-master.opt | 1 - .../t/innodb-alter-table-disk-full.test | 75 ------------------- storage/innobase/btr/btr0btr.cc | 6 -- storage/innobase/handler/handler0alter.cc | 1 + storage/innobase/os/os0file.cc | 17 ++++- storage/xtradb/btr/btr0btr.cc | 6 -- storage/xtradb/handler/handler0alter.cc | 1 + storage/xtradb/os/os0file.cc | 16 +++- 9 files changed, 28 insertions(+), 158 deletions(-) delete mode 100644 mysql-test/suite/innodb/r/innodb-alter-table-disk-full.result delete mode 100644 mysql-test/suite/innodb/t/innodb-alter-table-disk-full-master.opt delete mode 100644 mysql-test/suite/innodb/t/innodb-alter-table-disk-full.test diff --git a/mysql-test/suite/innodb/r/innodb-alter-table-disk-full.result b/mysql-test/suite/innodb/r/innodb-alter-table-disk-full.result deleted file mode 100644 index a357fe27f37..00000000000 --- a/mysql-test/suite/innodb/r/innodb-alter-table-disk-full.result +++ /dev/null @@ -1,63 +0,0 @@ -call mtr.add_suppression("InnoDB: Error: row_merge_drop_indexes_dict failed with error code*"); -create table t1(a int, b int) engine=innodb; -create procedure innodb_insert_proc (repeat_count int) -begin -declare current_num int; -set current_num = 0; -while current_num < repeat_count do -insert into t1 values(current_num, current_num); -set current_num = current_num + 1; -end while; -end// -commit; -set autocommit=0; -call innodb_insert_proc(20000); -commit; -set autocommit=1; -create table t2(a int) engine=innodb; -show create table t2; -Table Create Table -t2 CREATE TABLE `t2` ( - `a` int(11) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28'; -alter table t1 add testcol int; -ERROR HY000: The table 't1' is full -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a` int(11) DEFAULT NULL, - `b` int(11) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -alter table t2 add testcol int; -ERROR HY000: The table 't2' is full -alter table t1 add testcol int; -ERROR HY000: The table 't1' is full -alter table t1 add testcol int; -ERROR HY000: The table 't1' is full -alter table t1 add testcol2 int; -ERROR HY000: The table 't1' is full -alter table t1 add testcol3 int; -ERROR HY000: The table 't1' is full -alter table t1 add testcol int; -ERROR HY000: The table 't1' is full -show create table t1; -Table Create Table -t1 CREATE TABLE `t1` ( - `a` int(11) DEFAULT NULL, - `b` int(11) DEFAULT NULL -) ENGINE=InnoDB DEFAULT CHARSET=latin1 -drop table t2; -alter table t1 add testcol2 int; -ERROR HY000: The table 't1' is full -alter table t1 add testcol3 int; -ERROR HY000: The table 't1' is full -call innodb_insert_proc(20000); -set autocommit=0; -call innodb_insert_proc(20000); -commit; -set autocommit=1; -set DEBUG_DBUG=''; -drop procedure innodb_insert_proc; -drop table t1; -drop table if exists t2; diff --git a/mysql-test/suite/innodb/t/innodb-alter-table-disk-full-master.opt b/mysql-test/suite/innodb/t/innodb-alter-table-disk-full-master.opt deleted file mode 100644 index 9c2ee7846b6..00000000000 --- a/mysql-test/suite/innodb/t/innodb-alter-table-disk-full-master.opt +++ /dev/null @@ -1 +0,0 @@ ---innodb-use-native-aio=0 diff --git a/mysql-test/suite/innodb/t/innodb-alter-table-disk-full.test b/mysql-test/suite/innodb/t/innodb-alter-table-disk-full.test deleted file mode 100644 index 8fd8e3914c4..00000000000 --- a/mysql-test/suite/innodb/t/innodb-alter-table-disk-full.test +++ /dev/null @@ -1,75 +0,0 @@ -# MDEV-6288: Innodb causes server crash after disk full, then can't ALTER TABLE any more ---source include/have_innodb.inc ---source include/not_windows.inc ---source include/not_valgrind.inc ---source include/not_embedded.inc - -# DEBUG_SYNC must be compiled in. ---source include/have_debug_sync.inc - -call mtr.add_suppression("InnoDB: Error: row_merge_drop_indexes_dict failed with error code*"); - -create table t1(a int, b int) engine=innodb; - -delimiter //; -create procedure innodb_insert_proc (repeat_count int) -begin - declare current_num int; - set current_num = 0; - while current_num < repeat_count do - insert into t1 values(current_num, current_num); - set current_num = current_num + 1; - end while; -end// -delimiter ;// -commit; - -set autocommit=0; -call innodb_insert_proc(20000); -commit; -set autocommit=1; - -create table t2(a int) engine=innodb; -show create table t2; - -# This caused crash earlier -set DEBUG_DBUG='+d,ib_os_aio_func_io_failure_28'; ---error 1114 -alter table t1 add testcol int; -show create table t1; ---error 1114 -alter table t2 add testcol int; ---error 1114 -alter table t1 add testcol int; ---error 1114 -alter table t1 add testcol int; ---error 1114 -alter table t1 add testcol2 int; ---error 1114 -alter table t1 add testcol3 int; ---error 1114 -alter table t1 add testcol int; -show create table t1; ---error 0,1051 -drop table t2; ---error 1114 -alter table t1 add testcol2 int; ---error 1114 -alter table t1 add testcol3 int; ---error 0,1114 -call innodb_insert_proc(20000); -set autocommit=0; ---error 0,1114 -call innodb_insert_proc(20000); -commit; -set autocommit=1; - -set DEBUG_DBUG=''; - -drop procedure innodb_insert_proc; -drop table t1; ---disable_warnings -drop table if exists t2; ---enable_warnings - - diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc index 00b90120f6c..79b533481b7 100644 --- a/storage/innobase/btr/btr0btr.cc +++ b/storage/innobase/btr/btr0btr.cc @@ -3055,12 +3055,6 @@ func_start: /* 2. Allocate a new page to the index */ new_block = btr_page_alloc(cursor->index, hint_page_no, direction, btr_page_get_level(page, mtr), mtr, mtr); - - /* Play safe, if new page is not allocated */ - if (!new_block) { - return(rec); - } - new_page = buf_block_get_frame(new_block); new_page_zip = buf_block_get_page_zip(new_block); btr_page_create(new_block, new_page_zip, cursor->index, diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index b387c217b43..76d68bb9676 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -128,6 +128,7 @@ my_error_innodb( break; case DB_OUT_OF_FILE_SPACE: my_error(ER_RECORD_FILE_FULL, MYF(0), table); + ut_error; break; case DB_TEMP_FILE_WRITE_FAILURE: my_error(ER_GET_ERRMSG, MYF(0), diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index b646b74b246..30e98c2eddd 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -617,7 +617,7 @@ os_file_handle_error_cond_exit( os_has_said_disk_full = TRUE; fflush(stderr); - + ut_error; return(FALSE); case OS_FILE_AIO_RESOURCES_RESERVED: @@ -4607,7 +4607,7 @@ os_aio_func( mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER); DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28", - mode = OS_AIO_SYNC; os_has_said_disk_full = TRUE;); + mode = OS_AIO_SYNC; os_has_said_disk_full = FALSE;); if (mode == OS_AIO_SYNC #ifdef WIN_ASYNC_IO @@ -4639,7 +4639,11 @@ os_aio_func( ret = os_file_write_func(name, file, buf, offset, n); DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28", - os_has_said_disk_full = TRUE; ret = 0; errno = 28;); + os_has_said_disk_full = FALSE; ret = 0; errno = 28;); + + if (!ret) { + os_file_handle_error_cond_exit(name, "os_file_write_func", TRUE, FALSE); + } } return ret; @@ -5463,9 +5467,14 @@ consecutive_loop: aio_slot->offset, total_len); DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28", - os_has_said_disk_full = TRUE; + os_has_said_disk_full = FALSE; ret = 0; errno = 28;); + + if (!ret) { + os_file_handle_error_cond_exit(aio_slot->name, "os_file_write_func", TRUE, FALSE); + } + } else { ret = os_file_read( aio_slot->file, combined_buf, diff --git a/storage/xtradb/btr/btr0btr.cc b/storage/xtradb/btr/btr0btr.cc index 1da487f1400..d240188e772 100644 --- a/storage/xtradb/btr/btr0btr.cc +++ b/storage/xtradb/btr/btr0btr.cc @@ -3097,12 +3097,6 @@ func_start: /* 2. Allocate a new page to the index */ new_block = btr_page_alloc(cursor->index, hint_page_no, direction, btr_page_get_level(page, mtr), mtr, mtr); - - /* Play safe, if new page is not allocated */ - if (!new_block) { - return(rec); - } - new_page = buf_block_get_frame(new_block); new_page_zip = buf_block_get_page_zip(new_block); btr_page_create(new_block, new_page_zip, cursor->index, diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 3441fe04006..bb58a92ed1a 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -128,6 +128,7 @@ my_error_innodb( break; case DB_OUT_OF_FILE_SPACE: my_error(ER_RECORD_FILE_FULL, MYF(0), table); + ut_error; break; case DB_TEMP_FILE_WRITE_FAILURE: my_error(ER_GET_ERRMSG, MYF(0), diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index 112581442ab..a88c344a6ee 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -716,6 +716,7 @@ os_file_handle_error_cond_exit( fflush(stderr); + ut_error; return(FALSE); case OS_FILE_AIO_RESOURCES_RESERVED: @@ -4735,7 +4736,7 @@ os_aio_func( mode = mode & (~OS_AIO_SIMULATED_WAKE_LATER); DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28", - mode = OS_AIO_SYNC; os_has_said_disk_full = TRUE;); + mode = OS_AIO_SYNC; os_has_said_disk_full = FALSE;); if (mode == OS_AIO_SYNC) { ibool ret; @@ -4751,7 +4752,11 @@ os_aio_func( ret = os_file_write(name, file, buf, offset, n); DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28", - os_has_said_disk_full = TRUE; ret = 0; errno = 28;); + os_has_said_disk_full = FALSE; ret = 0; errno = 28;); + + if (!ret) { + os_file_handle_error_cond_exit(name, "os_file_write_func", TRUE, FALSE); + } } if (!ret) { @@ -5582,7 +5587,12 @@ consecutive_loop: aio_slot->offset, total_len); DBUG_EXECUTE_IF("ib_os_aio_func_io_failure_28", - os_has_said_disk_full = TRUE; ret = 0; errno = 28;); + os_has_said_disk_full = FALSE; ret = 0; errno = 28;); + + if (!ret) { + os_file_handle_error_cond_exit(aio_slot->name, "os_file_write_func", TRUE, FALSE); + } + } else { ret = os_file_read( aio_slot->file, combined_buf, From ed04c40b01c122436eda6552c550d62ce8a3920b Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Wed, 11 Mar 2015 09:18:16 +0100 Subject: [PATCH 6/7] MDEV-5289: master server starts slave parallel threads Delay spawning parallel replication worker threads until a slave SQL thread is running, and de-spawn them when the last SQL thread stops. This is especially useful to avoid needless threads on a master in a setup where same my.cnf is used on masters and slaves. --- mysql-test/suite/rpl/r/rpl_parallel.result | 14 +++++ mysql-test/suite/rpl/t/rpl_parallel.test | 11 ++++ .../r/slave_parallel_threads_basic.result | 15 ++++- .../t/slave_parallel_threads_basic.cnf | 5 ++ .../t/slave_parallel_threads_basic.test | 9 ++- sql/rpl_mi.cc | 28 ++++++++- sql/rpl_mi.h | 1 + sql/rpl_parallel.cc | 63 ++++++++----------- sql/rpl_parallel.h | 6 +- sql/slave.cc | 9 ++- sql/sys_vars.cc | 8 +-- 11 files changed, 116 insertions(+), 53 deletions(-) create mode 100644 mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.cnf diff --git a/mysql-test/suite/rpl/r/rpl_parallel.result b/mysql-test/suite/rpl/r/rpl_parallel.result index 3c66a541cc1..499ca23a645 100644 --- a/mysql-test/suite/rpl/r/rpl_parallel.result +++ b/mysql-test/suite/rpl/r/rpl_parallel.result @@ -4,8 +4,22 @@ SET GLOBAL slave_parallel_threads=10; ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first include/stop_slave.inc SET GLOBAL slave_parallel_threads=10; +SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; +IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) +OK CHANGE MASTER TO master_use_gtid=slave_pos; include/start_slave.inc +SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; +IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) +OK +include/stop_slave.inc +SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; +IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) +OK +include/start_slave.inc +SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; +IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) +OK *** Test long-running query in domain 1 can run in parallel with short queries in domain 0 *** ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; CREATE TABLE t1 (a int PRIMARY KEY) ENGINE=MyISAM; diff --git a/mysql-test/suite/rpl/t/rpl_parallel.test b/mysql-test/suite/rpl/t/rpl_parallel.test index 7397ede14b3..cafdffe81ac 100644 --- a/mysql-test/suite/rpl/t/rpl_parallel.test +++ b/mysql-test/suite/rpl/t/rpl_parallel.test @@ -12,9 +12,20 @@ SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads; SET GLOBAL slave_parallel_threads=10; --source include/stop_slave.inc SET GLOBAL slave_parallel_threads=10; + +# Check that we do not spawn any worker threads when no slave is running. +SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; + CHANGE MASTER TO master_use_gtid=slave_pos; --source include/start_slave.inc +# Check that worker threads get spawned when slave starts. +SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; +# ... and that worker threads get removed when slave stops. +--source include/stop_slave.inc +SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; +--source include/start_slave.inc +SELECT IF(COUNT(*) >= 10, "OK", CONCAT("Found too few system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; --echo *** Test long-running query in domain 1 can run in parallel with short queries in domain 0 *** diff --git a/mysql-test/suite/sys_vars/r/slave_parallel_threads_basic.result b/mysql-test/suite/sys_vars/r/slave_parallel_threads_basic.result index 2956d04c065..56aa5976f91 100644 --- a/mysql-test/suite/sys_vars/r/slave_parallel_threads_basic.result +++ b/mysql-test/suite/sys_vars/r/slave_parallel_threads_basic.result @@ -1,13 +1,22 @@ SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads; -SELECT @@GLOBAL.slave_parallel_threads as 'must be zero because of default'; -must be zero because of default -0 +SELECT IF(COUNT(*) < 20, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; +IF(COUNT(*) < 20, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) +OK +SELECT @@GLOBAL.slave_parallel_threads as 'must be 20 because of .cnf'; +must be 20 because of .cnf +20 SELECT @@SESSION.slave_parallel_threads as 'no session var'; ERROR HY000: Variable 'slave_parallel_threads' is a GLOBAL variable SET GLOBAL slave_parallel_threads= 0; SET GLOBAL slave_parallel_threads= DEFAULT; +SELECT @@GLOBAL.slave_parallel_threads as 'must be 0 because of default'; +must be 0 because of default +0 SET GLOBAL slave_parallel_threads= 10; SELECT @@GLOBAL.slave_parallel_threads; @@GLOBAL.slave_parallel_threads 10 +SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; +IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) +OK SET GLOBAL slave_parallel_threads = @save_slave_parallel_threads; diff --git a/mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.cnf b/mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.cnf new file mode 100644 index 00000000000..02bdb44e1de --- /dev/null +++ b/mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.cnf @@ -0,0 +1,5 @@ +# Use default setting for mysqld processes +!include include/default_mysqld.cnf + +[mysqld.1] +slave_parallel_threads=20 diff --git a/mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.test b/mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.test index 8e987489d86..b567b7f8854 100644 --- a/mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.test +++ b/mysql-test/suite/sys_vars/t/slave_parallel_threads_basic.test @@ -2,13 +2,20 @@ SET @save_slave_parallel_threads= @@GLOBAL.slave_parallel_threads; -SELECT @@GLOBAL.slave_parallel_threads as 'must be zero because of default'; +# Check that we don't spawn worker threads at server startup, when no +# slave is configured (MDEV-5289). +SELECT IF(COUNT(*) < 20, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; + +SELECT @@GLOBAL.slave_parallel_threads as 'must be 20 because of .cnf'; --error ER_INCORRECT_GLOBAL_LOCAL_VAR SELECT @@SESSION.slave_parallel_threads as 'no session var'; SET GLOBAL slave_parallel_threads= 0; SET GLOBAL slave_parallel_threads= DEFAULT; +SELECT @@GLOBAL.slave_parallel_threads as 'must be 0 because of default'; SET GLOBAL slave_parallel_threads= 10; SELECT @@GLOBAL.slave_parallel_threads; +# Check that we don't spawn worker threads when no slave is started. +SELECT IF(COUNT(*) < 10, "OK", CONCAT("Found too many system user processes: ", COUNT(*))) FROM information_schema.processlist WHERE user = "system user"; SET GLOBAL slave_parallel_threads = @save_slave_parallel_threads; diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc index 081265ccf58..50cd44df824 100644 --- a/sql/rpl_mi.cc +++ b/sql/rpl_mi.cc @@ -1248,7 +1248,7 @@ bool Master_info_index::remove_master_info(LEX_STRING *name) bool Master_info_index::give_error_if_slave_running() { - DBUG_ENTER("warn_if_slave_running"); + DBUG_ENTER("give_error_if_slave_running"); mysql_mutex_assert_owner(&LOCK_active_mi); if (!this) // master_info_index is set to NULL on server shutdown return TRUE; @@ -1268,6 +1268,32 @@ bool Master_info_index::give_error_if_slave_running() } +/** + Master_info_index::any_slave_sql_running() + + The LOCK_active_mi must be held while calling this function. + + @return + TRUE If some slave SQL thread is running. + FALSE No slave SQL thread is running +*/ + +bool Master_info_index::any_slave_sql_running() +{ + DBUG_ENTER("any_slave_sql_running"); + if (!this) // master_info_index is set to NULL on server shutdown + return TRUE; + + for (uint i= 0; i< master_info_hash.records; ++i) + { + Master_info *mi= (Master_info *)my_hash_element(&master_info_hash, i); + if (mi->rli.slave_running != MYSQL_SLAVE_NOT_RUN) + DBUG_RETURN(TRUE); + } + DBUG_RETURN(FALSE); +} + + /** Master_info_index::start_all_slaves() diff --git a/sql/rpl_mi.h b/sql/rpl_mi.h index ebb1b541728..2b0b40feb3d 100644 --- a/sql/rpl_mi.h +++ b/sql/rpl_mi.h @@ -218,6 +218,7 @@ public: Master_info *get_master_info(LEX_STRING *connection_name, Sql_condition::enum_warning_level warning); bool give_error_if_slave_running(); + bool any_slave_sql_running(); bool start_all_slaves(THD *thd); bool stop_all_slaves(THD *thd); }; diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index ec177280fea..2f47ad8892b 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -944,9 +944,9 @@ dealloc_gco(group_commit_orderer *gco) } -int +static int rpl_parallel_change_thread_count(rpl_parallel_thread_pool *pool, - uint32 new_count, bool skip_check) + uint32 new_count) { uint32 i; rpl_parallel_thread **new_list= NULL; @@ -991,24 +991,6 @@ rpl_parallel_change_thread_count(rpl_parallel_thread_pool *pool, new_free_list= new_list[i]; } - if (!skip_check) - { - mysql_mutex_lock(&LOCK_active_mi); - if (master_info_index->give_error_if_slave_running()) - { - mysql_mutex_unlock(&LOCK_active_mi); - goto err; - } - if (pool->changing) - { - mysql_mutex_unlock(&LOCK_active_mi); - my_error(ER_CHANGE_SLAVE_PARALLEL_THREADS_ACTIVE, MYF(0)); - goto err; - } - pool->changing= true; - mysql_mutex_unlock(&LOCK_active_mi); - } - /* Grab each old thread in turn, and signal it to stop. @@ -1068,13 +1050,6 @@ rpl_parallel_change_thread_count(rpl_parallel_thread_pool *pool, mysql_mutex_unlock(&pool->threads[i]->LOCK_rpl_thread); } - if (!skip_check) - { - mysql_mutex_lock(&LOCK_active_mi); - pool->changing= false; - mysql_mutex_unlock(&LOCK_active_mi); - } - mysql_mutex_lock(&pool->LOCK_rpl_thread_pool); mysql_cond_broadcast(&pool->COND_rpl_thread_pool); mysql_mutex_unlock(&pool->LOCK_rpl_thread_pool); @@ -1101,16 +1076,26 @@ err: } my_free(new_list); } - if (!skip_check) - { - mysql_mutex_lock(&LOCK_active_mi); - pool->changing= false; - mysql_mutex_unlock(&LOCK_active_mi); - } return 1; } +int +rpl_parallel_activate_pool(rpl_parallel_thread_pool *pool) +{ + if (!pool->count) + return rpl_parallel_change_thread_count(pool, opt_slave_parallel_threads); + return 0; +} + + +int +rpl_parallel_inactivate_pool(rpl_parallel_thread_pool *pool) +{ + return rpl_parallel_change_thread_count(pool, 0); +} + + void rpl_parallel_thread::batch_free() { @@ -1354,7 +1339,7 @@ rpl_parallel_thread::loc_free_gco(group_commit_orderer *gco) rpl_parallel_thread_pool::rpl_parallel_thread_pool() - : count(0), threads(0), free_list(0), changing(false), inited(false) + : count(0), threads(0), free_list(0), inited(false) { } @@ -1369,10 +1354,14 @@ rpl_parallel_thread_pool::init(uint32 size) mysql_mutex_init(key_LOCK_rpl_thread_pool, &LOCK_rpl_thread_pool, MY_MUTEX_INIT_SLOW); mysql_cond_init(key_COND_rpl_thread_pool, &COND_rpl_thread_pool, NULL); - changing= false; inited= true; - return rpl_parallel_change_thread_count(this, size, true); + /* + The pool is initially empty. Threads will be spawned when a slave SQL + thread is started. + */ + + return 0; } @@ -1381,7 +1370,7 @@ rpl_parallel_thread_pool::destroy() { if (!inited) return; - rpl_parallel_change_thread_count(this, 0, true); + rpl_parallel_change_thread_count(this, 0); mysql_mutex_destroy(&LOCK_rpl_thread_pool); mysql_cond_destroy(&COND_rpl_thread_pool); inited= false; diff --git a/sql/rpl_parallel.h b/sql/rpl_parallel.h index d60b2200c17..00421d6f5c9 100644 --- a/sql/rpl_parallel.h +++ b/sql/rpl_parallel.h @@ -204,7 +204,6 @@ struct rpl_parallel_thread_pool { struct rpl_parallel_thread *free_list; mysql_mutex_t LOCK_rpl_thread_pool; mysql_cond_t COND_rpl_thread_pool; - bool changing; bool inited; rpl_parallel_thread_pool(); @@ -314,9 +313,8 @@ struct rpl_parallel { extern struct rpl_parallel_thread_pool global_rpl_thread_pool; -extern int rpl_parallel_change_thread_count(rpl_parallel_thread_pool *pool, - uint32 new_count, - bool skip_check= false); +extern int rpl_parallel_activate_pool(rpl_parallel_thread_pool *pool); +extern int rpl_parallel_inactivate_pool(rpl_parallel_thread_pool *pool); extern bool process_gtid_for_restart_pos(Relay_log_info *rli, rpl_gtid *gtid); #endif /* RPL_PARALLEL_H */ diff --git a/sql/slave.cc b/sql/slave.cc index 1e1edcbe7c9..703338c435c 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -652,6 +652,10 @@ int terminate_slave_threads(Master_info* mi,int thread_mask,bool skip_lock) DBUG_RETURN(ER_ERROR_DURING_FLUSH_LOGS); mysql_mutex_unlock(log_lock); + + if (opt_slave_parallel_threads > 0 && + !master_info_index->any_slave_sql_running()) + rpl_parallel_inactivate_pool(&global_rpl_thread_pool); } if (thread_mask & (SLAVE_IO|SLAVE_FORCE_ALL)) { @@ -958,7 +962,10 @@ int start_slave_threads(bool need_slave_mutex, bool wait_for_start, mi); if (!error && (thread_mask & SLAVE_SQL)) { - error= start_slave_thread( + if (opt_slave_parallel_threads > 0) + error= rpl_parallel_activate_pool(&global_rpl_thread_pool); + if (!error) + error= start_slave_thread( #ifdef HAVE_PSI_INTERFACE key_thread_slave_sql, #endif diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index f1942d08591..31bd712ee67 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1752,16 +1752,12 @@ check_slave_parallel_threads(sys_var *self, THD *thd, set_var *var) static bool fix_slave_parallel_threads(sys_var *self, THD *thd, enum_var_type type) { - bool running; - bool err= false; + bool err; mysql_mutex_unlock(&LOCK_global_system_variables); mysql_mutex_lock(&LOCK_active_mi); - running= master_info_index->give_error_if_slave_running(); + err= master_info_index->give_error_if_slave_running(); mysql_mutex_unlock(&LOCK_active_mi); - if (running || rpl_parallel_change_thread_count(&global_rpl_thread_pool, - opt_slave_parallel_threads)) - err= true; mysql_mutex_lock(&LOCK_global_system_variables); return err; From 702fdc52fa02c5f20004d169ad48494122d8ffed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 12 Mar 2015 18:37:32 +0200 Subject: [PATCH 7/7] MDEV-7714: Make possible to get innodb internal primary key for wrapper type storage engine. Authored by: Kentoku Shiba --- storage/innobase/row/row0mysql.cc | 5 +++++ storage/xtradb/row/row0mysql.cc | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index fb632d1347e..be2646d4fc4 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -1461,6 +1461,11 @@ error_exit: with a latch. */ dict_table_n_rows_inc(table); + if (prebuilt->clust_index_was_generated) { + /* set row id to prebuilt */ + ut_memcpy(prebuilt->row_id, node->row_id_buf, DATA_ROW_ID_LEN); + } + row_update_statistics_if_needed(table); trx->op_info = ""; diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index ec4f865c6b3..fefd295f79d 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -1455,6 +1455,11 @@ error_exit: srv_stats.n_rows_inserted.add((size_t)trx->id, 1); } + if (prebuilt->clust_index_was_generated) { + /* set row id to prebuilt */ + ut_memcpy(prebuilt->row_id, node->row_id_buf, DATA_ROW_ID_LEN); + } + /* Not protected by dict_table_stats_lock() for performance reasons, we would rather get garbage in stat_n_rows (which is just an estimate anyway) than protecting the following code