From 6d911219d6b1232b0edb6047da322e791c312ae5 Mon Sep 17 00:00:00 2001 From: Oleg Smirnov Date: Thu, 29 Jun 2023 18:34:34 +0700 Subject: [PATCH 1/4] MDEV-30639 Upgrade to 10.8 and later does not work on Windows During the upgrade procedure on Windows mysqld.exe is started with the named pipe connection protocol. mysqladmin.exe then pings the server to check if is up and running. Command line looks like: mysqladmin.exe --protocol=pipe --socket=mysql_upgrade_service_xxx ping But the "socket" parameter resets the "protocol" which was previously initialized with the "pipe" value, setting it to "socket". As a result, connection cannot be established and the upgrade procedure fails. "socket" in Windows is used to pass the name of the pipe so resetting the protocol is not valid in this case. This commit fixes resetting of the "protocol" parameter with "socket" parameter in the case when protocol has been previously initialized to "pipe" value --- client/mysql.cc | 11 +++++++++-- client/mysqladmin.cc | 11 +++++++++-- client/mysqlbinlog.cc | 11 +++++++++-- client/mysqlcheck.c | 11 +++++++++-- client/mysqldump.c | 11 +++++++++-- client/mysqlimport.c | 11 +++++++++-- client/mysqlshow.c | 11 +++++++++-- client/mysqlslap.c | 11 +++++++++-- mysql-test/main/cli_options_force_protocol_win.result | 8 +++++++- mysql-test/main/cli_options_force_protocol_win.test | 7 +++++++ 10 files changed, 86 insertions(+), 17 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index bf3091ed262..a3f4b3832ce 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1915,8 +1915,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; case 'I': diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index e11dd4f91be..fda2a8f0c2a 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -321,8 +321,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; } diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index d644a9bda49..0542c6d092b 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -2036,8 +2036,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; case 'v': diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index cdaba212206..76e36115b78 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -387,8 +387,15 @@ get_one_option(const struct my_option *opt, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; } diff --git a/client/mysqldump.c b/client/mysqldump.c index 50ace857b9e..621875bb97f 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1064,8 +1064,15 @@ get_one_option(const struct my_option *opt, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; } diff --git a/client/mysqlimport.c b/client/mysqlimport.c index 8628b32dd53..4b624a1939c 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -271,8 +271,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; case '#': diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 824686173ec..425c22e0de8 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -345,8 +345,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; break; diff --git a/client/mysqlslap.c b/client/mysqlslap.c index 79e5fe1f8bc..f8b8ad15e4c 100644 --- a/client/mysqlslap.c +++ b/client/mysqlslap.c @@ -784,8 +784,15 @@ get_one_option(const struct my_option *opt, const char *argument, case 'S': if (filename[0] == '\0') { - /* Socket given on command line, switch protocol to use SOCKETSt */ - opt_protocol= MYSQL_PROTOCOL_SOCKET; + /* + Socket given on command line, switch protocol to use SOCKETSt + Except on Windows if 'protocol= pipe' has been provided in + the config file or command line. + */ + if (opt_protocol != MYSQL_PROTOCOL_PIPE) + { + opt_protocol= MYSQL_PROTOCOL_SOCKET; + } } break; case '#': diff --git a/mysql-test/main/cli_options_force_protocol_win.result b/mysql-test/main/cli_options_force_protocol_win.result index eedfde4f1de..0d17a54dbc7 100644 --- a/mysql-test/main/cli_options_force_protocol_win.result +++ b/mysql-test/main/cli_options_force_protocol_win.result @@ -12,6 +12,12 @@ Connection: localhost via named pipe # exec MYSQL --host=localhost -W -e "status" 2>&1 | findstr /c:"Connection:" Connection: localhost via named pipe # exec MYSQL --host=localhost -W --socket=MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" -Connection: localhost via TCP/IP +Connection: localhost via named pipe # exec MYSQL --host=localhost --socket=MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" Connection: localhost via TCP/IP +# +# MDEV-30639: Upgrade to 10.8 and later does not work on Windows +# due to connection protocol overwrite +# +# exec MYSQL --host=localhost --protocol=pipe --socket=MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" +Connection: localhost via named pipe diff --git a/mysql-test/main/cli_options_force_protocol_win.test b/mysql-test/main/cli_options_force_protocol_win.test index 63024f3b620..31fb47fd72b 100644 --- a/mysql-test/main/cli_options_force_protocol_win.test +++ b/mysql-test/main/cli_options_force_protocol_win.test @@ -25,3 +25,10 @@ --echo # exec MYSQL --host=localhost --socket=MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" --exec $MYSQL --host=localhost --socket=$MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" + +--echo # +--echo # MDEV-30639: Upgrade to 10.8 and later does not work on Windows +--echo # due to connection protocol overwrite +--echo # +--echo # exec MYSQL --host=localhost --protocol=pipe --socket=MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" +--exec $MYSQL --host=localhost --protocol=pipe --socket=$MASTER_MYSOCK -e "status" 2>&1 | findstr /c:"Connection:" From 3d9014385926096264e36bb3a0960660d61d0d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 30 Jun 2023 17:07:21 +0300 Subject: [PATCH 2/4] MDEV-31559 btr_search_hash_table_validate() does not check if CHECK TABLE is killed btr_search_hash_table_validate(), btr_search_validate(): Add the parameter THD for checking if the statement has been killed. Any non-QUICK CHECK TABLE will validate the entire adaptive hash index for all InnoDB tables, which may be extremely slow when running multiple concurrent CHECK TABLE. --- storage/innobase/btr/btr0sea.cc | 59 ++++++++++++--------------- storage/innobase/handler/ha_innodb.cc | 3 +- storage/innobase/include/btr0sea.h | 3 +- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index a1609248512..a6a05bf3a93 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -2116,14 +2116,13 @@ static bool ha_validate(const hash_table_t *table, } /** Validates the search system for given hash table. -@param[in] hash_table_id hash table to validate -@return TRUE if ok */ -static -ibool -btr_search_hash_table_validate(ulint hash_table_id) +@param thd connection, for checking if CHECK TABLE has been killed +@param hash_table_id hash table to validate +@return true if ok */ +static bool btr_search_hash_table_validate(THD *thd, ulint hash_table_id) { ha_node_t* node; - ibool ok = TRUE; + bool ok = true; ulint i; ulint cell_count; mem_heap_t* heap = NULL; @@ -2131,9 +2130,15 @@ btr_search_hash_table_validate(ulint hash_table_id) rec_offs* offsets = offsets_; btr_search_x_lock_all(); - if (!btr_search_enabled) { + if (!btr_search_enabled || (thd && thd_kill_level(thd))) { +func_exit: btr_search_x_unlock_all(); - return(TRUE); + + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + + return ok; } /* How many cells to check before temporarily releasing @@ -2160,8 +2165,8 @@ btr_search_hash_table_validate(ulint hash_table_id) btr_search_x_lock_all(); - if (!btr_search_enabled) { - ok = true; + if (!btr_search_enabled + || (thd && thd_kill_level(thd))) { goto func_exit; } @@ -2268,8 +2273,8 @@ state_ok: btr_search_x_lock_all(); - if (!btr_search_enabled) { - ok = true; + if (!btr_search_enabled + || (thd && thd_kill_level(thd))) { goto func_exit; } @@ -2290,33 +2295,23 @@ state_ok: ulint end_index = ut_min(i + chunk_size - 1, cell_count - 1); if (!ha_validate(&part.table, i, end_index)) { - ok = FALSE; + ok = false; } } mysql_mutex_unlock(&buf_pool.mutex); -func_exit: - btr_search_x_unlock_all(); - - if (UNIV_LIKELY_NULL(heap)) { - mem_heap_free(heap); - } - - return(ok); + goto func_exit; } -/** Validate the search system. -@return true if ok. */ -bool -btr_search_validate() +/** Validates the search system. +@param thd connection, for checking if CHECK TABLE has been killed +@return true if ok */ +bool btr_search_validate(THD *thd) { - for (ulint i = 0; i < btr_ahi_parts; ++i) { - if (!btr_search_hash_table_validate(i)) { - return(false); - } - } - - return(true); + for (ulint i= 0; i < btr_ahi_parts; ++i) + if (!btr_search_hash_table_validate(thd, i)) + return(false); + return true; } #ifdef UNIV_DEBUG diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index d45433fd97c..efbde4b5393 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -15406,7 +15406,8 @@ ha_innobase::check( /* We validate the whole adaptive hash index for all tables at every CHECK TABLE only when QUICK flag is not present. */ - if (!(check_opt->flags & T_QUICK) && !btr_search_validate()) { + if (!(check_opt->flags & T_QUICK) + && !btr_search_validate(m_prebuilt->trx->mysql_thd)) { push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_NOT_KEYFILE, "InnoDB: The adaptive hash index is corrupted."); diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h index 48e4fadab9b..b75cad10180 100644 --- a/storage/innobase/include/btr0sea.h +++ b/storage/innobase/include/btr0sea.h @@ -127,8 +127,9 @@ void btr_search_update_hash_on_insert(btr_cur_t *cursor, void btr_search_update_hash_on_delete(btr_cur_t *cursor); /** Validates the search system. +@param thd connection, for checking if CHECK TABLE has been killed @return true if ok */ -bool btr_search_validate(); +bool btr_search_validate(THD *thd); /** Lock all search latches in exclusive mode. */ static inline void btr_search_x_lock_all(); From dc1bd1802a3175e2b890df368482cd39b5ed9444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 3 Jul 2023 14:39:29 +0300 Subject: [PATCH 3/4] MDEV-31386 InnoDB: Failing assertion: page_type == i_s_page_type[page_type].type_value i_s_innodb_buffer_page_get_info(): Correct a condition. After crash recovery, there may be some buffer pool pages in FREED state, containing garbage (invalid data page contents). Let us ignore such pages in the INFORMATION_SCHEMA output. The test innodb.innodb_defragment_fill_factor will be removed, because the queries that it is invoking on information_schema.innodb_buffer_page would start to fail. The defragmentation feature was removed in commit 7ca89af6f8faf1f8ec6ede01a9353ac499d37711 in MariaDB Server 11.1. Tested by: Matthias Leich --- .../r/innodb_defragment_fill_factor.result | 118 ---------- .../r/innodb_information_schema_buffer.result | 1 - .../t/innodb_defragment_fill_factor.opt | 4 - .../t/innodb_defragment_fill_factor.test | 203 ------------------ storage/innobase/handler/i_s.cc | 2 +- 5 files changed, 1 insertion(+), 327 deletions(-) delete mode 100644 mysql-test/suite/innodb/r/innodb_defragment_fill_factor.result delete mode 100644 mysql-test/suite/innodb/t/innodb_defragment_fill_factor.opt delete mode 100644 mysql-test/suite/innodb/t/innodb_defragment_fill_factor.test diff --git a/mysql-test/suite/innodb/r/innodb_defragment_fill_factor.result b/mysql-test/suite/innodb/r/innodb_defragment_fill_factor.result deleted file mode 100644 index 8453050a92a..00000000000 --- a/mysql-test/suite/innodb/r/innodb_defragment_fill_factor.result +++ /dev/null @@ -1,118 +0,0 @@ -Testing tables with large records -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), c VARCHAR(256), KEY SECOND(a, b,c)) ENGINE=INNODB; -INSERT INTO t1 VALUES (1, REPEAT('A', 256), REPEAT('B', 256)); -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -SET GLOBAL innodb_fast_shutdown = 0; -# restart -optimize table t1; -Table Op Msg_type Msg_text -test.t1 optimize status OK -select count(*) from t1; -count(*) -927 -select count(*) from t1 force index (second); -count(*) -927 -# A few more insertions on the page should not cause a page split. -insert into t1 values (81, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (83, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (87, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (82, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (86, REPEAT('A', 256), REPEAT('B', 256)); -# Insert more rows to cause a page split -insert into t1 values (180, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (181, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (182, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (183, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (184, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (185, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (186, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (187, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (188, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (189, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (190, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (191, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (192, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (193, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (194, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (195, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (196, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (197, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (198, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (199, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (200, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (201, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (202, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (203, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (204, REPEAT('A', 256), REPEAT('B', 256)); -DROP TABLE t1; -Testing table with small records -CREATE TABLE t2 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(16), c VARCHAR(32), KEY SECOND(a,b,c)) ENGINE=INNODB; -SET GLOBAL innodb_fast_shutdown = 0; -# restart -optimize table t2; -Table Op Msg_type Msg_text -test.t2 optimize status OK -select count(*) from t2; -count(*) -3701 -select count(*) from t2 force index(second); -count(*) -3701 -The page should have room for about 20 insertions -insert into t2 values(1181, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1191, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1182, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1192, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1183, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1193, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1184, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1194, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1185, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1195, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1186, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1196, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1187, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1197, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1188, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1198, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1189, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1199, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1190, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1180, REPEAT('A', 16), REPEAT('B',32)); -# Insert more rows to cause a page split -insert into t2 values (180, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (181, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (182, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (183, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (184, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (185, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (186, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (187, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (188, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (189, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (190, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (191, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (192, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (193, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (194, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (195, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (196, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (197, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (198, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (199, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (200, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (201, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (202, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (203, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (204, REPEAT('A', 16), REPEAT('B', 32)); -DROP TABLE t2; diff --git a/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result b/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result index 46372cd85f2..e87b35383a7 100644 --- a/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result +++ b/mysql-test/suite/innodb/r/innodb_information_schema_buffer.result @@ -14,7 +14,6 @@ WHERE TABLE_NAME LIKE '%infoschema_buffer_test%' AND PAGE_TYPE='index'; POOL_ID BLOCK_ID SPACE PAGE_NUMBER PAGE_TYPE FLUSH_TYPE FIX_COUNT IS_HASHED NEWEST_MODIFICATION OLDEST_MODIFICATION ACCESS_TIME TABLE_NAME INDEX_NAME NUMBER_RECORDS DATA_SIZE COMPRESSED_SIZE PAGE_STATE IO_FIX IS_OLD FREE_PAGE_CLOCK 0 # # 3 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_buffer_test` GEN_CLUST_INDEX 2 58 0 FILE_PAGE IO_FIX OLD # 0 # # 4 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_buffer_test` idx 2 32 0 FILE_PAGE IO_FIX OLD # -0 # # 5 INDEX 0 FIX AHI LSN LSN TIME `test`.`infoschema_buffer_test` idx 2 32 0 FILE_PAGE IO_FIX OLD # DROP TABLE infoschema_buffer_test; SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE WHERE TABLE_NAME LIKE '%infoschema_buffer_test%'; diff --git a/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.opt b/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.opt deleted file mode 100644 index 6426bac41a0..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.opt +++ /dev/null @@ -1,4 +0,0 @@ ---loose-innodb-buffer-pool-stats ---loose-innodb-buffer-page ---loose-innodb-buffer-page-lru ---innodb-defragment=1 \ No newline at end of file diff --git a/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.test b/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.test deleted file mode 100644 index 3a5897b9911..00000000000 --- a/mysql-test/suite/innodb/t/innodb_defragment_fill_factor.test +++ /dev/null @@ -1,203 +0,0 @@ ---source include/have_innodb.inc ---source include/big_test.inc ---source include/not_valgrind.inc ---source include/not_embedded.inc ---source include/have_innodb_16k.inc - ---echo Testing tables with large records -# Create table. -CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(256), c VARCHAR(256), KEY SECOND(a, b,c)) ENGINE=INNODB; - -# Populate table. -INSERT INTO t1 VALUES (1, REPEAT('A', 256), REPEAT('B', 256)); -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; -INSERT INTO t1 (b) SELECT b from t1; - ---disable_query_log -let $size = 10; -while ($size) -{ - let $j = 100 * $size; - eval delete from t1 where a between $j - 20 and $j + 5; - dec $size; -} ---enable_query_log - -SET GLOBAL innodb_fast_shutdown = 0; ---source include/restart_mysqld.inc -optimize table t1; - -select count(*) from t1; - ---let $primary_before = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY', Value, 1) - -select count(*) from t1 force index (second); - ---let $second_before = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second', Value, 1) - ---echo # A few more insertions on the page should not cause a page split. -insert into t1 values (81, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (83, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (87, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (82, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (86, REPEAT('A', 256), REPEAT('B', 256)); ---let $primary_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY', Value, 1) ---let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second', Value, 1) - -if ($primary_before != $primary_after) { - --echo Insertion caused page split on primary, which should be avoided by innodb_defragment_fill_factor. -} - -if ($second_before != $second_after) { - --echo Insertion caused page split on second, which should be avoided by innodb_defragment_fill_factor. -} - ---echo # Insert more rows to cause a page split -insert into t1 values (180, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (181, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (182, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (183, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (184, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (185, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (186, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (187, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (188, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (189, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (190, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (191, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (192, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (193, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (194, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (195, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (196, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (197, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (198, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (199, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (200, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (201, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (202, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (203, REPEAT('A', 256), REPEAT('B', 256)); -insert into t1 values (204, REPEAT('A', 256), REPEAT('B', 256)); - ---let $primary_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'PRIMARY', Value, 1) - ---let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t1%' and index_name = 'second', Value, 1) - -if ($primary_before == $primary_after) { - --echo Too little space is reserved on primary index. -} - -if ($second_before == $second_after) { - --echo Too little space is reserved on second index. -} - -DROP TABLE t1; - ---echo Testing table with small records -CREATE TABLE t2 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b VARCHAR(16), c VARCHAR(32), KEY SECOND(a,b,c)) ENGINE=INNODB; -# Populate table. ---disable_query_log -INSERT INTO t2 VALUES (1, REPEAT('A', 16), REPEAT('B', 32)); -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; -INSERT INTO t2 (b) SELECT b from t2; ---enable_query_log - ---disable_query_log -let $size = 40; -while ($size) -{ - let $j = 100 * $size; - eval delete from t2 where a between $j - 20 and $j; - dec $size; -} ---enable_query_log - -SET GLOBAL innodb_fast_shutdown = 0; ---source include/restart_mysqld.inc -optimize table t2; - -select count(*) from t2; -select count(*) from t2 force index(second); - ---let $second_before = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t2%' and index_name = 'second', Value, 1) - ---echo The page should have room for about 20 insertions -insert into t2 values(1181, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1191, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1182, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1192, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1183, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1193, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1184, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1194, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1185, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1195, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1186, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1196, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1187, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1197, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1188, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1198, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1189, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1199, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1190, REPEAT('A', 16), REPEAT('B',32)); -insert into t2 values(1180, REPEAT('A', 16), REPEAT('B',32)); - ---let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t2%' and index_name = 'second', Value, 1) - -if ($second_before != $second_after) { - --echo Insertion caused page split on second, which should be avoided by innodb_defragment_fill_factor. -} - ---echo # Insert more rows to cause a page split -insert into t2 values (180, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (181, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (182, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (183, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (184, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (185, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (186, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (187, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (188, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (189, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (190, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (191, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (192, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (193, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (194, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (195, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (196, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (197, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (198, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (199, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (200, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (201, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (202, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (203, REPEAT('A', 16), REPEAT('B', 32)); -insert into t2 values (204, REPEAT('A', 16), REPEAT('B', 32)); - ---let $second_after = query_get_value(select count(*) as Value from information_schema.innodb_buffer_page where table_name like '%t2%' and index_name = 'second', Value, 1) - -if ($second_before == $second_after) { - --echo Too little space is reserved on second index. -} - -DROP TABLE t2; diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index e393bed6d9f..a8e110889e3 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -4066,7 +4066,7 @@ i_s_innodb_buffer_page_get_info( page_info->state = bpage->state(); - if (page_info->state < buf_page_t::FREED) { + if (page_info->state < buf_page_t::UNFIXED) { page_info->page_type = I_S_PAGE_TYPE_UNKNOWN; page_info->compressed_only = false; } else { From f7b8a2c953e21d7a1c8e7ef3b7107c13a1402967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 3 Jul 2023 16:47:58 +0300 Subject: [PATCH 4/4] MDEV-31607 ER_DUP_KEY in mysql.innodb_table_stats upon RENAME on sequence ha_innobase::delete_table(): Also on DROP SEQUENCE, do try to drop any persistent statistics. They should really not be created for SEQUENCE objects (which internally are 1-row no-rollback tables), but that is how happened to always work. --- mysql-test/suite/sql_sequence/alter.result | 14 ++++++++++++++ mysql-test/suite/sql_sequence/alter.test | 12 ++++++++++++ storage/innobase/handler/ha_innodb.cc | 11 +++++------ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/sql_sequence/alter.result b/mysql-test/suite/sql_sequence/alter.result index 90de2ebfcc0..6d29876a8eb 100644 --- a/mysql-test/suite/sql_sequence/alter.result +++ b/mysql-test/suite/sql_sequence/alter.result @@ -248,3 +248,17 @@ SELECT NEXTVAL(s); NEXTVAL(s) 1 DROP SEQUENCE s; +# +# MDEV-31607 ER_DUP_KEY in mysql.table_stats upon REANME on sequence +# +CREATE SEQUENCE s1 ENGINE=InnoDB; +CREATE SEQUENCE s2 ENGINE=InnoDB; +SHOW CREATE SEQUENCE s1; +Table Create Table +s1 CREATE SEQUENCE `s1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB +SHOW CREATE SEQUENCE s2; +Table Create Table +s2 CREATE SEQUENCE `s2` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB +DROP SEQUENCE s2; +RENAME TABLE s1 TO s2; +DROP SEQUENCE s2; diff --git a/mysql-test/suite/sql_sequence/alter.test b/mysql-test/suite/sql_sequence/alter.test index a5e6245d609..3ad9821b0cf 100644 --- a/mysql-test/suite/sql_sequence/alter.test +++ b/mysql-test/suite/sql_sequence/alter.test @@ -161,3 +161,15 @@ CREATE SEQUENCE s; ALTER TABLE s ORDER BY cache_size; SELECT NEXTVAL(s); DROP SEQUENCE s; + +--echo # +--echo # MDEV-31607 ER_DUP_KEY in mysql.table_stats upon REANME on sequence +--echo # + +CREATE SEQUENCE s1 ENGINE=InnoDB; +CREATE SEQUENCE s2 ENGINE=InnoDB; +SHOW CREATE SEQUENCE s1; +SHOW CREATE SEQUENCE s2; +DROP SEQUENCE s2; +RENAME TABLE s1 TO s2; +DROP SEQUENCE s2; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index efbde4b5393..ca03a5cdf0b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13748,13 +13748,12 @@ err_exit: } if (!table->no_rollback()) - { err= trx->drop_table_foreign(table->name); - if (err == DB_SUCCESS && table_stats && index_stats) - err= trx->drop_table_statistics(table->name); - if (err != DB_SUCCESS) - goto err_exit; - } + + if (err == DB_SUCCESS && table_stats && index_stats) + err= trx->drop_table_statistics(table->name); + if (err != DB_SUCCESS) + goto err_exit; err= trx->drop_table(*table); if (err != DB_SUCCESS)