diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2021-01-28 14:15:01 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2021-01-28 14:15:01 +0200 |
commit | 6d1f1b61b59310027698a92ccf533a3093f1ce04 (patch) | |
tree | d2fbe999dc4df7ebbf2e4c6b20e3f902a0ddffb4 | |
parent | 744e9752d887c3be20c655d882f6ec1b7e0fd727 (diff) | |
download | mariadb-git-6d1f1b61b59310027698a92ccf533a3093f1ce04.tar.gz |
MDEV-24564 Statistics are lost after ALTER TABLEbb-10.5-MDEV-24564
Ever since commit 007f68c37f6b77588866a04d7515aca084ab950d,
ALTER TABLE no longer invokes handler::open() after
handler::commit_inplace_alter_table().
ha_innobase::reload_statistics(): Reload or recompute statistics
after ALTER TABLE.
innodb_notify_tabledef_changed(): A new function to invoke
ha_innobase::reload_statistics().
handlerton::notify_tabledef_changed(): Add the parameter handler*
so that ha_innobase::reload_statistics() can be invoked.
ha_partition::notify_tabledef_changed(),
partition_notify_tabledef_changed(): Pass through the call
to any partitions or subpartitions.
This is based on code that was supplied by Monty.
-rw-r--r-- | mysql-test/suite/gcol/r/innodb_virtual_stats.result | 16 | ||||
-rw-r--r-- | mysql-test/suite/gcol/t/innodb_virtual_stats.test | 1 | ||||
-rw-r--r-- | sql/ha_partition.cc | 78 | ||||
-rw-r--r-- | sql/ha_partition.h | 5 | ||||
-rw-r--r-- | sql/handler.h | 5 | ||||
-rw-r--r-- | sql/sql_table.cc | 15 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 26 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.h | 4 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 14 | ||||
-rw-r--r-- | storage/maria/ha_s3.cc | 12 |
10 files changed, 135 insertions, 41 deletions
diff --git a/mysql-test/suite/gcol/r/innodb_virtual_stats.result b/mysql-test/suite/gcol/r/innodb_virtual_stats.result index c11b02ff8cb..c0f595263df 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_stats.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_stats.result @@ -121,5 +121,19 @@ SELECT index_name, stat_name, stat_description FROM mysql.innodb_index_stats WHERE database_name = 'test' AND table_name = 't'; index_name stat_name stat_description -# MDEV-24564 FIXME: Do reload statistics after the above ALTER TABLE! +GEN_CLUST_INDEX n_diff_pfx01 DB_ROW_ID +GEN_CLUST_INDEX n_leaf_pages Number of leaf pages in the index +GEN_CLUST_INDEX size Number of pages in the index +idxb n_diff_pfx01 b +idxb n_diff_pfx02 b,DB_ROW_ID +idxb n_leaf_pages Number of leaf pages in the index +idxb size Number of pages in the index +vidxe n_diff_pfx01 e +vidxe n_diff_pfx02 e,DB_ROW_ID +vidxe n_leaf_pages Number of leaf pages in the index +vidxe size Number of pages in the index +vidxf n_diff_pfx01 f +vidxf n_diff_pfx02 f,DB_ROW_ID +vidxf n_leaf_pages Number of leaf pages in the index +vidxf size Number of pages in the index DROP TABLE t; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_stats.test b/mysql-test/suite/gcol/t/innodb_virtual_stats.test index 728f84de72c..69c67af8ed1 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_stats.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_stats.test @@ -52,6 +52,5 @@ ALTER TABLE t DROP INDEX vidxcd; SELECT index_name, stat_name, stat_description FROM mysql.innodb_index_stats WHERE database_name = 'test' AND table_name = 't'; --- echo # MDEV-24564 FIXME: Do reload statistics after the above ALTER TABLE! DROP TABLE t; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 470f59fe15f..0140a825ef5 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2005, 2019, Oracle and/or its affiliates. - Copyright (c) 2009, 2020, MariaDB + Copyright (c) 2009, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -92,6 +92,61 @@ static handler *partition_create_handler(handlerton *hton, static uint partition_flags(); static alter_table_operations alter_table_flags(alter_table_operations flags); + +int ha_partition::notify_tabledef_changed(LEX_CSTRING *db, + LEX_CSTRING *org_table_name, + LEX_CUSTRING *frm, + LEX_CUSTRING *version) +{ + char from_buff[FN_REFLEN + 1], from_lc_buff[FN_REFLEN + 1]; + const char *from_path, *name_buffer_ptr, *from; + int res= 0; + handler **file= m_file; + DBUG_ENTER("ha_partition::notify_tabledef_changed"); + + from= table->s->normalized_path.str; + + /* setup m_name_buffer_ptr */ + if (read_par_file(table->s->normalized_path.str)) + DBUG_RETURN(1); + + from_path= get_canonical_filename(*file, from, from_lc_buff); + name_buffer_ptr= m_name_buffer_ptr; + do + { + LEX_CSTRING table_name; + const char *table_name_ptr; + if (create_partition_name(from_buff, sizeof(from_buff), + from_path, name_buffer_ptr, + NORMAL_PART_NAME, FALSE)) + res=1; + table_name_ptr= from_buff + dirname_length(from_buff); + + lex_string_set3(&table_name, table_name_ptr, strlen(table_name_ptr)); + + if (((*file)->ht)->notify_tabledef_changed((*file)->ht, db, &table_name, + frm, version, *file)) + res=1; + name_buffer_ptr= strend(name_buffer_ptr) + 1; + } while (*(++file)); + DBUG_RETURN(res); +} + + +static int +partition_notify_tabledef_changed(handlerton *, + LEX_CSTRING *db, + LEX_CSTRING *table, + LEX_CUSTRING *frm, + LEX_CUSTRING *version, + handler *file) +{ + DBUG_ENTER("partition_notify_tabledef_changed"); + DBUG_RETURN(static_cast<ha_partition*> + (file)->notify_tabledef_changed(db, table, frm, version)); +} + + /* If frm_error() is called then we will use this to to find out what file extensions exist for the storage engine. This is also used by the default @@ -149,7 +204,9 @@ static int partition_initialize(void *p) partition_hton->db_type= DB_TYPE_PARTITION_DB; partition_hton->create= partition_create_handler; + partition_hton->partition_flags= partition_flags; + partition_hton->notify_tabledef_changed= partition_notify_tabledef_changed; partition_hton->alter_table_flags= alter_table_flags; partition_hton->flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN | @@ -211,25 +268,6 @@ static handler *partition_create_handler(handlerton *hton, return file; } -/* - HA_CAN_PARTITION: - Used by storage engines that can handle partitioning without this - partition handler - (Partition, NDB) - - HA_CAN_UPDATE_PARTITION_KEY: - Set if the handler can update fields that are part of the partition - function. - - HA_CAN_PARTITION_UNIQUE: - Set if the handler can handle unique indexes where the fields of the - unique key are not part of the fields of the partition function. Thus - a unique key can be set on all fields. - - HA_USE_AUTO_PARTITION - Set if the handler sets all tables to be partitioned by default. -*/ - static uint partition_flags() { return HA_CAN_PARTITION; diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 3c3e394d59f..60a2d7f6762 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -3,7 +3,7 @@ /* Copyright (c) 2005, 2012, Oracle and/or its affiliates. - Copyright (c) 2009, 2020, MariaDB Corporation. + Copyright (c) 2009, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1617,6 +1617,9 @@ public: return part_recs; } + int notify_tabledef_changed(LEX_CSTRING *db, LEX_CSTRING *table, + LEX_CUSTRING *frm, LEX_CUSTRING *version); + friend int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2); friend int cmp_key_part_id(void *key_p, uchar *ref1, uchar *ref2); bool can_convert_string( diff --git a/sql/handler.h b/sql/handler.h index 4e1e3f0413f..d115fdddddc 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -2,7 +2,7 @@ #define HANDLER_INCLUDED /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. - Copyright (c) 2009, 2020, MariaDB + Copyright (c) 2009, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -1681,7 +1681,8 @@ struct handlerton */ int (*notify_tabledef_changed)(handlerton *hton, LEX_CSTRING *db, LEX_CSTRING *table_name, LEX_CUSTRING *frm, - LEX_CUSTRING *org_tabledef_version); + LEX_CUSTRING *org_tabledef_version, + handler *file); /* System Versioning diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 6825fbc8e24..116bfa7fd1c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. - Copyright (c) 2010, 2020, MariaDB + Copyright (c) 2010, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -7934,7 +7934,6 @@ static bool mysql_inplace_alter_table(THD *thd, Alter_info *alter_info= ha_alter_info->alter_info; bool reopen_tables= false; bool res; - handlerton *hton; const enum_alter_inplace_result inplace_supported= ha_alter_info->inplace_supported; @@ -8145,20 +8144,22 @@ static bool mysql_inplace_alter_table(THD *thd, /* Notify the engine that the table definition has changed */ - hton= table->file->partition_ht(); - if (hton->notify_tabledef_changed) + if (table->file->partition_ht()->notify_tabledef_changed) { char db_buff[FN_REFLEN], table_buff[FN_REFLEN]; + handlerton *hton= table->file->ht; LEX_CSTRING tmp_db, tmp_table; - tmp_db.str= db_buff; - tmp_table.str= table_buff; + + tmp_db.str= db_buff; + tmp_table.str= table_buff; tmp_db.length= tablename_to_filename(table_list->db.str, db_buff, sizeof(db_buff)); tmp_table.length= tablename_to_filename(table_list->table_name.str, table_buff, sizeof(table_buff)); if ((hton->notify_tabledef_changed)(hton, &tmp_db, &tmp_table, table->s->frm_image, - &table->s->tabledef_version)) + &table->s->tabledef_version, + table->file)) { my_error(HA_ERR_INCOMPATIBLE_DEFINITION, MYF(0)); DBUG_RETURN(true); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index dd52fee3f9b..5e9a7d951e3 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -1330,6 +1330,30 @@ innobase_show_status( stat_print_fn* stat_print, enum ha_stat_type stat_type); +/** After ALTER TABLE, recompute statistics. */ +inline void ha_innobase::reload_statistics() +{ + if (dict_table_t *table= m_prebuilt ? m_prebuilt->table : nullptr) + { + if (table->is_readable()) + dict_stats_init(table); + else + table->stat_initialized= 1; + } +} + +/** After ALTER TABLE, recompute statistics. */ +static int innodb_notify_tabledef_changed(handlerton *, + LEX_CSTRING *, LEX_CSTRING *, + LEX_CUSTRING *, LEX_CUSTRING *, + handler *handler) +{ + DBUG_ENTER("innodb_notify_tabledef_changed"); + if (handler) + static_cast<ha_innobase*>(handler)->reload_statistics(); + DBUG_RETURN(0); +} + /****************************************************************//** Parse and enable InnoDB monitor counters during server startup. User can enable monitor counters/groups by specifying @@ -3816,6 +3840,7 @@ static int innodb_init(void* p) innobase_hton->flush_logs = innobase_flush_logs; innobase_hton->show_status = innobase_show_status; + innobase_hton->notify_tabledef_changed= innodb_notify_tabledef_changed; innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS | HTON_NATIVE_SYS_VERSIONING | HTON_WSREP_REPLICATION; @@ -16233,6 +16258,7 @@ innobase_show_status( /* Success */ return(false); } + /*********************************************************************//** Returns number of THR_LOCK locks used for one instance of InnoDB table. InnoDB no longer relies on THR_LOCK locks so 0 value is returned. diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index b47acae01f2..d8277a7a5a8 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2020, MariaDB Corporation. +Copyright (c) 2013, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -211,6 +211,8 @@ public: int check(THD* thd, HA_CHECK_OPT* check_opt) override; char* update_table_comment(const char* comment) override; + inline void reload_statistics(); + char* get_foreign_key_create_info() override; int get_foreign_key_list(THD *thd, diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 06fa442ed0e..4248442f3da 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -11263,12 +11263,18 @@ foreign_fail: && m_prebuilt->table->n_v_cols && ha_alter_info->handler_flags & ALTER_STORED_COLUMN_ORDER)) { DBUG_ASSERT(ctx0->old_table->get_ref_count() == 1); + ut_ad(ctx0->prebuilt == m_prebuilt); trx_commit_for_mysql(m_prebuilt->trx); - m_prebuilt->table = innobase_reload_table(m_user_thd, - m_prebuilt->table, - table->s->table_name, - *ctx0); + for (inplace_alter_handler_ctx** pctx = ctx_array; *pctx; + pctx++) { + auto ctx= static_cast<ha_innobase_inplace_ctx*>(*pctx); + ctx->prebuilt->table = innobase_reload_table( + m_user_thd, ctx->prebuilt->table, + table->s->table_name, *ctx0); + innobase_copy_frm_flags_from_table_share( + ctx->prebuilt->table, altered_table->s); + } row_mysql_unlock_data_dictionary(trx); trx->free(); diff --git a/storage/maria/ha_s3.cc b/storage/maria/ha_s3.cc index cf2b9098142..b27afc2fcf7 100644 --- a/storage/maria/ha_s3.cc +++ b/storage/maria/ha_s3.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2019, 2020 MariaDB Corporation Ab +/* Copyright (C) 2019, 2021 MariaDB Corporation Ab This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -887,10 +887,11 @@ int ha_s3::discover_check_version() Update the .frm file in S3 */ -static int s3_notify_tabledef_changed(handlerton *hton __attribute__((unused)), +static int s3_notify_tabledef_changed(handlerton *, LEX_CSTRING *db, LEX_CSTRING *table, LEX_CUSTRING *frm, - LEX_CUSTRING *org_tabledef_version) + LEX_CUSTRING *org_tabledef_version, + handler *) { char aws_path[AWS_PATH_LENGTH]; S3_INFO s3_info; @@ -898,6 +899,9 @@ static int s3_notify_tabledef_changed(handlerton *hton __attribute__((unused)), int error= 0; DBUG_ENTER("s3_notify_tabledef_changed"); + if (strstr(table->str, "#P#")) + DBUG_RETURN(0); // Ignore partitions + if (s3_info_init(&s3_info)) DBUG_RETURN(0); if (!(s3_client= s3_open_connection(&s3_info))) @@ -916,7 +920,7 @@ static int s3_notify_tabledef_changed(handlerton *hton __attribute__((unused)), NullS); if (s3_put_object(s3_client, s3_info.bucket.str, aws_path, (uchar*) frm->str, - frm->length, 0)) + frm->length, 0)) error= 2; err: |