From 364a20fe0b072fb1d2a9b54a8c4e47a5012f3e97 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Sat, 23 Jun 2018 19:36:26 -0700 Subject: MDEV-16507 SIGSEGV when use_stat_tables = preferably and optimizer_use_condition_selectivity = 4 It does not makes sense to try to read statistics for temporary tables because it's not collected. --- mysql-test/r/statistics.result | 20 ++++++++++++++++++++ mysql-test/t/statistics.test | 24 ++++++++++++++++++++++++ sql/sql_statistics.cc | 8 ++++---- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/statistics.result b/mysql-test/r/statistics.result index 74997c92d3e..23c8807897b 100644 --- a/mysql-test/r/statistics.result +++ b/mysql-test/r/statistics.result @@ -1659,3 +1659,23 @@ id set use_stat_tables=@save_use_stat_tables; set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1,t2; +# +# MDEV-16507: statistics for temporary tables should not be used +# +SET +@save_optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity; +SET @@use_stat_tables = preferably ; +SET @@optimizer_use_condition_selectivity = 4; +CREATE TABLE t1 ( +TIMESTAMP TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP +ON UPDATE CURRENT_TIMESTAMP +); +SET @had_t1_table= @@warning_count != 0; +CREATE TEMPORARY TABLE tmp_t1 LIKE t1; +INSERT INTO tmp_t1 VALUES (now()); +INSERT INTO t1 SELECT * FROM tmp_t1 WHERE @had_t1_table=0; +DROP TABLE t1; +SET +use_stat_tables=@save_use_stat_tables; +SET +optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; diff --git a/mysql-test/t/statistics.test b/mysql-test/t/statistics.test index 0ab42453125..5831e0b1d60 100644 --- a/mysql-test/t/statistics.test +++ b/mysql-test/t/statistics.test @@ -737,3 +737,27 @@ set use_stat_tables=@save_use_stat_tables; set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; drop table t1,t2; +--echo # +--echo # MDEV-16507: statistics for temporary tables should not be used +--echo # + +SET +@save_optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity; +SET @@use_stat_tables = preferably ; +SET @@optimizer_use_condition_selectivity = 4; + +CREATE TABLE t1 ( + TIMESTAMP TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP + ON UPDATE CURRENT_TIMESTAMP +); + +SET @had_t1_table= @@warning_count != 0; +CREATE TEMPORARY TABLE tmp_t1 LIKE t1; +INSERT INTO tmp_t1 VALUES (now()); +INSERT INTO t1 SELECT * FROM tmp_t1 WHERE @had_t1_table=0; +DROP TABLE t1; + +SET +use_stat_tables=@save_use_stat_tables; +SET +optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity; diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 471749ad346..1febc02b903 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -2952,7 +2952,7 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables) for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) { - if (!tl->is_view_or_derived() && tl->table) + if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table) { TABLE_SHARE *table_share= tl->table->s; if (table_share && @@ -2964,7 +2964,7 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables) for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) { - if (!tl->is_view_or_derived() && tl->table) + if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table) { TABLE_SHARE *table_share= tl->table->s; if (table_share && @@ -3093,7 +3093,7 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables) for (TABLE_LIST *tl= tables; tl; tl= tl->next_global) { - if (!tl->is_view_or_derived() && tl->table) + if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table) { TABLE_SHARE *table_share= tl->table->s; if (table_share && @@ -3867,4 +3867,4 @@ bool is_stat_table(const char *db, const char *table) } } return false; -} \ No newline at end of file +} -- cgit v1.2.1 From 28e1f1453f12b8b748c31a86a22b336f62002654 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Tue, 19 Jun 2018 18:14:47 +0300 Subject: MDEV-15242 Poor RBR update performance with partitioned tables Observed and described partitioned engine execution time difference between master and slave was caused by excessive invocation of base_engine::rnd_init which was done also for partitions uninvolved into Rows-event operation. The bug's slave slowdown therefore scales with the number of partitions. Fixed with applying an upstream patch. References: ---------- https://bugs.mysql.com/bug.php?id=73648 Bug#25687813 REPLICATION REGRESSION WITH RBR AND PARTITIONED TABLES --- sql/ha_partition.cc | 3 ++- sql/handler.h | 10 +++++++++- sql/log_event.cc | 4 ---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 6a6627f9276..0488ebfb60f 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -5090,7 +5090,8 @@ int ha_partition::rnd_pos_by_record(uchar *record) if (unlikely(get_part_for_delete(record, m_rec0, m_part_info, &m_last_part))) DBUG_RETURN(1); - DBUG_RETURN(handler::rnd_pos_by_record(record)); + int err= m_file[m_last_part]->rnd_pos_by_record(record); + DBUG_RETURN(err); } diff --git a/sql/handler.h b/sql/handler.h index 74d50536ec4..52396b84c0d 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -3042,9 +3042,17 @@ private: */ virtual int rnd_pos_by_record(uchar *record) { + int error; DBUG_ASSERT(table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION); + + error = ha_rnd_init(false); + if (error != 0) + return error; + position(record); - return rnd_pos(record, ref); + error = ha_rnd_pos(record, ref); + ha_rnd_end(); + return error; } virtual int read_first_row(uchar *buf, uint primary_key); public: diff --git a/sql/log_event.cc b/sql/log_event.cc index 7989db9c687..3638269cbf5 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -12135,10 +12135,6 @@ int Rows_log_event::find_row(rpl_group_info *rgi) int error; DBUG_PRINT("info",("locating record using primary key (position)")); - if (!table->file->inited && - (error= table->file->ha_rnd_init_with_error(0))) - DBUG_RETURN(error); - error= table->file->ha_rnd_pos_by_record(table->record[0]); if (error) { -- cgit v1.2.1 From ff8b3c8df89e973f3b91fa82a5fec65ef0e01c53 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Sat, 23 Jun 2018 13:49:36 +0300 Subject: MDEV-15953 Alter InnoDB Partitioned Table Moves Files (which were originally not in the datadir) to the datadir ha_innobase::prepare_inplace_alter_table: preserve DATA DICTIONARY for table --- .../parts/r/alter_data_directory_innodb.result | 65 ++++++++++++++++++++++ .../suite/parts/t/alter_data_directory_innodb.test | 46 +++++++++++++++ storage/innobase/handler/handler0alter.cc | 6 ++ storage/xtradb/handler/handler0alter.cc | 6 ++ 4 files changed, 123 insertions(+) create mode 100644 mysql-test/suite/parts/r/alter_data_directory_innodb.result create mode 100644 mysql-test/suite/parts/t/alter_data_directory_innodb.test diff --git a/mysql-test/suite/parts/r/alter_data_directory_innodb.result b/mysql-test/suite/parts/r/alter_data_directory_innodb.result new file mode 100644 index 00000000000..ee0a7b80ebb --- /dev/null +++ b/mysql-test/suite/parts/r/alter_data_directory_innodb.result @@ -0,0 +1,65 @@ +# +# MDEV-15953 Alter InnoDB Partitioned Table Moves Files (which were originally not in the datadir) to the datadir +# +CREATE TABLE t ( +a INT NOT NULL +) ENGINE=INNODB +PARTITION BY HASH (a) ( +PARTITION p1 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here/' ENGINE = INNODB, +PARTITION p2 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here/' ENGINE = INNODB +); +INSERT INTO t VALUES (1); +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY HASH (a) +(PARTITION p1 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here' ENGINE = InnoDB, + PARTITION p2 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here' ENGINE = InnoDB) */ +ALTER TABLE t ADD PRIMARY KEY pk(a), ALGORITHM=INPLACE; +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY HASH (a) +(PARTITION p1 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here' ENGINE = InnoDB, + PARTITION p2 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here' ENGINE = InnoDB) */ +ALTER TABLE t DROP PRIMARY KEY, ALGORITHM=COPY; +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY HASH (a) +(PARTITION p1 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here' ENGINE = InnoDB, + PARTITION p2 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here' ENGINE = InnoDB) */ +SET @TMP = @@GLOBAL.INNODB_FILE_PER_TABLE; +SET GLOBAL INNODB_FILE_PER_TABLE=OFF; +ALTER TABLE t ADD PRIMARY KEY pk(a), ALGORITHM=INPLACE; +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY HASH (a) +(PARTITION p1 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here' ENGINE = InnoDB, + PARTITION p2 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here' ENGINE = InnoDB) */ +SET GLOBAL INNODB_FILE_PER_TABLE=@TMP; +ALTER TABLE t REORGANIZE PARTITION p1,p2 INTO ( +PARTITION p1 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_somewhere_else/' ENGINE = INNODB, +PARTITION p2 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_somewhere_else/' ENGINE = INNODB +); +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) NOT NULL, + PRIMARY KEY (`a`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY HASH (a) +(PARTITION p1 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here' ENGINE = InnoDB, + PARTITION p2 DATA DIRECTORY = 'MYSQLTEST_VARDIR/tmp/partitions_here' ENGINE = InnoDB) */ +DROP TABLE t; diff --git a/mysql-test/suite/parts/t/alter_data_directory_innodb.test b/mysql-test/suite/parts/t/alter_data_directory_innodb.test new file mode 100644 index 00000000000..ac15e9bec6c --- /dev/null +++ b/mysql-test/suite/parts/t/alter_data_directory_innodb.test @@ -0,0 +1,46 @@ +--source include/have_innodb.inc +--source include/have_partition.inc + +--echo # +--echo # MDEV-15953 Alter InnoDB Partitioned Table Moves Files (which were originally not in the datadir) to the datadir +--echo # + +mkdir $MYSQLTEST_VARDIR/tmp/partitions_here; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval CREATE TABLE t ( + a INT NOT NULL +) ENGINE=INNODB +PARTITION BY HASH (a) ( + PARTITION p1 DATA DIRECTORY = '$MYSQLTEST_VARDIR/tmp/partitions_here/' ENGINE = INNODB, + PARTITION p2 DATA DIRECTORY = '$MYSQLTEST_VARDIR/tmp/partitions_here/' ENGINE = INNODB +); +INSERT INTO t VALUES (1); + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +SHOW CREATE TABLE t; +ALTER TABLE t ADD PRIMARY KEY pk(a), ALGORITHM=INPLACE; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +SHOW CREATE TABLE t; +ALTER TABLE t DROP PRIMARY KEY, ALGORITHM=COPY; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +SHOW CREATE TABLE t; +SET @TMP = @@GLOBAL.INNODB_FILE_PER_TABLE; +SET GLOBAL INNODB_FILE_PER_TABLE=OFF; +ALTER TABLE t ADD PRIMARY KEY pk(a), ALGORITHM=INPLACE; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +SHOW CREATE TABLE t; +SET GLOBAL INNODB_FILE_PER_TABLE=@TMP; + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval ALTER TABLE t REORGANIZE PARTITION p1,p2 INTO ( + PARTITION p1 DATA DIRECTORY = '$MYSQLTEST_VARDIR/tmp/partitions_somewhere_else/' ENGINE = INNODB, + PARTITION p2 DATA DIRECTORY = '$MYSQLTEST_VARDIR/tmp/partitions_somewhere_else/' ENGINE = INNODB +); +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +SHOW CREATE TABLE t; + +DROP TABLE t; + +rmdir $MYSQLTEST_VARDIR/tmp/partitions_here/test; +rmdir $MYSQLTEST_VARDIR/tmp/partitions_here; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 86935a4aa34..3de46ed4f80 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -3572,6 +3572,12 @@ check_if_ok_to_rename: goto err_exit_no_heap; } + /* Preserve this flag, because it currenlty can't be changed during + ALTER TABLE*/ + if (flags2 & DICT_TF2_USE_TABLESPACE) { + flags |= prebuilt->table->flags & 1U << DICT_TF_POS_DATA_DIR; + } + max_col_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags); /* Check each index's column length to make sure they do not diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index ff524e6a9be..755c07848e1 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -3586,6 +3586,12 @@ check_if_ok_to_rename: goto err_exit_no_heap; } + /* Preserve this flag, because it currenlty can't be changed during + ALTER TABLE*/ + if (flags2 & DICT_TF2_USE_TABLESPACE) { + flags |= prebuilt->table->flags & 1U << DICT_TF_POS_DATA_DIR; + } + max_col_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags); /* Check each index's column length to make sure they do not -- cgit v1.2.1