diff --git a/mysql-test/suite/funcs_1/r/is_columns_mysql.result b/mysql-test/suite/funcs_1/r/is_columns_mysql.result index d021c73b339..25dbb185e44 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result +++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result @@ -124,13 +124,13 @@ def mysql innodb_index_stats sample_size 7 NULL YES bigint NULL NULL 20 0 NULL N def mysql innodb_index_stats stat_description 8 NULL NO varchar 1024 3072 NULL NULL NULL utf8 utf8_bin varchar(1024) select,insert,update,references NEVER NULL def mysql innodb_index_stats stat_name 5 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references NEVER NULL def mysql innodb_index_stats stat_value 6 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL -def mysql innodb_index_stats table_name 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references NEVER NULL +def mysql innodb_index_stats table_name 2 NULL NO varchar 199 597 NULL NULL NULL utf8 utf8_bin varchar(199) PRI select,insert,update,references NEVER NULL def mysql innodb_table_stats clustered_index_size 5 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL def mysql innodb_table_stats database_name 1 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references NEVER NULL def mysql innodb_table_stats last_update 3 current_timestamp() NO timestamp NULL NULL NULL NULL 0 NULL NULL timestamp on update current_timestamp() select,insert,update,references NEVER NULL def mysql innodb_table_stats n_rows 4 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL def mysql innodb_table_stats sum_of_other_index_sizes 6 NULL NO bigint NULL NULL 20 0 NULL NULL NULL bigint(20) unsigned select,insert,update,references NEVER NULL -def mysql innodb_table_stats table_name 2 NULL NO varchar 64 192 NULL NULL NULL utf8 utf8_bin varchar(64) PRI select,insert,update,references NEVER NULL +def mysql innodb_table_stats table_name 2 NULL NO varchar 199 597 NULL NULL NULL utf8 utf8_bin varchar(199) PRI select,insert,update,references NEVER NULL def mysql plugin dl 2 '' NO varchar 128 384 NULL NULL NULL utf8 utf8_general_ci varchar(128) select,insert,update,references NEVER NULL def mysql plugin name 1 '' NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) PRI select,insert,update,references NEVER NULL def mysql proc body 11 NULL NO longblob 4294967295 4294967295 NULL NULL NULL NULL NULL longblob select,insert,update,references NEVER NULL @@ -453,7 +453,7 @@ NULL mysql help_topic help_category_id smallint NULL NULL NULL NULL smallint(5) NULL mysql index_stats prefix_arity int NULL NULL NULL NULL int(11) unsigned NULL mysql index_stats avg_frequency decimal NULL NULL NULL NULL decimal(12,4) 3.0000 mysql innodb_index_stats database_name varchar 64 192 utf8 utf8_bin varchar(64) -3.0000 mysql innodb_index_stats table_name varchar 64 192 utf8 utf8_bin varchar(64) +3.0000 mysql innodb_index_stats table_name varchar 199 597 utf8 utf8_bin varchar(199) 3.0000 mysql innodb_index_stats index_name varchar 64 192 utf8 utf8_bin varchar(64) NULL mysql innodb_index_stats last_update timestamp NULL NULL NULL NULL timestamp 3.0000 mysql innodb_index_stats stat_name varchar 64 192 utf8 utf8_bin varchar(64) @@ -461,7 +461,7 @@ NULL mysql innodb_index_stats stat_value bigint NULL NULL NULL NULL bigint(20) u NULL mysql innodb_index_stats sample_size bigint NULL NULL NULL NULL bigint(20) unsigned 3.0000 mysql innodb_index_stats stat_description varchar 1024 3072 utf8 utf8_bin varchar(1024) 3.0000 mysql innodb_table_stats database_name varchar 64 192 utf8 utf8_bin varchar(64) -3.0000 mysql innodb_table_stats table_name varchar 64 192 utf8 utf8_bin varchar(64) +3.0000 mysql innodb_table_stats table_name varchar 199 597 utf8 utf8_bin varchar(199) NULL mysql innodb_table_stats last_update timestamp NULL NULL NULL NULL timestamp NULL mysql innodb_table_stats n_rows bigint NULL NULL NULL NULL bigint(20) unsigned NULL mysql innodb_table_stats clustered_index_size bigint NULL NULL NULL NULL bigint(20) unsigned diff --git a/mysql-test/suite/innodb_gis/r/create_spatial_index.result b/mysql-test/suite/innodb_gis/r/create_spatial_index.result index 71d3092c3b7..80632affb67 100644 --- a/mysql-test/suite/innodb_gis/r/create_spatial_index.result +++ b/mysql-test/suite/innodb_gis/r/create_spatial_index.result @@ -1284,7 +1284,7 @@ CREATE SPATIAL INDEX idx2 ON t1(c1); DROP TABLE t1; CREATE TABLE mysql.innodb_table_stats ( database_name varchar(64) COLLATE utf8_bin NOT NULL, -table_name varchar(64) COLLATE utf8_bin NOT NULL, +table_name varchar(199) COLLATE utf8_bin NOT NULL, last_update timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, n_rows bigint(20) unsigned NOT NULL, clustered_index_size bigint(20) unsigned NOT NULL, diff --git a/mysql-test/suite/innodb_gis/t/create_spatial_index.test b/mysql-test/suite/innodb_gis/t/create_spatial_index.test index d25a2e79793..6a15b0f2d74 100644 --- a/mysql-test/suite/innodb_gis/t/create_spatial_index.test +++ b/mysql-test/suite/innodb_gis/t/create_spatial_index.test @@ -1166,7 +1166,7 @@ CREATE SPATIAL INDEX idx2 ON t1(c1); DROP TABLE t1; CREATE TABLE mysql.innodb_table_stats ( database_name varchar(64) COLLATE utf8_bin NOT NULL, - table_name varchar(64) COLLATE utf8_bin NOT NULL, + table_name varchar(199) COLLATE utf8_bin NOT NULL, last_update timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, n_rows bigint(20) unsigned NOT NULL, clustered_index_size bigint(20) unsigned NOT NULL, diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index 7b614163f46..c5792168213 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -1,4 +1,4 @@ --- Copyright (c) 2007, 2013, Oracle and/or its affiliates. +-- Copyright (c) 2007, 2018, Oracle and/or its affiliates. -- Copyright (c) 2008, 2014, Monty Program Ab & SkySQL Ab -- -- This program is free software; you can redistribute it and/or modify @@ -105,7 +105,7 @@ CREATE TABLE IF NOT EXISTS event ( db char(64) CHARACTER SET utf8 COLLATE utf8_b SET @create_innodb_table_stats="CREATE TABLE IF NOT EXISTS innodb_table_stats ( database_name VARCHAR(64) NOT NULL, - table_name VARCHAR(64) NOT NULL, + table_name VARCHAR(199) NOT NULL, last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, n_rows BIGINT UNSIGNED NOT NULL, clustered_index_size BIGINT UNSIGNED NOT NULL, @@ -115,7 +115,7 @@ SET @create_innodb_table_stats="CREATE TABLE IF NOT EXISTS innodb_table_stats ( SET @create_innodb_index_stats="CREATE TABLE IF NOT EXISTS innodb_index_stats ( database_name VARCHAR(64) NOT NULL, - table_name VARCHAR(64) NOT NULL, + table_name VARCHAR(199) NOT NULL, index_name VARCHAR(64) NOT NULL, last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, /* there are at least: diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index e724c3e2d23..db32834c4d6 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -697,13 +697,13 @@ set @str=replace(@str, "innodb_index_stats", "innodb_table_stats"); prepare stmt from @str; execute stmt; -# update timestamp fields in the innodb stat tables -set @str="alter table mysql.innodb_index_stats modify last_update timestamp not null default current_timestamp on update current_timestamp"; +# update table_name and timestamp fields in the innodb stat tables +set @str="alter table mysql.innodb_index_stats modify last_update timestamp not null default current_timestamp on update current_timestamp, modify table_name varchar(199)"; set @str=if(@have_innodb <> 0, @str, "set @dummy = 0"); prepare stmt from @str; execute stmt; -set @str="alter table mysql.innodb_table_stats modify last_update timestamp not null default current_timestamp on update current_timestamp"; +set @str="alter table mysql.innodb_table_stats modify last_update timestamp not null default current_timestamp on update current_timestamp, modify table_name varchar(199)"; set @str=if(@have_innodb <> 0, @str, "set @dummy = 0"); prepare stmt from @str; execute stmt; diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index cb03562b598..5af0a8b899a 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -65,6 +65,8 @@ Created 10/16/1994 Heikki Tuuri #include "lock0lock.h" #include "zlib.h" #include "srv0start.h" +#include "mysql_com.h" +#include "dict0stats.h" /** Buffered B-tree operation types, introduced as part of delete buffering. */ enum btr_op_t { @@ -771,6 +773,22 @@ static ulint btr_node_ptr_max_size(const dict_index_t* index) rec_max_size += (srv_page_size == UNIV_PAGE_SIZE_MAX) ? REDUNDANT_REC_MAX_DATA_SIZE : page_get_free_space_of_empty(FALSE) / 2; + } else if (field_max_size == NAME_LEN && i == 1 + && (!strcmp(index->table->name.m_name, + TABLE_STATS_NAME) + || !strcmp(index->table->name.m_name, + INDEX_STATS_NAME))) { + ut_ad(!strcmp(field->name, "table_name")); + /* Interpret "table_name" as VARCHAR(199) even + if it was incorrectly defined as VARCHAR(64). + While the caller of ha_innobase enforces the + maximum length on any data written, the InnoDB + internal SQL parser will happily write as much + data as is provided. The purpose of this hack + is to avoid InnoDB hangs after persistent + statistics on partitioned tables are + deleted. */ + field_max_size = 199 * SYSTEM_CHARSET_MBMAXLEN; } field_ext_max_size = field_max_size < 256 ? 1 : 2; diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index a0d430e0257..fd7428001f8 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -6490,8 +6490,17 @@ dict_table_schema_check( compare column types and flags */ /* check length for exact match */ - if (req_schema->columns[i].len != table->cols[j].len) { - + if (req_schema->columns[i].len == table->cols[j].len) { + } else if (!strcmp(req_schema->table_name, TABLE_STATS_NAME) + || !strcmp(req_schema->table_name, + INDEX_STATS_NAME)) { + ut_ad(table->cols[j].len < req_schema->columns[i].len); + ib::warn() << "Table " << req_schema->table_name + << " has length mismatch in the" + << " column name " + << req_schema->columns[i].name + << ". Please run mysql_upgrade"; + } else { CREATE_TYPES_NAMES(); snprintf(errstr, errstr_sz, diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 98a846bcaba..2719c7e7222 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2009, 2017, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2009, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2015, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -108,9 +108,7 @@ where n=1..n_uniq. @} */ /* names of the tables from the persistent statistics storage */ -#define TABLE_STATS_NAME "mysql/innodb_table_stats" #define TABLE_STATS_NAME_PRINT "mysql.innodb_table_stats" -#define INDEX_STATS_NAME "mysql/innodb_index_stats" #define INDEX_STATS_NAME_PRINT "mysql.innodb_index_stats" #ifdef UNIV_STATS_DEBUG @@ -181,7 +179,7 @@ dict_stats_persistent_storage_check( DATA_NOT_NULL, 192}, {"table_name", DATA_VARMYSQL, - DATA_NOT_NULL, 192}, + DATA_NOT_NULL, 597}, {"last_update", DATA_FIXBINARY, DATA_NOT_NULL, 4}, @@ -209,7 +207,7 @@ dict_stats_persistent_storage_check( DATA_NOT_NULL, 192}, {"table_name", DATA_VARMYSQL, - DATA_NOT_NULL, 192}, + DATA_NOT_NULL, 597}, {"index_name", DATA_VARMYSQL, DATA_NOT_NULL, 192}, diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index dccdeacb08f..aa6d9d48117 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5459,15 +5459,16 @@ ha_innobase::max_supported_key_length() const switch (UNIV_PAGE_SIZE) { case 4096: - return(768); + /* Hack: allow mysql.innodb_index_stats to be created. */ + /* FIXME: rewrite this API, and in sql_table.cc consider + that in index-organized tables (such as InnoDB), secondary + index records will be padded with the PRIMARY KEY, instead + of some short ROWID or record heap address. */ + return(1173); case 8192: return(1536); default: -#ifdef WITH_WSREP return(3500); -#else - return(3500); -#endif } } diff --git a/storage/innobase/include/dict0stats.h b/storage/innobase/include/dict0stats.h index 03f0c0c6377..407e0221110 100644 --- a/storage/innobase/include/dict0stats.h +++ b/storage/innobase/include/dict0stats.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2009, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2009, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, 2018, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -32,6 +32,9 @@ Created Jan 06, 2010 Vasil Dimov #include "dict0types.h" #include "trx0types.h" +#define TABLE_STATS_NAME "mysql/innodb_table_stats" +#define INDEX_STATS_NAME "mysql/innodb_index_stats" + enum dict_stats_upd_option_t { DICT_STATS_RECALC_PERSISTENT,/* (re) calculate the statistics using a precise and slow diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index ad8a76c5280..05131eb69b0 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -3307,7 +3307,8 @@ os_file_get_status_posix( { int ret = stat(path, statinfo); - if (ret && (errno == ENOENT || errno == ENOTDIR)) { + if (ret && (errno == ENOENT || errno == ENOTDIR + || errno == ENAMETOOLONG)) { /* file does not exist */ return(DB_NOT_FOUND); @@ -4697,7 +4698,8 @@ os_file_get_status_win32( { int ret = _stat64(path, statinfo); - if (ret && (errno == ENOENT || errno == ENOTDIR)) { + if (ret && (errno == ENOENT || errno == ENOTDIR + || errno == ENAMETOOLONG)) { /* file does not exist */ return(DB_NOT_FOUND);