Skip to content

Commit 6d1f1b6

Browse files
committed
MDEV-24564 Statistics are lost after ALTER TABLE
Ever since commit 007f68c, 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.
1 parent 744e975 commit 6d1f1b6

File tree

10 files changed

+135
-41
lines changed

10 files changed

+135
-41
lines changed

mysql-test/suite/gcol/r/innodb_virtual_stats.result

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,5 +121,19 @@ SELECT index_name, stat_name, stat_description
121121
FROM mysql.innodb_index_stats
122122
WHERE database_name = 'test' AND table_name = 't';
123123
index_name stat_name stat_description
124-
# MDEV-24564 FIXME: Do reload statistics after the above ALTER TABLE!
124+
GEN_CLUST_INDEX n_diff_pfx01 DB_ROW_ID
125+
GEN_CLUST_INDEX n_leaf_pages Number of leaf pages in the index
126+
GEN_CLUST_INDEX size Number of pages in the index
127+
idxb n_diff_pfx01 b
128+
idxb n_diff_pfx02 b,DB_ROW_ID
129+
idxb n_leaf_pages Number of leaf pages in the index
130+
idxb size Number of pages in the index
131+
vidxe n_diff_pfx01 e
132+
vidxe n_diff_pfx02 e,DB_ROW_ID
133+
vidxe n_leaf_pages Number of leaf pages in the index
134+
vidxe size Number of pages in the index
135+
vidxf n_diff_pfx01 f
136+
vidxf n_diff_pfx02 f,DB_ROW_ID
137+
vidxf n_leaf_pages Number of leaf pages in the index
138+
vidxf size Number of pages in the index
125139
DROP TABLE t;

mysql-test/suite/gcol/t/innodb_virtual_stats.test

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,5 @@ ALTER TABLE t DROP INDEX vidxcd;
5252
SELECT index_name, stat_name, stat_description
5353
FROM mysql.innodb_index_stats
5454
WHERE database_name = 'test' AND table_name = 't';
55-
-- echo # MDEV-24564 FIXME: Do reload statistics after the above ALTER TABLE!
5655

5756
DROP TABLE t;

sql/ha_partition.cc

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
Copyright (c) 2005, 2019, Oracle and/or its affiliates.
3-
Copyright (c) 2009, 2020, MariaDB
3+
Copyright (c) 2009, 2021, MariaDB
44
55
This program is free software; you can redistribute it and/or modify
66
it under the terms of the GNU General Public License as published by
@@ -92,6 +92,61 @@ static handler *partition_create_handler(handlerton *hton,
9292
static uint partition_flags();
9393
static alter_table_operations alter_table_flags(alter_table_operations flags);
9494

95+
96+
int ha_partition::notify_tabledef_changed(LEX_CSTRING *db,
97+
LEX_CSTRING *org_table_name,
98+
LEX_CUSTRING *frm,
99+
LEX_CUSTRING *version)
100+
{
101+
char from_buff[FN_REFLEN + 1], from_lc_buff[FN_REFLEN + 1];
102+
const char *from_path, *name_buffer_ptr, *from;
103+
int res= 0;
104+
handler **file= m_file;
105+
DBUG_ENTER("ha_partition::notify_tabledef_changed");
106+
107+
from= table->s->normalized_path.str;
108+
109+
/* setup m_name_buffer_ptr */
110+
if (read_par_file(table->s->normalized_path.str))
111+
DBUG_RETURN(1);
112+
113+
from_path= get_canonical_filename(*file, from, from_lc_buff);
114+
name_buffer_ptr= m_name_buffer_ptr;
115+
do
116+
{
117+
LEX_CSTRING table_name;
118+
const char *table_name_ptr;
119+
if (create_partition_name(from_buff, sizeof(from_buff),
120+
from_path, name_buffer_ptr,
121+
NORMAL_PART_NAME, FALSE))
122+
res=1;
123+
table_name_ptr= from_buff + dirname_length(from_buff);
124+
125+
lex_string_set3(&table_name, table_name_ptr, strlen(table_name_ptr));
126+
127+
if (((*file)->ht)->notify_tabledef_changed((*file)->ht, db, &table_name,
128+
frm, version, *file))
129+
res=1;
130+
name_buffer_ptr= strend(name_buffer_ptr) + 1;
131+
} while (*(++file));
132+
DBUG_RETURN(res);
133+
}
134+
135+
136+
static int
137+
partition_notify_tabledef_changed(handlerton *,
138+
LEX_CSTRING *db,
139+
LEX_CSTRING *table,
140+
LEX_CUSTRING *frm,
141+
LEX_CUSTRING *version,
142+
handler *file)
143+
{
144+
DBUG_ENTER("partition_notify_tabledef_changed");
145+
DBUG_RETURN(static_cast<ha_partition*>
146+
(file)->notify_tabledef_changed(db, table, frm, version));
147+
}
148+
149+
95150
/*
96151
If frm_error() is called then we will use this to to find out what file
97152
extensions exist for the storage engine. This is also used by the default
@@ -149,7 +204,9 @@ static int partition_initialize(void *p)
149204

150205
partition_hton->db_type= DB_TYPE_PARTITION_DB;
151206
partition_hton->create= partition_create_handler;
207+
152208
partition_hton->partition_flags= partition_flags;
209+
partition_hton->notify_tabledef_changed= partition_notify_tabledef_changed;
153210
partition_hton->alter_table_flags= alter_table_flags;
154211
partition_hton->flags= HTON_NOT_USER_SELECTABLE |
155212
HTON_HIDDEN |
@@ -211,25 +268,6 @@ static handler *partition_create_handler(handlerton *hton,
211268
return file;
212269
}
213270

214-
/*
215-
HA_CAN_PARTITION:
216-
Used by storage engines that can handle partitioning without this
217-
partition handler
218-
(Partition, NDB)
219-
220-
HA_CAN_UPDATE_PARTITION_KEY:
221-
Set if the handler can update fields that are part of the partition
222-
function.
223-
224-
HA_CAN_PARTITION_UNIQUE:
225-
Set if the handler can handle unique indexes where the fields of the
226-
unique key are not part of the fields of the partition function. Thus
227-
a unique key can be set on all fields.
228-
229-
HA_USE_AUTO_PARTITION
230-
Set if the handler sets all tables to be partitioned by default.
231-
*/
232-
233271
static uint partition_flags()
234272
{
235273
return HA_CAN_PARTITION;

sql/ha_partition.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
/*
55
Copyright (c) 2005, 2012, Oracle and/or its affiliates.
6-
Copyright (c) 2009, 2020, MariaDB Corporation.
6+
Copyright (c) 2009, 2021, MariaDB Corporation.
77
88
This program is free software; you can redistribute it and/or modify
99
it under the terms of the GNU General Public License as published by
@@ -1617,6 +1617,9 @@ class ha_partition :public handler
16171617
return part_recs;
16181618
}
16191619

1620+
int notify_tabledef_changed(LEX_CSTRING *db, LEX_CSTRING *table,
1621+
LEX_CUSTRING *frm, LEX_CUSTRING *version);
1622+
16201623
friend int cmp_key_rowid_part_id(void *ptr, uchar *ref1, uchar *ref2);
16211624
friend int cmp_key_part_id(void *key_p, uchar *ref1, uchar *ref2);
16221625
bool can_convert_string(

sql/handler.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define HANDLER_INCLUDED
33
/*
44
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
5-
Copyright (c) 2009, 2020, MariaDB
5+
Copyright (c) 2009, 2021, MariaDB
66
77
This program is free software; you can redistribute it and/or
88
modify it under the terms of the GNU General Public License
@@ -1681,7 +1681,8 @@ struct handlerton
16811681
*/
16821682
int (*notify_tabledef_changed)(handlerton *hton, LEX_CSTRING *db,
16831683
LEX_CSTRING *table_name, LEX_CUSTRING *frm,
1684-
LEX_CUSTRING *org_tabledef_version);
1684+
LEX_CUSTRING *org_tabledef_version,
1685+
handler *file);
16851686

16861687
/*
16871688
System Versioning

sql/sql_table.cc

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
Copyright (c) 2000, 2019, Oracle and/or its affiliates.
3-
Copyright (c) 2010, 2020, MariaDB
3+
Copyright (c) 2010, 2021, MariaDB
44
55
This program is free software; you can redistribute it and/or modify
66
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,
79347934
Alter_info *alter_info= ha_alter_info->alter_info;
79357935
bool reopen_tables= false;
79367936
bool res;
7937-
handlerton *hton;
79387937

79397938
const enum_alter_inplace_result inplace_supported=
79407939
ha_alter_info->inplace_supported;
@@ -8145,20 +8144,22 @@ static bool mysql_inplace_alter_table(THD *thd,
81458144

81468145
/* Notify the engine that the table definition has changed */
81478146

8148-
hton= table->file->partition_ht();
8149-
if (hton->notify_tabledef_changed)
8147+
if (table->file->partition_ht()->notify_tabledef_changed)
81508148
{
81518149
char db_buff[FN_REFLEN], table_buff[FN_REFLEN];
8150+
handlerton *hton= table->file->ht;
81528151
LEX_CSTRING tmp_db, tmp_table;
8153-
tmp_db.str= db_buff;
8154-
tmp_table.str= table_buff;
8152+
8153+
tmp_db.str= db_buff;
8154+
tmp_table.str= table_buff;
81558155
tmp_db.length= tablename_to_filename(table_list->db.str,
81568156
db_buff, sizeof(db_buff));
81578157
tmp_table.length= tablename_to_filename(table_list->table_name.str,
81588158
table_buff, sizeof(table_buff));
81598159
if ((hton->notify_tabledef_changed)(hton, &tmp_db, &tmp_table,
81608160
table->s->frm_image,
8161-
&table->s->tabledef_version))
8161+
&table->s->tabledef_version,
8162+
table->file))
81628163
{
81638164
my_error(HA_ERR_INCOMPATIBLE_DEFINITION, MYF(0));
81648165
DBUG_RETURN(true);

storage/innobase/handler/ha_innodb.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,30 @@ innobase_show_status(
13301330
stat_print_fn* stat_print,
13311331
enum ha_stat_type stat_type);
13321332

1333+
/** After ALTER TABLE, recompute statistics. */
1334+
inline void ha_innobase::reload_statistics()
1335+
{
1336+
if (dict_table_t *table= m_prebuilt ? m_prebuilt->table : nullptr)
1337+
{
1338+
if (table->is_readable())
1339+
dict_stats_init(table);
1340+
else
1341+
table->stat_initialized= 1;
1342+
}
1343+
}
1344+
1345+
/** After ALTER TABLE, recompute statistics. */
1346+
static int innodb_notify_tabledef_changed(handlerton *,
1347+
LEX_CSTRING *, LEX_CSTRING *,
1348+
LEX_CUSTRING *, LEX_CUSTRING *,
1349+
handler *handler)
1350+
{
1351+
DBUG_ENTER("innodb_notify_tabledef_changed");
1352+
if (handler)
1353+
static_cast<ha_innobase*>(handler)->reload_statistics();
1354+
DBUG_RETURN(0);
1355+
}
1356+
13331357
/****************************************************************//**
13341358
Parse and enable InnoDB monitor counters during server startup.
13351359
User can enable monitor counters/groups by specifying
@@ -3816,6 +3840,7 @@ static int innodb_init(void* p)
38163840

38173841
innobase_hton->flush_logs = innobase_flush_logs;
38183842
innobase_hton->show_status = innobase_show_status;
3843+
innobase_hton->notify_tabledef_changed= innodb_notify_tabledef_changed;
38193844
innobase_hton->flags =
38203845
HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS
38213846
| HTON_NATIVE_SYS_VERSIONING | HTON_WSREP_REPLICATION;
@@ -16233,6 +16258,7 @@ innobase_show_status(
1623316258
/* Success */
1623416259
return(false);
1623516260
}
16261+
1623616262
/*********************************************************************//**
1623716263
Returns number of THR_LOCK locks used for one instance of InnoDB table.
1623816264
InnoDB no longer relies on THR_LOCK locks so 0 value is returned.

storage/innobase/handler/ha_innodb.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2013, 2020, MariaDB Corporation.
4+
Copyright (c) 2013, 2021, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -211,6 +211,8 @@ class ha_innobase final : public handler
211211
int check(THD* thd, HA_CHECK_OPT* check_opt) override;
212212
char* update_table_comment(const char* comment) override;
213213

214+
inline void reload_statistics();
215+
214216
char* get_foreign_key_create_info() override;
215217

216218
int get_foreign_key_list(THD *thd,

storage/innobase/handler/handler0alter.cc

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11263,12 +11263,18 @@ ha_innobase::commit_inplace_alter_table(
1126311263
&& m_prebuilt->table->n_v_cols
1126411264
&& ha_alter_info->handler_flags & ALTER_STORED_COLUMN_ORDER)) {
1126511265
DBUG_ASSERT(ctx0->old_table->get_ref_count() == 1);
11266+
ut_ad(ctx0->prebuilt == m_prebuilt);
1126611267
trx_commit_for_mysql(m_prebuilt->trx);
1126711268

11268-
m_prebuilt->table = innobase_reload_table(m_user_thd,
11269-
m_prebuilt->table,
11270-
table->s->table_name,
11271-
*ctx0);
11269+
for (inplace_alter_handler_ctx** pctx = ctx_array; *pctx;
11270+
pctx++) {
11271+
auto ctx= static_cast<ha_innobase_inplace_ctx*>(*pctx);
11272+
ctx->prebuilt->table = innobase_reload_table(
11273+
m_user_thd, ctx->prebuilt->table,
11274+
table->s->table_name, *ctx0);
11275+
innobase_copy_frm_flags_from_table_share(
11276+
ctx->prebuilt->table, altered_table->s);
11277+
}
1127211278

1127311279
row_mysql_unlock_data_dictionary(trx);
1127411280
trx->free();

storage/maria/ha_s3.cc

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (C) 2019, 2020 MariaDB Corporation Ab
1+
/* Copyright (C) 2019, 2021 MariaDB Corporation Ab
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -887,17 +887,21 @@ int ha_s3::discover_check_version()
887887
Update the .frm file in S3
888888
*/
889889

890-
static int s3_notify_tabledef_changed(handlerton *hton __attribute__((unused)),
890+
static int s3_notify_tabledef_changed(handlerton *,
891891
LEX_CSTRING *db, LEX_CSTRING *table,
892892
LEX_CUSTRING *frm,
893-
LEX_CUSTRING *org_tabledef_version)
893+
LEX_CUSTRING *org_tabledef_version,
894+
handler *)
894895
{
895896
char aws_path[AWS_PATH_LENGTH];
896897
S3_INFO s3_info;
897898
ms3_st *s3_client;
898899
int error= 0;
899900
DBUG_ENTER("s3_notify_tabledef_changed");
900901

902+
if (strstr(table->str, "#P#"))
903+
DBUG_RETURN(0); // Ignore partitions
904+
901905
if (s3_info_init(&s3_info))
902906
DBUG_RETURN(0);
903907
if (!(s3_client= s3_open_connection(&s3_info)))
@@ -916,7 +920,7 @@ static int s3_notify_tabledef_changed(handlerton *hton __attribute__((unused)),
916920
NullS);
917921

918922
if (s3_put_object(s3_client, s3_info.bucket.str, aws_path, (uchar*) frm->str,
919-
frm->length, 0))
923+
frm->length, 0))
920924
error= 2;
921925

922926
err:

0 commit comments

Comments
 (0)