From ca9e0089d5d9c8777c58b1e44ff97e7bcb1bdddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 27 Sep 2019 10:43:23 +0300 Subject: [PATCH 1/5] MDEV-19740: Fix GCC 9.2.1 -Wmaybe-uninitialized on AMD64 For CMAKE_BUILD_TYPE=Debug, the default MYSQL_MAINTAINER_MODE=AUTO implies -Werror along with other flags in cmake/maintainer.cmake, which would break the debug builds when CMAKE_CXX_FLAGS include -O2. This fix includes a backport of 6dd3f24090ce2d237037eb09cf7db083ebbc92f9 from MariaDB 10.3. --- sql/item_cmpfunc.cc | 4 +--- sql/opt_subselect.h | 18 +++++++----------- sql/sql_statistics.cc | 7 ++----- storage/maria/ma_ft_nlq_search.c | 2 +- storage/myisam/ft_nlq_search.c | 2 +- storage/myisam/mi_create.c | 2 +- 6 files changed, 13 insertions(+), 22 deletions(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 2c3a96f3f47..a28daf36f05 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -428,11 +428,9 @@ static bool convert_const_to_int(THD *thd, Item_field *field_item, TABLE *table= field->table; sql_mode_t orig_sql_mode= thd->variables.sql_mode; enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields; - my_bitmap_map *old_maps[2]; + my_bitmap_map *old_maps[2] = { NULL, NULL }; ulonglong UNINIT_VAR(orig_field_val); /* original field value if valid */ - LINT_INIT_STRUCT(old_maps); - /* table->read_set may not be set if we come here from a CREATE TABLE */ if (table && table->read_set) dbug_tmp_use_all_columns(table, old_maps, diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h index 7641a5d6196..69f1cc33017 100644 --- a/sql/opt_subselect.h +++ b/sql/opt_subselect.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2010, 2015, MariaDB + Copyright (c) 2010, 2019, 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,19 +92,15 @@ class Loose_scan_opt public: Loose_scan_opt(): - try_loosescan(FALSE), + try_loosescan(false), bound_sj_equalities(0), - quick_uses_applicable_index(FALSE) + quick_uses_applicable_index(FALSE), quick_max_loose_keypart(0), + best_loose_scan_key(0), best_loose_scan_records(0.0), + best_loose_scan_start_key(NULL), + best_max_loose_keypart(0), best_ref_depend_map(0) { - /* Protected by quick_uses_applicable_index */ - LINT_INIT(quick_max_loose_keypart); - /* The following are protected by best_loose_scan_cost!= DBL_MAX */ - LINT_INIT(best_loose_scan_key); - LINT_INIT(best_loose_scan_records); - LINT_INIT(best_max_loose_keypart); - LINT_INIT(best_loose_scan_start_key); } - + void init(JOIN *join, JOIN_TAB *s, table_map remaining_tables) { /* diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 7bf8fd676d4..55af2c34e6e 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -1814,16 +1814,13 @@ public: bool is_partial_fields_present; Index_prefix_calc(THD *thd, TABLE *table, KEY *key_info) - : index_table(table), index_info(key_info) + : index_table(table), index_info(key_info), prefixes(0), empty(true), + calc_state(NULL), is_single_comp_pk(false), is_partial_fields_present(false) { uint i; Prefix_calc_state *state; uint key_parts= table->actual_n_key_parts(key_info); - empty= TRUE; - prefixes= 0; - LINT_INIT_STRUCT(calc_state); - is_partial_fields_present= is_single_comp_pk= FALSE; uint pk= table->s->primary_key; if ((uint) (table->key_info - key_info) == pk && table->key_info[pk].user_defined_key_parts == 1) diff --git a/storage/maria/ma_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c index d83981e424c..2afd493b32d 100644 --- a/storage/maria/ma_ft_nlq_search.c +++ b/storage/maria/ma_ft_nlq_search.c @@ -83,13 +83,13 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) #error #endif DBUG_ENTER("walk_and_match"); - LINT_INIT_STRUCT(subkeys); word->weight=LWS_FOR_QUERY; _ma_ft_make_key(info, &key, aio->keynr, keybuff, word, 0); key.data_length-= HA_FT_WLEN; doc_cnt=0; + subkeys.i= 0; if (share->lock_key_trees) mysql_rwlock_rdlock(&share->keyinfo[aio->keynr].root_lock); diff --git a/storage/myisam/ft_nlq_search.c b/storage/myisam/ft_nlq_search.c index e6bbf6656a1..4f51879ac00 100644 --- a/storage/myisam/ft_nlq_search.c +++ b/storage/myisam/ft_nlq_search.c @@ -81,13 +81,13 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio) #error #endif DBUG_ENTER("walk_and_match"); - LINT_INIT_STRUCT(subkeys); word->weight=LWS_FOR_QUERY; keylen=_ft_make_key(info,aio->keynr,keybuff,word,0); keylen-=HA_FT_WLEN; doc_cnt=0; + subkeys.i= 0; if (share->concurrent_insert) mysql_rwlock_rdlock(&share->key_root_lock[aio->keynr]); diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index 57d9630ecb9..fd230698acc 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -47,7 +47,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, uint internal_table= flags & HA_CREATE_INTERNAL_TABLE; ulong reclength, real_reclength,min_pack_length; char kfilename[FN_REFLEN],klinkname[FN_REFLEN], *klinkname_ptr; - char dfilename[FN_REFLEN],dlinkname[FN_REFLEN], *dlinkname_ptr; + char dfilename[FN_REFLEN],dlinkname[FN_REFLEN], *dlinkname_ptr= 0; ulong pack_reclength; ulonglong tot_length,max_rows, tmp; enum en_fieldtype type; From 4ec0c346b80901c27a25aae0adb805d8aab4e81d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 27 Sep 2019 13:58:01 +0300 Subject: [PATCH 2/5] Remove a useless large test, and add a debug assertion The test innodb_fts.fulltext_table_evict was only creating 1000 tables with fulltext indexes, only to check that no tables with fulltext indexes are being evicted. The reason why tables containing fulltext indexes cannot be evicted is that fts_optimize_init() invokes dict_table_prevent_eviction(). --- .../innodb_fts/r/fulltext_table_evict.result | 19 ------- .../innodb_fts/t/fulltext_table_evict.test | 49 ------------------- mysql-test/unstable-tests | 1 - storage/innobase/dict/dict0dict.cc | 9 +--- 4 files changed, 1 insertion(+), 77 deletions(-) delete mode 100644 mysql-test/suite/innodb_fts/r/fulltext_table_evict.result delete mode 100644 mysql-test/suite/innodb_fts/t/fulltext_table_evict.test diff --git a/mysql-test/suite/innodb_fts/r/fulltext_table_evict.result b/mysql-test/suite/innodb_fts/r/fulltext_table_evict.result deleted file mode 100644 index d9d329aa6c0..00000000000 --- a/mysql-test/suite/innodb_fts/r/fulltext_table_evict.result +++ /dev/null @@ -1,19 +0,0 @@ -# -# Bug Bug #27304661 MYSQL CRASH DOING SYNC INDEX ] -# [FATAL] INNODB: SEMAPHORE WAIT HAS LASTED > 600 -# -CREATE TABLE t1 ( -id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, -f1 TEXT(500), -FULLTEXT idx (f1) -) ENGINE=InnoDB; -insert into t1 (f1) values ('fjdhfsjhf'),('dhjfhjshfj'),('dhjafjhfj'); -set @save_table_definition_cache=@@global.table_definition_cache; -set @save_table_open_cache=@@global.table_open_cache; -set global table_definition_cache=400; -set global table_open_cache= 1024; -SET @save_dbug = @@GLOBAL.debug_dbug; -SET GLOBAL DEBUG_DBUG="+d,crash_if_fts_table_is_evicted"; -set @@global.table_definition_cache=@save_table_definition_cache; -set @@global.table_open_cache=@save_table_open_cache; -drop table t1; diff --git a/mysql-test/suite/innodb_fts/t/fulltext_table_evict.test b/mysql-test/suite/innodb_fts/t/fulltext_table_evict.test deleted file mode 100644 index eaf50856c55..00000000000 --- a/mysql-test/suite/innodb_fts/t/fulltext_table_evict.test +++ /dev/null @@ -1,49 +0,0 @@ ---source include/have_innodb.inc ---source include/have_debug.inc ---source include/big_test.inc ---source include/have_64bit.inc - ---echo # ---echo # Bug Bug #27304661 MYSQL CRASH DOING SYNC INDEX ] ---echo # [FATAL] INNODB: SEMAPHORE WAIT HAS LASTED > 600 ---echo # - -CREATE TABLE t1 ( - id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, - f1 TEXT(500), - FULLTEXT idx (f1) - ) ENGINE=InnoDB; -insert into t1 (f1) values ('fjdhfsjhf'),('dhjfhjshfj'),('dhjafjhfj'); - ---source include/restart_mysqld.inc - -set @save_table_definition_cache=@@global.table_definition_cache; -set @save_table_open_cache=@@global.table_open_cache; - -set global table_definition_cache=400; -set global table_open_cache= 1024; - -SET @save_dbug = @@GLOBAL.debug_dbug; -SET GLOBAL DEBUG_DBUG="+d,crash_if_fts_table_is_evicted"; -#Create 1000 tables, try the best to evict t1 . - ---disable_query_log -let $loop=1000; -while($loop) -{ - eval create table t_$loop(id int, name text(100), fulltext idxt_$loop(name) )engine=innodb; - dec $loop; -} - -let $loop=1000; -while($loop) -{ - eval drop table t_$loop; - dec $loop; -} - -SET GLOBAL DEBUG_DBUG = @save_dbug; ---enable_query_log -set @@global.table_definition_cache=@save_table_definition_cache; -set @@global.table_open_cache=@save_table_open_cache; -drop table t1; diff --git a/mysql-test/unstable-tests b/mysql-test/unstable-tests index 79d278b5bff..556ae663b1e 100644 --- a/mysql-test/unstable-tests +++ b/mysql-test/unstable-tests @@ -519,7 +519,6 @@ innodb.xa_recovery : MDEV-15279 - mysqld got exception #----------------------------------------------------------------------- innodb_fts.fulltext2 : Modified in 10.2.26 -innodb_fts.fulltext_table_evict : Modified in 10.2.27 innodb_fts.innodb_fts_misc : Modified in 10.2.27 innodb_fts.innodb_fts_misc_debug : MDEV-14156 - Unexpected warning innodb_fts.innodb_fts_plugin : MDEV-13888 - Errors in server log diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 5d636f59225..7103ee974d7 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1442,14 +1442,7 @@ dict_make_room_in_cache( prev_table = UT_LIST_GET_PREV(table_LRU, table); if (dict_table_can_be_evicted(table)) { - - DBUG_EXECUTE_IF("crash_if_fts_table_is_evicted", - { - if (table->fts && - dict_table_has_fts_index(table)) { - ut_ad(0); - } - };); + ut_ad(!table->fts); dict_table_remove_from_cache_low(table, TRUE); ++n_evicted; From 718fcee0a30e8c4e818e9f24946fa2c2def62734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 27 Sep 2019 14:22:59 +0300 Subject: [PATCH 3/5] Reduce rw_lock_debug_mutex contention rw_lock_own(), rw_lock_own_flagged(): Traverse the rw_lock_t::debug_list only after quickly checking if the thread is holding X-latch or SX-latch. --- storage/innobase/sync/sync0rw.cc | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc index 2c3407ba56a..96108ab0bf1 100644 --- a/storage/innobase/sync/sync0rw.cc +++ b/storage/innobase/sync/sync0rw.cc @@ -999,13 +999,22 @@ rw_lock_own( ut_ad(lock); ut_ad(rw_lock_validate(lock)); + const os_thread_id_t thread_id = os_thread_get_curr_id(); + + if (!os_thread_eq(lock->writer_thread, thread_id)) { + } else if (lock_type == RW_LOCK_X && rw_lock_get_x_lock_count(lock)) { + return TRUE; + } else if (lock_type == RW_LOCK_SX && rw_lock_get_sx_lock_count(lock)) { + return TRUE; + } + rw_lock_debug_mutex_enter(); for (const rw_lock_debug_t* info = UT_LIST_GET_FIRST(lock->debug_list); info != NULL; info = UT_LIST_GET_NEXT(list, info)) { - if (os_thread_eq(info->thread_id, os_thread_get_curr_id()) + if (os_thread_eq(info->thread_id, thread_id) && info->pass == 0 && info->lock_type == lock_type) { @@ -1030,12 +1039,23 @@ bool rw_lock_own_flagged(const rw_lock_t* lock, rw_lock_flags_t flags) { ut_ad(rw_lock_validate(lock)); + const os_thread_id_t thread_id = os_thread_get_curr_id(); + + if (!os_thread_eq(lock->writer_thread, thread_id)) { + } else if ((flags & RW_LOCK_FLAG_X) + && rw_lock_get_x_lock_count(lock)) { + return true; + } else if ((flags & RW_LOCK_FLAG_SX) + && rw_lock_get_sx_lock_count(lock)) { + return true; + } + rw_lock_debug_mutex_enter(); for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(lock->debug_list); info != NULL; info = UT_LIST_GET_NEXT(list, info)) { - if (!os_thread_eq(info->thread_id, os_thread_get_curr_id()) + if (!os_thread_eq(info->thread_id, thread_id) || info->pass) { continue; } From d874cdecccc4c4702e4e78bd551e72e99453021a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 27 Sep 2019 14:29:22 +0300 Subject: [PATCH 4/5] dict_load_table(): Remove constant parameter cached=true Spotted by Thirunarayanan Balathandayuthapani. --- storage/innobase/dict/dict0dict.cc | 2 +- storage/innobase/dict/dict0load.cc | 25 ++++++----------------- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/handler/handler0alter.cc | 2 +- storage/innobase/include/dict0load.h | 7 +------ storage/innobase/include/dict0priv.ic | 2 +- storage/innobase/row/row0mysql.cc | 6 +++--- 7 files changed, 14 insertions(+), 32 deletions(-) diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 7103ee974d7..58c9cfb3178 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1159,7 +1159,7 @@ dict_table_open_on_name( table = dict_table_check_if_in_cache_low(table_name); if (table == NULL) { - table = dict_load_table(table_name, true, ignore_err); + table = dict_load_table(table_name, ignore_err); } ut_ad(!table || table->cached); diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 6900d62b225..fc7436e97c8 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -69,7 +69,6 @@ NULL. These tables must be subsequently loaded so that all the foreign key constraints are loaded into memory. @param[in] name Table name in the db/tablename format -@param[in] cached true=add to cache, false=do not @param[in] ignore_err Error to be ignored when loading table and its index definition @param[out] fk_tables Related table names that must also be @@ -82,7 +81,6 @@ static dict_table_t* dict_load_table_one( const table_name_t& name, - bool cached, dict_err_ignore_t ignore_err, dict_names_t& fk_tables); @@ -2777,17 +2775,12 @@ the cluster definition if the table is a member in a cluster. Also loads all foreign key constraints where the foreign key is in the table or where a foreign key references columns in this table. @param[in] name Table name in the dbname/tablename format -@param[in] cached true=add to cache, false=do not @param[in] ignore_err Error to be ignored when loading table and its index definition @return table, NULL if does not exist; if the table is stored in an .ibd file, but the file does not exist, then we set the file_unreadable flag in the table object we return. */ -dict_table_t* -dict_load_table( - const char* name, - bool cached, - dict_err_ignore_t ignore_err) +dict_table_t* dict_load_table(const char* name, dict_err_ignore_t ignore_err) { dict_names_t fk_list; dict_table_t* result; @@ -2802,12 +2795,12 @@ dict_load_table( if (!result) { result = dict_load_table_one(const_cast(name), - cached, ignore_err, fk_list); + ignore_err, fk_list); while (!fk_list.empty()) { if (!dict_table_check_if_in_cache_low(fk_list.front())) dict_load_table_one( const_cast(fk_list.front()), - cached, ignore_err, fk_list); + ignore_err, fk_list); fk_list.pop_front(); } } @@ -2898,7 +2891,6 @@ NULL. These tables must be subsequently loaded so that all the foreign key constraints are loaded into memory. @param[in] name Table name in the db/tablename format -@param[in] cached true=add to cache, false=do not @param[in] ignore_err Error to be ignored when loading table and its index definition @param[out] fk_tables Related table names that must also be @@ -2911,7 +2903,6 @@ static dict_table_t* dict_load_table_one( const table_name_t& name, - bool cached, dict_err_ignore_t ignore_err, dict_names_t& fk_tables) { @@ -2998,11 +2989,7 @@ err_exit: dict_load_virtual(table, heap); - if (cached) { - dict_table_add_to_cache(table, TRUE, heap); - } else { - dict_table_add_system_columns(table, heap); - } + dict_table_add_to_cache(table, TRUE, heap); mem_heap_empty(heap); @@ -3048,7 +3035,7 @@ err_exit: of the error condition, since the user may want to dump data from the clustered index. However we load the foreign key information only if all indexes were loaded. */ - if (!cached || !table->is_readable()) { + if (!table->is_readable()) { /* Don't attempt to load the indexes from disk. */ } else if (err == DB_SUCCESS) { err = dict_load_foreigns(table->name.m_name, NULL, @@ -3229,7 +3216,7 @@ check_rec: /* Load the table definition to memory */ char* table_name = mem_heap_strdupl( heap, (char*) field, len); - table = dict_load_table(table_name, true, ignore_err); + table = dict_load_table(table_name, ignore_err); } } } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index fb3673acf4a..5ff36aa9c24 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -12694,7 +12694,7 @@ int create_table_info_t::create_table(bool create_fk) DICT_ERR_IGNORE_NONE, fk_tables); while (err == DB_SUCCESS && !fk_tables.empty()) { - dict_load_table(fk_tables.front(), true, + dict_load_table(fk_tables.front(), DICT_ERR_IGNORE_NONE); fk_tables.pop_front(); } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index ef7938afec3..9ed13f5ac0d 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -7446,7 +7446,7 @@ innobase_update_foreign_cache( also be loaded. */ while (err == DB_SUCCESS && !fk_tables.empty()) { dict_table_t* table = dict_load_table( - fk_tables.front(), true, DICT_ERR_IGNORE_NONE); + fk_tables.front(), DICT_ERR_IGNORE_NONE); if (table == NULL) { err = DB_TABLE_NOT_FOUND; diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h index 8d5c039a0d5..79440533ab2 100644 --- a/storage/innobase/include/dict0load.h +++ b/storage/innobase/include/dict0load.h @@ -110,17 +110,12 @@ the cluster definition if the table is a member in a cluster. Also loads all foreign key constraints where the foreign key is in the table or where a foreign key references columns in this table. @param[in] name Table name in the dbname/tablename format -@param[in] cached true=add to cache, false=do not @param[in] ignore_err Error to be ignored when loading table and its index definition @return table, NULL if does not exist; if the table is stored in an .ibd file, but the file does not exist, then we set the file_unreadable flag in the table object we return. */ -dict_table_t* -dict_load_table( - const char* name, - bool cached, - dict_err_ignore_t ignore_err); +dict_table_t* dict_load_table(const char* name, dict_err_ignore_t ignore_err); /***********************************************************************//** Loads a table object based on the table id. diff --git a/storage/innobase/include/dict0priv.ic b/storage/innobase/include/dict0priv.ic index f717ddd313a..7b584c7e1cb 100644 --- a/storage/innobase/include/dict0priv.ic +++ b/storage/innobase/include/dict0priv.ic @@ -55,7 +55,7 @@ dict_table_get_low( } if (table == NULL) { - table = dict_load_table(table_name, true, DICT_ERR_IGNORE_NONE); + table = dict_load_table(table_name, DICT_ERR_IGNORE_NONE); } ut_ad(!table || table->cached); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 1ecd0f7f94b..fe2a012c323 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2671,7 +2671,7 @@ row_mysql_drop_garbage_tables() btr_pcur_store_position(&pcur, &mtr); btr_pcur_commit_specify_mtr(&pcur, &mtr); - if (dict_load_table(table_name, true, + if (dict_load_table(table_name, DICT_ERR_IGNORE_DROP)) { row_drop_table_for_mysql( table_name, trx, @@ -3198,7 +3198,7 @@ row_drop_table_from_cache( dict_table_remove_from_cache(table); - if (dict_load_table(tablename, true, DICT_ERR_IGNORE_FK_NOKEY)) { + if (dict_load_table(tablename, DICT_ERR_IGNORE_FK_NOKEY)) { ib::error() << "Not able to remove table " << ut_get_name(trx, tablename) << " from the dictionary cache!"; @@ -4576,7 +4576,7 @@ end: dict_mem_table_fill_foreign_vcol_set(table); while (!fk_tables.empty()) { - dict_load_table(fk_tables.front(), true, + dict_load_table(fk_tables.front(), DICT_ERR_IGNORE_NONE); fk_tables.pop_front(); } From c76873f23ddf4ba36bb14dd3415c3073c51875bf Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Fri, 27 Sep 2019 17:46:10 +0530 Subject: [PATCH 5/5] MDEV-20688 Recovery crashes after unnecessarily reading a corrupted page The test encryption.innodb-redo-badkey was accidentally disabled until commit 23657a21018d0b3d0464bbd55236113ebcd3d4b7 enabled it recently. Once it was enabled, it started failing randomly. recv_recover_corrupt_page(): Do not assume that any redo log exists for the page. A page may be unnecessarily read by read-ahead. When noting the corruption, reset recv_addr->state to RECV_PROCESSED, so that even if the same page is re-read again, we will only decrement recv_sys->n_addrs once. --- .../encryption/r/innodb-redo-badkey.result | 7 ++--- .../encryption/t/innodb-redo-badkey.test | 7 ++--- storage/innobase/log/log0recv.cc | 26 ++++++++++--------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/mysql-test/suite/encryption/r/innodb-redo-badkey.result b/mysql-test/suite/encryption/r/innodb-redo-badkey.result index 101edbf5fdc..e551282667a 100644 --- a/mysql-test/suite/encryption/r/innodb-redo-badkey.result +++ b/mysql-test/suite/encryption/r/innodb-redo-badkey.result @@ -1,9 +1,10 @@ call mtr.add_suppression("Plugin 'file_key_management'"); call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); -call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[0-9]+\\] in file .*test/t[1-4]\\.ibd cannot be decrypted"); +call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[0-9]+\\] in file '.*test/t[1-4]\\.ibd' cannot be decrypted"); call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]"); -call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t1\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); -call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t1 page \\[page id: space=[1-9][0-9]*, page number=[0-9]*\\]"); +call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t[12]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); +call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t[12] page \\[page id: space=[1-9][0-9]*, page number=[0-9]*\\]"); +call mtr.add_suppression("InnoDB: Failed to read file '.*' at offset .*"); call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); # Restart mysqld --file-key-management-filename=keys2.txt diff --git a/mysql-test/suite/encryption/t/innodb-redo-badkey.test b/mysql-test/suite/encryption/t/innodb-redo-badkey.test index 70040f7b2de..502a3828835 100644 --- a/mysql-test/suite/encryption/t/innodb-redo-badkey.test +++ b/mysql-test/suite/encryption/t/innodb-redo-badkey.test @@ -5,10 +5,11 @@ call mtr.add_suppression("Plugin 'file_key_management'"); call mtr.add_suppression("Plugin 'InnoDB' init function returned error."); -call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[0-9]+\\] in file .*test/t[1-4]\\.ibd cannot be decrypted"); +call mtr.add_suppression("InnoDB: The page \\[page id: space=[1-9][0-9]*, page number=[0-9]+\\] in file '.*test/t[1-4]\\.ibd' cannot be decrypted"); call mtr.add_suppression("failed to read or decrypt \\[page id: space=[1-9][0-9]*, page number=[1-9][0-9]*\\]"); -call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t1\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); -call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t1 page \\[page id: space=[1-9][0-9]*, page number=[0-9]*\\]"); +call mtr.add_suppression("InnoDB: Unable to decompress .*.test.t[12]\\.ibd\\[page id: space=[1-9][0-9]*, page number=[0-9]+\\]"); +call mtr.add_suppression("InnoDB: Database page corruption on disk or a failed file read of tablespace test/t[12] page \\[page id: space=[1-9][0-9]*, page number=[0-9]*\\]"); +call mtr.add_suppression("InnoDB: Failed to read file '.*' at offset .*"); call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed"); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 2df1a8950d8..3068a510b4e 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2221,18 +2221,20 @@ void recv_recover_corrupt_page(page_id_t page_id) mutex_enter(&recv_sys->mutex); if (!recv_sys->apply_log_recs) { - mutex_exit(&recv_sys->mutex); - return; - } - - recv_addr_t* recv_addr = recv_get_fil_addr_struct( - page_id.space(), page_id.page_no()); - - ut_ad(recv_addr->state != RECV_WILL_NOT_READ); - - if (recv_addr->state != RECV_BEING_PROCESSED - && recv_addr->state != RECV_PROCESSED) { - recv_sys->n_addrs--; + } else if (recv_addr_t* recv_addr = recv_get_fil_addr_struct( + page_id.space(), page_id.page_no())) { + switch (recv_addr->state) { + case RECV_WILL_NOT_READ: + ut_ad(!"wrong state"); + break; + case RECV_BEING_PROCESSED: + case RECV_PROCESSED: + break; + default: + recv_addr->state = RECV_PROCESSED; + ut_ad(recv_sys->n_addrs); + recv_sys->n_addrs--; + } } mutex_exit(&recv_sys->mutex);