From ca3aa679644e16f5283e1082d395a530c1803765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 3 Jun 2020 12:14:11 +0300 Subject: [PATCH 01/13] MDEV-22577 innodb_fast_shutdown=0 fails to report purge progress srv_purge_should_exit(): Report progress on slow shutdown not only to systemd, but also to the error log. --- storage/innobase/srv/srv0srv.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 6eb67a1b2d4..9818b20ba6c 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -2516,18 +2516,20 @@ srv_purge_should_exit(ulint n_purged) return(true); } /* Slow shutdown was requested. */ - if (n_purged) { -#if defined HAVE_SYSTEMD && !defined EMBEDDED_LIBRARY + if (ulint history_size = n_purged ? trx_sys->rseg_history_len : 0) { static time_t progress_time; time_t now = time(NULL); if (now - progress_time >= 15) { progress_time = now; +#if defined HAVE_SYSTEMD && !defined EMBEDDED_LIBRARY service_manager_extend_timeout( INNODB_EXTEND_TIMEOUT_INTERVAL, "InnoDB: to purge " ULINTPF " transactions", - trx_sys->rseg_history_len); - } + history_size); #endif + ib::info() << "to purge " << history_size + << " transactions"; + } /* The previous round still did some work. */ return(false); } From ad2bf1129cfa85c00072b46e0355fe14bf69ee54 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 27 May 2020 13:03:06 +0530 Subject: [PATCH 02/13] MDEV-22646 Assertion `table2->cached' failed in dict_table_t::add_to_cache Problem: ======== During buffer pool resizing, InnoDB recreates the dictionary hash tables. Dictionary hash table reuses the heap of AHI hash tables. It leads to memory corruption. Fix: ==== - While disabling AHI, free the heap and AHI hash tables. Recreate the AHI hash tables and assign new heap when AHI is enabled. - btr_blob_free() access invalid page if page was reallocated during buffer poolresizing. So btr_blob_free() should get the page from buf_pool instead of using existing block. - btr_search_enabled and block->index should be checked after acquiring the btr_search_sys latch - Moved the buffer_pool_scan debug sync to earlier before accessing the btr_search_sys latches to avoid the hang of truncate_purge_debug test case - srv_printf_innodb_monitor() should acquire btr_search_sys latches before AHI hash tables. --- storage/innobase/btr/btr0cur.cc | 20 +-- storage/innobase/btr/btr0sea.cc | 209 ++++++++++++-------------- storage/innobase/buf/buf0buf.cc | 8 +- storage/innobase/fil/fil0fil.cc | 2 +- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/include/btr0sea.h | 19 +-- storage/innobase/srv/srv0srv.cc | 4 +- storage/innobase/srv/srv0start.cc | 2 +- 8 files changed, 118 insertions(+), 148 deletions(-) diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc index f7cef687dc8..5fc980b42d3 100644 --- a/storage/innobase/btr/btr0cur.cc +++ b/storage/innobase/btr/btr0cur.cc @@ -6631,29 +6631,19 @@ btr_blob_free( mtr_t* mtr) /*!< in: mini-transaction to commit */ { buf_pool_t* buf_pool = buf_pool_from_block(block); - ulint space = block->page.id.space(); - ulint page_no = block->page.id.page_no(); - + const page_id_t page_id = block->page.id; ut_ad(mtr_is_block_fix(mtr, block, MTR_MEMO_PAGE_X_FIX, index->table)); - mtr_commit(mtr); buf_pool_mutex_enter(buf_pool); - /* Only free the block if it is still allocated to - the same file page. */ - - if (buf_block_get_state(block) - == BUF_BLOCK_FILE_PAGE - && block->page.id.space() == space - && block->page.id.page_no() == page_no) { - - if (!buf_LRU_free_page(&block->page, all) - && all && block->page.zip.data) { + if (buf_page_t* bpage = buf_page_hash_get(buf_pool, page_id)) { + if (!buf_LRU_free_page(bpage, all) + && all && bpage->zip.data) { /* Attempt to deallocate the uncompressed page if the whole block cannot be deallocted. */ - buf_LRU_free_page(&block->page, false); + buf_LRU_free_page(bpage, false); } } diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 76aabf287c0..5614adc082a 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -141,28 +141,32 @@ static void btr_search_check_free_space_in_heap(dict_index_t* index) { - hash_table_t* table = btr_get_search_table(index); - mem_heap_t* heap = table->heap; - /* Note that we peek the value of heap->free_block without reserving the latch: this is ok, because we will not guarantee that there will be enough free space in the hash table. */ - if (heap->free_block == NULL) { - buf_block_t* block = buf_block_alloc(NULL); - rw_lock_t* latch = btr_get_search_latch(index); + buf_block_t* block = buf_block_alloc(NULL); + rw_lock_t* latch = btr_get_search_latch(index); + hash_table_t* table; + mem_heap_t* heap; - rw_lock_x_lock(latch); + rw_lock_x_lock(latch); - if (btr_search_enabled - && heap->free_block == NULL) { - heap->free_block = block; - } else { - buf_block_free(block); - } - - rw_lock_x_unlock(latch); + if (!btr_search_enabled) { + goto func_exit; } + + table = btr_get_search_table(index); + heap = table->heap; + + if (heap->free_block == NULL) { + heap->free_block = block; + } else { +func_exit: + buf_block_free(block); + } + + rw_lock_x_unlock(latch); } /** Creates and initializes the adaptive search system at a database start. @@ -191,58 +195,11 @@ btr_search_sys_create(ulint hash_size) btr_search_sys = reinterpret_cast( ut_malloc(sizeof(btr_search_sys_t), mem_key_ahi)); - btr_search_sys->hash_tables = reinterpret_cast( - ut_malloc(sizeof(hash_table_t*) * btr_ahi_parts, mem_key_ahi)); - - for (ulint i = 0; i < btr_ahi_parts; ++i) { - - btr_search_sys->hash_tables[i] = - ib_create((hash_size / btr_ahi_parts), - LATCH_ID_HASH_TABLE_MUTEX, - 0, MEM_HEAP_FOR_BTR_SEARCH); - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - btr_search_sys->hash_tables[i]->adaptive = TRUE; -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - } -} - -/** Resize hash index hash table. -@param[in] hash_size hash index hash table size */ -void -btr_search_sys_resize(ulint hash_size) -{ - /* Step-1: Lock all search latches in exclusive mode. */ - btr_search_x_lock_all(); + btr_search_sys->hash_tables = NULL; if (btr_search_enabled) { - - btr_search_x_unlock_all(); - - ib::error() << "btr_search_sys_resize failed because" - " hash index hash table is not empty."; - ut_ad(0); - return; + btr_search_enable(); } - - /* Step-2: Recreate hash tables with new size. */ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - - mem_heap_free(btr_search_sys->hash_tables[i]->heap); - hash_table_free(btr_search_sys->hash_tables[i]); - - btr_search_sys->hash_tables[i] = - ib_create((hash_size / btr_ahi_parts), - LATCH_ID_HASH_TABLE_MUTEX, - 0, MEM_HEAP_FOR_BTR_SEARCH); - -#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG - btr_search_sys->hash_tables[i]->adaptive = TRUE; -#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ - } - - /* Step-3: Unlock all search latches from exclusive mode. */ - btr_search_x_unlock_all(); } /** Frees the adaptive search system at a database shutdown. */ @@ -251,19 +208,10 @@ btr_search_sys_free() { ut_ad(btr_search_sys != NULL && btr_search_latches != NULL); - /* Step-1: Release the hash tables. */ - for (ulint i = 0; i < btr_ahi_parts; ++i) { - - mem_heap_free(btr_search_sys->hash_tables[i]->heap); - hash_table_free(btr_search_sys->hash_tables[i]); - - } - - ut_free(btr_search_sys->hash_tables); ut_free(btr_search_sys); btr_search_sys = NULL; - /* Step-2: Release all allocates latches. */ + /* Free all latches. */ for (ulint i = 0; i < btr_ahi_parts; ++i) { rw_lock_free(btr_search_latches[i]); @@ -365,26 +313,17 @@ static void buf_pool_clear_hash_index() btr_search_lazy_free(*i); } -/** Disable the adaptive hash search system and empty the index. -@param[in] need_mutex need to acquire dict_sys->mutex */ -void -btr_search_disable( - bool need_mutex) +/** Disable the adaptive hash search system and empty the index. */ +void btr_search_disable() { dict_table_t* table; - if (need_mutex) { - mutex_enter(&dict_sys->mutex); - } + mutex_enter(&dict_sys->mutex); - ut_ad(mutex_own(&dict_sys->mutex)); btr_search_x_lock_all(); if (!btr_search_enabled) { - if (need_mutex) { - mutex_exit(&dict_sys->mutex); - } - + mutex_exit(&dict_sys->mutex); btr_search_x_unlock_all(); return; } @@ -405,34 +344,57 @@ btr_search_disable( btr_search_disable_ref_count(table); } - if (need_mutex) { - mutex_exit(&dict_sys->mutex); - } + mutex_exit(&dict_sys->mutex); /* Set all block->index = NULL. */ buf_pool_clear_hash_index(); /* Clear the adaptive hash index. */ for (ulint i = 0; i < btr_ahi_parts; ++i) { - hash_table_clear(btr_search_sys->hash_tables[i]); - mem_heap_empty(btr_search_sys->hash_tables[i]->heap); + mem_heap_free(btr_search_sys->hash_tables[i]->heap); + hash_table_free(btr_search_sys->hash_tables[i]); } + ut_free(btr_search_sys->hash_tables); + btr_search_sys->hash_tables = NULL; btr_search_x_unlock_all(); } -/** Enable the adaptive hash search system. */ +/** Enable the adaptive hash search system. +@param[in] resize Flag to indicate call during buf_pool_resize() */ void -btr_search_enable() +btr_search_enable(bool resize) { - buf_pool_mutex_enter_all(); - if (srv_buf_pool_old_size != srv_buf_pool_size) { + if (!resize) { + buf_pool_mutex_enter_all(); + if (srv_buf_pool_old_size != srv_buf_pool_size) { + buf_pool_mutex_exit_all(); + return; + } buf_pool_mutex_exit_all(); + } + + ulint hash_size = buf_pool_get_curr_size() / sizeof(void *) / 64; + btr_search_x_lock_all(); + + if (btr_search_sys->hash_tables) { + ut_ad(btr_search_enabled); + btr_search_x_unlock_all(); return; } - buf_pool_mutex_exit_all(); - btr_search_x_lock_all(); + btr_search_sys->hash_tables = reinterpret_cast( + ut_malloc(sizeof(hash_table_t*) * btr_ahi_parts, mem_key_ahi)); + for (ulint i = 0; i < btr_ahi_parts; ++i) { + btr_search_sys->hash_tables[i] = + ib_create((hash_size / btr_ahi_parts), + LATCH_ID_HASH_TABLE_MUTEX, + 0, MEM_HEAP_FOR_BTR_SEARCH); +#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + btr_search_sys->hash_tables[i]->adaptive = TRUE; +#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + } + btr_search_enabled = true; btr_search_x_unlock_all(); } @@ -662,7 +624,8 @@ btr_search_update_hash_ref( if (block->index && (block->curr_n_fields == info->n_fields) && (block->curr_n_bytes == info->n_bytes) - && (block->curr_left_side == info->left_side)) { + && (block->curr_left_side == info->left_side) + && btr_search_enabled) { mem_heap_t* heap = NULL; rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs_init(offsets_); @@ -1173,7 +1136,7 @@ retry: rw_lock_s_lock(latch); assert_block_ahi_valid(block); - if (!block->index) { + if (!block->index || !btr_search_enabled) { rw_lock_s_unlock(latch); return; } @@ -1409,6 +1372,11 @@ btr_search_build_page_hash_index( rw_lock_t* const latch = btr_get_search_latch(index); rw_lock_s_lock(latch); + if (!btr_search_enabled) { + rw_lock_s_unlock(latch); + return; + } + table = btr_get_search_table(index); page = buf_block_get_frame(block); @@ -1517,6 +1485,7 @@ btr_search_build_page_hash_index( goto exit_func; } + table = btr_get_search_table(index); if (block->index && ((block->curr_n_fields != n_fields) || (block->curr_n_bytes != n_bytes) || (block->curr_left_side != left_side))) { @@ -1663,8 +1632,6 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor) ut_a(block->curr_n_fields > 0 || block->curr_n_bytes > 0); ut_ad(!dict_index_is_ibuf(index)); - table = btr_get_search_table(index); - rec = btr_cur_get_rec(cursor); fold = rec_fold(rec, rec_get_offsets(rec, index, offsets_, true, @@ -1678,6 +1645,12 @@ btr_search_update_hash_on_delete(btr_cur_t* cursor) rw_lock_x_lock(latch); assert_block_ahi_valid(block); + if (!btr_search_enabled) { + rw_lock_x_unlock(latch); + return; + } + + table = btr_get_search_table(index); if (block->index) { ut_a(block->index == index); @@ -1732,7 +1705,7 @@ btr_search_update_hash_node_on_insert(btr_cur_t* cursor) rw_lock_t* const latch = btr_get_search_latch(index); rw_lock_x_lock(latch); - if (!block->index) { + if (!block->index || !btr_search_enabled) { goto func_exit; } @@ -1808,8 +1781,6 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor) ut_ad(block->page.id.space() == index->space); btr_search_check_free_space_in_heap(index); - table = btr_get_search_table(index); - rec = btr_cur_get_rec(cursor); #ifdef MYSQL_INDEX_DISABLE_AHI @@ -1850,10 +1821,11 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor) if (locked) { rw_lock_x_lock(latch); - if (!btr_search_enabled) { + if (!btr_search_enabled || !block->index) { goto function_exit; } + table = btr_get_search_table(index); ha_insert_for_fold(table, ins_fold, block, ins_rec); } @@ -1866,9 +1838,10 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor) locked = true; rw_lock_x_lock(latch); - if (!btr_search_enabled) { + if (!btr_search_enabled || !block->index) { goto function_exit; } + table = btr_get_search_table(index); } if (!left_side) { @@ -1886,9 +1859,10 @@ check_next_rec: locked = true; rw_lock_x_lock(latch); - if (!btr_search_enabled) { + if (!btr_search_enabled || !block->index) { goto function_exit; } + table = btr_get_search_table(index); } ha_insert_for_fold(table, ins_fold, block, ins_rec); @@ -1902,9 +1876,10 @@ check_next_rec: locked = true; rw_lock_x_lock(latch); - if (!btr_search_enabled) { + if (!btr_search_enabled || !block->index) { goto function_exit; } + table = btr_get_search_table(index); } if (!left_side) { @@ -1940,7 +1915,9 @@ btr_search_hash_table_validate(ulint hash_table_id) rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs* offsets = offsets_; + btr_search_x_lock_all(); if (!btr_search_enabled) { + btr_search_x_unlock_all(); return(TRUE); } @@ -1950,7 +1927,6 @@ btr_search_hash_table_validate(ulint hash_table_id) rec_offs_init(offsets_); - btr_search_x_lock_all(); buf_pool_mutex_enter_all(); cell_count = hash_get_n_cells( @@ -1967,6 +1943,12 @@ btr_search_hash_table_validate(ulint hash_table_id) os_thread_yield(); btr_search_x_lock_all(); + + if (!btr_search_enabled) { + ok = true; + goto func_exit; + } + buf_pool_mutex_enter_all(); ulint curr_cell_count = hash_get_n_cells( @@ -2084,6 +2066,12 @@ btr_search_hash_table_validate(ulint hash_table_id) os_thread_yield(); btr_search_x_lock_all(); + + if (!btr_search_enabled) { + ok = true; + goto func_exit; + } + buf_pool_mutex_enter_all(); ulint curr_cell_count = hash_get_n_cells( @@ -2108,6 +2096,7 @@ btr_search_hash_table_validate(ulint hash_table_id) } buf_pool_mutex_exit_all(); +func_exit: btr_search_x_unlock_all(); if (UNIV_LIKELY_NULL(heap)) { diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 5cecb9581bd..ca62e088780 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2698,7 +2698,7 @@ buf_pool_resize() btr_search_s_unlock_all(); } - btr_search_disable(true); + btr_search_disable(); if (btr_search_disabled) { ib::info() << "disabled adaptive hash index."; @@ -3072,10 +3072,6 @@ calc_buf_pool_size: srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE); lock_sys_resize(srv_lock_table_size); - /* normalize btr_search_sys */ - btr_search_sys_resize( - buf_pool_get_curr_size() / sizeof(void*) / 64); - /* normalize dict_sys */ dict_resize(); @@ -3100,7 +3096,7 @@ calc_buf_pool_size: #ifdef BTR_CUR_HASH_ADAPT /* enable AHI if needed */ if (btr_search_disabled) { - btr_search_enable(); + btr_search_enable(true); ib::info() << "Re-enabled adaptive hash index."; } #endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index bb7fc0d015f..eaf3a80b6b1 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -3124,10 +3124,10 @@ fil_reinit_space_header_for_table( dict_table_x_unlock_indexes(table); row_mysql_unlock_data_dictionary(trx); + DEBUG_SYNC_C("buffer_pool_scan"); /* Lock the search latch in shared mode to prevent user from disabling AHI during the scan */ btr_search_s_lock_all(); - DEBUG_SYNC_C("buffer_pool_scan"); buf_LRU_flush_or_remove_pages(id, NULL); btr_search_s_unlock_all(); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 895761a5a63..7e2e477cce3 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -18134,7 +18134,7 @@ innodb_adaptive_hash_index_update( if (*(my_bool*) save) { btr_search_enable(); } else { - btr_search_disable(true); + btr_search_disable(); } mysql_mutex_lock(&LOCK_global_system_variables); } diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h index b808ba036db..f2e208df6eb 100644 --- a/storage/innobase/include/btr0sea.h +++ b/storage/innobase/include/btr0sea.h @@ -36,23 +36,17 @@ Created 2/17/1996 Heikki Tuuri void btr_search_sys_create(ulint hash_size); -/** Resize hash index hash table. -@param[in] hash_size hash index hash table size */ -void -btr_search_sys_resize(ulint hash_size); - /** Frees the adaptive search system at a database shutdown. */ void btr_search_sys_free(); -/** Disable the adaptive hash search system and empty the index. -@param need_mutex need to acquire dict_sys->mutex */ +/** Disable the adaptive hash search system and empty the index. */ +void btr_search_disable(); + +/** Enable the adaptive hash search system. +@param[in] resize Flag to indicate call during buf_pool_resize() */ void -btr_search_disable( - bool need_mutex); -/** Enable the adaptive hash search system. */ -void -btr_search_enable(); +btr_search_enable(bool resize=false); /*********************************************************************//** Updates the search info. */ @@ -209,7 +203,6 @@ btr_get_search_table(const dict_index_t* index); # define btr_search_move_or_delete_hash_entries(new_block, block, index) # define btr_search_update_hash_on_insert(cursor) # define btr_search_update_hash_on_delete(cursor) -# define btr_search_sys_resize(hash_size) #endif /* BTR_CUR_HASH_ADAPT */ #ifdef BTR_CUR_ADAPT diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 9818b20ba6c..19d4c7fb7d7 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1333,7 +1333,8 @@ srv_printf_innodb_monitor( ibuf_print(file); #ifdef BTR_CUR_HASH_ADAPT - for (ulint i = 0; i < btr_ahi_parts; ++i) { + btr_search_x_lock_all(); + for (ulint i = 0; i < btr_ahi_parts && btr_search_enabled; ++i) { const hash_table_t* table = btr_search_sys->hash_tables[i]; ut_ad(table->magic_n == HASH_TABLE_MAGIC_N); @@ -1357,6 +1358,7 @@ srv_printf_innodb_monitor( ", node heap has " ULINTPF " buffer(s)\n", table->n_cells, heap->base.count - !heap->free_block); } + btr_search_x_unlock_all(); fprintf(file, "%.2f hash searches/s, %.2f non-hash searches/s\n", diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index e8a6a10d39d..964da389ca5 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2847,7 +2847,7 @@ innodb_shutdown() #ifdef BTR_CUR_HASH_ADAPT if (dict_sys) { - btr_search_disable(true); + btr_search_disable(); } #endif /* BTR_CUR_HASH_ADAPT */ if (ibuf) { From eba2d10ac53d1d2f975027ba2b2ca39d9c9b98ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 4 Jun 2020 10:24:10 +0300 Subject: [PATCH 03/13] MDEV-22721 Remove bloat caused by InnoDB logger class Introduce a new ATTRIBUTE_NOINLINE to ib::logger member functions, and add UNIV_UNLIKELY hints to callers. Also, remove some crash reporting output. If needed, the information will be available using debugging tools. Furthermore, remove some fts_enable_diag_print output that included indexed words in raw form. The code seemed to assume that words are NUL-terminated byte strings. It is not clear whether a NUL terminator is always guaranteed to be present. Also, UCS2 or UTF-16 strings would typically contain many NUL bytes. --- include/my_compiler.h | 4 ++ storage/innobase/buf/buf0buf.cc | 23 +++---- storage/innobase/buf/buf0dblwr.cc | 4 +- storage/innobase/buf/buf0flu.cc | 15 ++--- storage/innobase/buf/buf0lru.cc | 43 +------------ storage/innobase/dict/dict0crea.cc | 19 +++--- storage/innobase/dict/dict0load.cc | 4 +- storage/innobase/dict/dict0stats.cc | 10 +-- storage/innobase/fil/fil0crypt.cc | 17 +++-- storage/innobase/fil/fil0fil.cc | 6 +- storage/innobase/fsp/fsp0file.cc | 4 +- storage/innobase/fsp/fsp0fsp.cc | 2 +- storage/innobase/fts/fts0config.cc | 16 ++--- storage/innobase/fts/fts0fts.cc | 53 +++++++--------- storage/innobase/fts/fts0opt.cc | 40 +++++------- storage/innobase/fts/fts0que.cc | 25 +++----- storage/innobase/handler/ha_innodb.cc | 5 +- storage/innobase/handler/handler0alter.cc | 2 +- storage/innobase/handler/i_s.cc | 8 +-- storage/innobase/include/btr0pcur.ic | 2 +- storage/innobase/include/lock0lock.h | 1 + storage/innobase/include/ut0ut.h | 77 +++++++++++------------ storage/innobase/lock/lock0lock.cc | 34 +++++----- storage/innobase/log/log0recv.cc | 24 +++---- storage/innobase/page/page0page.cc | 19 +++--- storage/innobase/row/row0ftsort.cc | 19 +++--- storage/innobase/row/row0import.cc | 4 +- storage/innobase/row/row0merge.cc | 3 +- storage/innobase/row/row0mysql.cc | 11 ++-- storage/innobase/row/row0undo.cc | 11 +--- storage/innobase/row/row0upd.cc | 14 ++--- storage/innobase/row/row0vers.cc | 2 +- storage/innobase/srv/srv0conc.cc | 6 +- storage/innobase/srv/srv0start.cc | 4 +- storage/innobase/trx/trx0purge.cc | 5 +- storage/innobase/trx/trx0rec.cc | 4 +- storage/innobase/trx/trx0trx.cc | 5 +- storage/innobase/ut/ut0ut.cc | 8 ++- 38 files changed, 227 insertions(+), 326 deletions(-) diff --git a/include/my_compiler.h b/include/my_compiler.h index 12e6c1a087c..faffd852b5d 100644 --- a/include/my_compiler.h +++ b/include/my_compiler.h @@ -2,6 +2,7 @@ #define MY_COMPILER_INCLUDED /* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2017, 2020, 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 @@ -150,6 +151,7 @@ struct my_aligned_storage #ifdef __GNUC__ # define ATTRIBUTE_NORETURN __attribute__((noreturn)) +# define ATTRIBUTE_NOINLINE __attribute__((noinline)) # if MY_GNUC_PREREQ(4,3) /** Starting with GCC 4.3, the "cold" attribute is used to inform the compiler that a function is unlikely executed. The function is @@ -163,8 +165,10 @@ rarely invoked function for size instead for speed. */ # endif #elif defined _MSC_VER # define ATTRIBUTE_NORETURN __declspec(noreturn) +# define ATTRIBUTE_NOINLINE __declspec(noinline) #else # define ATTRIBUTE_NORETURN /* empty */ +# define ATTRIBUTE_NOINLINE /* empty */ #endif #ifndef ATTRIBUTE_COLD diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index ca62e088780..4b78cb38b42 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -3725,9 +3725,9 @@ lookup: ut_ad(!hash_lock); dberr_t err = buf_read_page(page_id, page_size); - if (err != DB_SUCCESS) { + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::error() << "Reading compressed page " << page_id - << " failed with error: " << ut_strerr(err); + << " failed with error: " << err; goto err_exit; } @@ -5250,7 +5250,8 @@ buf_page_init( if (hash_page == NULL) { /* Block not found in hash table */ - } else if (buf_pool_watch_is_sentinel(buf_pool, hash_page)) { + } else if (UNIV_LIKELY(buf_pool_watch_is_sentinel(buf_pool, + hash_page))) { /* Preserve the reference count. */ ib_uint32_t buf_fix_count = hash_page->buf_fix_count; @@ -5260,18 +5261,8 @@ buf_page_init( buf_pool_watch_remove(buf_pool, hash_page); } else { - - ib::error() << "Page " << page_id - << " already found in the hash table: " - << hash_page << ", " << block; - - ut_d(buf_page_mutex_exit(block)); - ut_d(buf_pool_mutex_exit(buf_pool)); - ut_d(buf_print()); - ut_d(buf_LRU_print()); - ut_d(buf_validate()); - ut_d(buf_LRU_validate()); - ut_error; + ib::fatal() << "Page already foudn in the hash table: " + << page_id; } ut_ad(!block->page.in_zip_hash); @@ -7253,6 +7244,7 @@ operator<<( return(out); } +#if defined UNIV_DEBUG_PRINT || defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /** Print the given buf_pool_t object. @param[in,out] out the output stream @param[in] buf_pool the buf_pool_t object to be printed @@ -7280,6 +7272,7 @@ operator<<( << ", written=" << buf_pool.stat.n_pages_written << "]"; return(out); } +#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */ /** Encrypt a buffer of temporary tablespace @param[in] offset Page offset diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 7fb4cf9a9d3..42128f873eb 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -600,11 +600,11 @@ buf_dblwr_process() page_id, page_size, 0, page_size.physical(), read_buf, NULL); - if (err != DB_SUCCESS) { + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::warn() << "Double write buffer recovery: " << page_id << " read failed with " - << "error: " << ut_strerr(err); + << "error: " << err; } const bool is_all_zero = buf_is_zeroes( diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 3c91c9595c4..7318d4f1eb6 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -578,18 +578,11 @@ buf_flush_ready_for_replace( #endif /* UNIV_DEBUG */ ut_ad(mutex_own(buf_page_get_mutex(bpage))); ut_ad(bpage->in_LRU_list); + ut_a(buf_page_in_file(bpage)); - if (buf_page_in_file(bpage)) { - - return(bpage->oldest_modification == 0 - && bpage->buf_fix_count == 0 - && buf_page_get_io_fix(bpage) == BUF_IO_NONE); - } - - ib::fatal() << "Buffer block " << bpage << " state " << bpage->state - << " in the LRU list!"; - - return(FALSE); + return bpage->oldest_modification == 0 + && bpage->buf_fix_count == 0 + && buf_page_get_io_fix(bpage) == BUF_IO_NONE; } /********************************************************************//** diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 107d0628400..317a17b142f 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -1824,46 +1824,9 @@ buf_LRU_block_remove_hashed( } hashed_bpage = buf_page_hash_get_low(buf_pool, bpage->id); - if (bpage != hashed_bpage) { - ib::error() << "Page " << bpage->id - << " not found in the hash table"; - -#ifdef UNIV_DEBUG - - - ib::error() - << "in_page_hash:" << bpage->in_page_hash - << " in_zip_hash:" << bpage->in_zip_hash - // << " in_free_list:"<< bpage->in_fee_list - << " in_flush_list:" << bpage->in_flush_list - << " in_LRU_list:" << bpage->in_LRU_list - << " zip.data:" << bpage->zip.data - << " zip_size:" << bpage->size.logical() - << " page_state:" << buf_page_get_state(bpage); -#else - ib::error() - << " zip.data:" << bpage->zip.data - << " zip_size:" << bpage->size.logical() - << " page_state:" << buf_page_get_state(bpage); -#endif - - if (hashed_bpage) { - - ib::error() << "In hash table we find block " - << hashed_bpage << " of " << hashed_bpage->id - << " which is not " << bpage; - } - -#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG - mutex_exit(buf_page_get_mutex(bpage)); - rw_lock_x_unlock(hash_lock); - buf_pool_mutex_exit(buf_pool); - buf_print(); - buf_LRU_print(); - buf_validate(); - buf_LRU_validate(); -#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ - ut_error; + if (UNIV_UNLIKELY(bpage != hashed_bpage)) { + ib::fatal() << "Page not found in the hash table: " + << bpage->id; } ut_ad(!bpage->in_zip_hash); diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc index 1a3d6c51d98..2976581c19f 100644 --- a/storage/innobase/dict/dict0crea.cc +++ b/storage/innobase/dict/dict0crea.cc @@ -1719,10 +1719,9 @@ dict_create_or_check_foreign_constraint_tables(void) "END;\n", FALSE, trx); - if (err != DB_SUCCESS) { - + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::error() << "Creation of SYS_FOREIGN and SYS_FOREIGN_COLS" - " failed: " << ut_strerr(err) << ". Tablespace is" + " failed: " << err << ". Tablespace is" " full. Dropping incompletely created tables."; ut_ad(err == DB_OUT_OF_FILE_SPACE @@ -1821,10 +1820,9 @@ dict_create_or_check_sys_virtual() "END;\n", FALSE, trx); - if (err != DB_SUCCESS) { - + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::error() << "Creation of SYS_VIRTUAL" - " failed: " << ut_strerr(err) << ". Tablespace is" + " failed: " << err << ". Tablespace is" " full or too many transactions." " Dropping incompletely created tables."; @@ -1902,9 +1900,9 @@ dict_foreign_eval_sql( return(error); } - if (error != DB_SUCCESS) { + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { ib::error() << "Foreign key constraint creation failed: " - << ut_strerr(error); + << error; mutex_enter(&dict_foreign_err_mutex); ut_print_timestamp(ef); @@ -2353,10 +2351,9 @@ dict_create_or_check_sys_tablespace(void) "END;\n", FALSE, trx); - if (err != DB_SUCCESS) { - + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::error() << "Creation of SYS_TABLESPACES and SYS_DATAFILES" - " has failed with error " << ut_strerr(err) + " has failed with error " << err << ". Dropping incompletely created tables."; ut_a(err == DB_OUT_OF_FILE_SPACE diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 486f3c1081c..96309329ad4 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -925,7 +925,7 @@ dict_update_filepath( trx->dict_operation_lock_mode = 0; trx_free_for_background(trx); - if (err == DB_SUCCESS) { + if (UNIV_LIKELY(err == DB_SUCCESS)) { /* We just updated SYS_DATAFILES due to the contents in a link file. Make a note that we did this. */ ib::info() << "The InnoDB data dictionary table SYS_DATAFILES" @@ -935,7 +935,7 @@ dict_update_filepath( ib::warn() << "Error occurred while updating InnoDB data" " dictionary table SYS_DATAFILES for tablespace ID " << space_id << " to file " << filepath << ": " - << ut_strerr(err) << "."; + << err << "."; } return(err); diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 0da77dfdff7..77c1e9627eb 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -2355,14 +2355,14 @@ dict_stats_save_index_stat( ");\n" "END;", trx); - if (ret != DB_SUCCESS) { + if (UNIV_UNLIKELY(ret != DB_SUCCESS)) { if (innodb_index_stats_not_found == false && index->stats_error_printed == false) { ib::error() << "Cannot save index statistics for table " << index->table->name << ", index " << index->name << ", stat name \"" << stat_name << "\": " - << ut_strerr(ret); + << ret; index->stats_error_printed = true; } } @@ -2473,9 +2473,9 @@ dict_stats_save( ");\n" "END;", NULL); - if (ret != DB_SUCCESS) { + if (UNIV_UNLIKELY(ret != DB_SUCCESS)) { ib::error() << "Cannot save table statistics for table " - << table->name << ": " << ut_strerr(ret); + << table->name << ": " << ret; mutex_exit(&dict_sys->mutex); rw_lock_x_unlock(&dict_operation_lock); @@ -3330,7 +3330,7 @@ dict_stats_update( " for table " << table->name << " from " TABLE_STATS_NAME_PRINT " and " - INDEX_STATS_NAME_PRINT ": " << ut_strerr(err) + INDEX_STATS_NAME_PRINT ": " << err << ". Using transient stats method instead."; } diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index f06aa7606ee..331516e868a 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -298,14 +298,9 @@ fil_space_read_crypt_data(const page_size_t& page_size, const byte* page) type == CRYPT_SCHEME_1) || iv_length != sizeof crypt_data->iv) { ib::error() << "Found non sensible crypt scheme: " - << type << "," << iv_length << " for space: " - << page_get_space_id(page) << " offset: " - << offset << " bytes: [" - << page[offset + 2 + MAGIC_SZ] - << page[offset + 3 + MAGIC_SZ] - << page[offset + 4 + MAGIC_SZ] - << page[offset + 5 + MAGIC_SZ] - << "]."; + << type << "," << iv_length + << " for space: " + << page_get_space_id(page); return NULL; } @@ -725,8 +720,10 @@ fil_space_decrypt( } ib::fatal() << "Unable to decrypt data-block " - << " src: " << src << "srclen: " - << srclen << " buf: " << dst << "buflen: " + << " src: " << static_cast(src) + << "srclen: " + << srclen << " buf: " + << static_cast(dst) << "buflen: " << dstlen << " return-code: " << rc << " Can't continue!"; } diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index eaf3a80b6b1..69790c44617 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -3228,12 +3228,12 @@ fil_discard_tablespace( case DB_IO_ERROR: ib::warn() << "While deleting tablespace " << id << " in DISCARD TABLESPACE. File rename/delete" - " failed: " << ut_strerr(err); + " failed: " << err; break; case DB_TABLESPACE_NOT_FOUND: ib::warn() << "Cannot delete tablespace " << id - << " in DISCARD TABLESPACE: " << ut_strerr(err); + << " in DISCARD TABLESPACE: " << err; break; default: @@ -5177,7 +5177,7 @@ fil_aio_wait( ib::error() << "Failed to read file '" << node->name << "' at offset " << offset - << ": " << ut_strerr(err); + << ": " << err; } fil_space_release_for_io(space); diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc index 673e74cfb3d..5abdf22d939 100644 --- a/storage/innobase/fsp/fsp0file.cc +++ b/storage/innobase/fsp/fsp0file.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2020, 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 @@ -331,7 +331,7 @@ Datafile::read_first_page(bool read_only_mode) ib::error() << "Cannot read first page of '" << m_filepath << "' " - << ut_strerr(err); + << err; break; } } diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 06f66e88e56..2501f4f8ba3 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -1437,7 +1437,7 @@ fsp_alloc_free_page( ut_a(!is_system_tablespace(space_id)); if (page_no >= FSP_EXTENT_SIZE) { ib::error() << "Trying to extend a single-table" - " tablespace " << space << " , by single" + " tablespace " << space->name << " , by single" " page(s) though the space size " << space_size << ". Page no " << page_no << "."; return(NULL); diff --git a/storage/innobase/fts/fts0config.cc b/storage/innobase/fts/fts0config.cc index 6130546e963..768e3a2eabd 100644 --- a/storage/innobase/fts/fts0config.cc +++ b/storage/innobase/fts/fts0config.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, 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 @@ -317,9 +317,7 @@ fts_config_get_index_ulint( error = fts_config_get_index_value(trx, index, name, &value); if (UNIV_UNLIKELY(error != DB_SUCCESS)) { - - ib::error() << "(" << ut_strerr(error) << ") reading `" - << name << "'"; + ib::error() << "(" << error << ") reading `" << name << "'"; } else { *int_value = strtoul((char*) value.f_str, NULL, 10); } @@ -357,9 +355,7 @@ fts_config_set_index_ulint( error = fts_config_set_index_value(trx, index, name, &value); if (UNIV_UNLIKELY(error != DB_SUCCESS)) { - - ib::error() << "(" << ut_strerr(error) << ") writing `" - << name << "'"; + ib::error() << "(" << error << ") writing `" << name << "'"; } ut_free(value.f_str); @@ -391,8 +387,7 @@ fts_config_get_ulint( error = fts_config_get_value(trx, fts_table, name, &value); if (UNIV_UNLIKELY(error != DB_SUCCESS)) { - ib::error() << "(" << ut_strerr(error) << ") reading `" - << name << "'"; + ib::error() << "(" << error << ") reading `" << name << "'"; } else { *int_value = strtoul((char*) value.f_str, NULL, 10); } @@ -430,8 +425,7 @@ fts_config_set_ulint( error = fts_config_set_value(trx, fts_table, name, &value); if (UNIV_UNLIKELY(error != DB_SUCCESS)) { - ib::error() << "(" << ut_strerr(error) << ") writing `" - << name << "'"; + ib::error() << "(" << error << ") writing `" << name << "'"; } ut_free(value.f_str); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 2706c59495b..dd4938dd019 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -510,7 +510,7 @@ cleanup: for (;;) { dberr_t error = fts_eval_sql(trx, graph); - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); stopword_info->status = STOPWORD_USER_TABLE; break; @@ -523,7 +523,7 @@ cleanup: trx->error_state = DB_SUCCESS; } else { - ib::error() << "Error '" << ut_strerr(error) + ib::error() << "Error '" << error << "' while reading user stopword" " table."; ret = FALSE; @@ -1454,9 +1454,9 @@ fts_drop_table( error = row_drop_table_for_mysql(table_name, trx, SQLCOM_DROP_DB, false, false); - if (error != DB_SUCCESS) { + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { ib::error() << "Unable to drop FTS index aux table " - << table_name << ": " << ut_strerr(error); + << table_name << ": " << error; } } else { error = DB_FAIL; @@ -2535,8 +2535,7 @@ fts_get_max_cache_size( error = fts_config_get_value( trx, fts_table, FTS_MAX_CACHE_SIZE_IN_MB, &value); - if (error == DB_SUCCESS) { - + if (UNIV_LIKELY(error == DB_SUCCESS)) { value.f_str[value.f_len] = 0; cache_size_in_mb = strtoul((char*) value.f_str, NULL, 10); @@ -2566,7 +2565,7 @@ fts_get_max_cache_size( cache_size_in_mb = FTS_CACHE_SIZE_LOWER_LIMIT_IN_MB; } } else { - ib::error() << "(" << ut_strerr(error) << ") reading max" + ib::error() << "(" << error << ") reading max" " cache config value from config table"; } @@ -2735,13 +2734,12 @@ retry: func_exit: - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); } else { *doc_id = 0; - ib::error() << "(" << ut_strerr(error) << ") while getting" - " next doc id."; + ib::error() << "(" << error << ") while getting next doc id."; fts_sql_rollback(trx); if (error == DB_DEADLOCK) { @@ -2816,12 +2814,11 @@ fts_update_sync_doc_id( fts_que_graph_free_check_lock(&fts_table, NULL, graph); if (local_trx) { - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); cache->synced_doc_id = doc_id; } else { - - ib::error() << "(" << ut_strerr(error) << ") while" + ib::error() << "(" << error << ") while" " updating last doc id."; fts_sql_rollback(trx); @@ -4065,14 +4062,14 @@ fts_sync_write_words( n_nodes += ib_vector_size(word->nodes); - if (error != DB_SUCCESS && !print_error) { - ib::error() << "(" << ut_strerr(error) << ") writing" + if (UNIV_UNLIKELY(error != DB_SUCCESS) && !print_error) { + ib::error() << "(" << error << ") writing" " word node to FTS auxiliary index table."; print_error = TRUE; } } - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { printf("Avg number of nodes: %lf\n", (double) n_nodes / (double) (n_words > 1 ? n_words : 1)); } @@ -4098,7 +4095,7 @@ fts_sync_begin( sync->trx = trx_allocate_for_background(); trx_start_internal(sync->trx); - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "FTS SYNC for table " << sync->table->name << ", deleted count: " << ib_vector_size(cache->deleted_doc_ids) @@ -4121,7 +4118,7 @@ fts_sync_index( trx->op_info = "doing SYNC index"; - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "SYNC words: " << rbt_size(index_cache->words); } @@ -4218,18 +4215,14 @@ fts_sync_commit( fts_cache_init(cache); rw_lock_x_unlock(&cache->lock); - if (error == DB_SUCCESS) { - + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); - - } else if (error != DB_SUCCESS) { - + } else { fts_sql_rollback(trx); - - ib::error() << "(" << ut_strerr(error) << ") during SYNC."; + ib::error() << "(" << error << ") during SYNC."; } - if (fts_enable_diag_print && elapsed_time) { + if (UNIV_UNLIKELY(fts_enable_diag_print) && elapsed_time) { ib::info() << "SYNC for table " << sync->table->name << ": SYNC time: " << (time(NULL) - sync->start_time) @@ -4983,7 +4976,7 @@ fts_get_rows_count( for (;;) { error = fts_eval_sql(trx, graph); - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); break; /* Exit the loop. */ @@ -4996,7 +4989,7 @@ fts_get_rows_count( trx->error_state = DB_SUCCESS; } else { - ib::error() << "(" << ut_strerr(error) + ib::error() << "(" << error << ") while reading FTS table."; break; /* Exit the loop. */ @@ -7061,7 +7054,7 @@ fts_drop_orphaned_tables(void) for (;;) { error = fts_eval_sql(trx, graph); - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_check_and_drop_orphaned_tables(trx, tables); break; /* Exit the loop. */ } else { @@ -7075,7 +7068,7 @@ fts_drop_orphaned_tables(void) trx->error_state = DB_SUCCESS; } else { - ib::error() << "(" << ut_strerr(error) + ib::error() << "(" << error << ") while reading SYS_TABLES."; break; /* Exit the loop. */ diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index 39a7b086e34..ae943577348 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -525,7 +525,7 @@ fts_index_fetch_nodes( for (;;) { error = fts_eval_sql(trx, *graph); - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); break; /* Exit the loop. */ @@ -538,7 +538,7 @@ fts_index_fetch_nodes( trx->error_state = DB_SUCCESS; } else { - ib::error() << "(" << ut_strerr(error) + ib::error() << "(" << error << ") while reading FTS index."; break; /* Exit the loop. */ @@ -860,7 +860,7 @@ fts_index_fetch_words( error = fts_eval_sql(optim->trx, graph); } - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { //FIXME fts_sql_commit(optim->trx); break; } else { @@ -877,7 +877,7 @@ fts_index_fetch_words( optim->trx->error_state = DB_SUCCESS; } else { - ib::error() << "(" << ut_strerr(error) + ib::error() << "(" << error << ") while reading document."; break; /* Exit the loop. */ @@ -1356,12 +1356,6 @@ fts_optimize_word( enc.src_last_doc_id = 0; enc.src_ilist_ptr = NULL; - if (fts_enable_diag_print) { - word->text.f_str[word->text.f_len] = 0; - ib::info() << "FTS_OPTIMIZE: optimize \"" << word->text.f_str - << "\""; - } - while (i < size) { ulint copied; fts_node_t* src_node; @@ -1439,11 +1433,6 @@ fts_optimize_write_word( ut_ad(fts_table->charset); - if (fts_enable_diag_print) { - ib::info() << "FTS_OPTIMIZE: processed \"" << word->f_str - << "\""; - } - pars_info_bind_varchar_literal( info, "word", word->f_str, word->f_len); @@ -1461,8 +1450,8 @@ fts_optimize_write_word( error = fts_eval_sql(trx, graph); - if (error != DB_SUCCESS) { - ib::error() << "(" << ut_strerr(error) << ") during optimize," + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { + ib::error() << "(" << error << ") during optimize," " when deleting a word from the FTS index."; } @@ -1485,8 +1474,8 @@ fts_optimize_write_word( error = fts_write_node( trx, &graph, fts_table, word, node); - if (error != DB_SUCCESS) { - ib::error() << "(" << ut_strerr(error) << ")" + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { + ib::error() << "(" << error << ")" " during optimize, while adding a" " word to the FTS index."; } @@ -1875,9 +1864,8 @@ fts_optimize_index_completed( error = fts_config_set_index_value( optim->trx, index, FTS_LAST_OPTIMIZED_WORD, &word); - if (error != DB_SUCCESS) { - - ib::error() << "(" << ut_strerr(error) << ") while updating" + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { + ib::error() << "(" << error << ") while updating" " last optimized word!"; } @@ -2429,7 +2417,7 @@ fts_optimize_table( fts_optimize_t* optim = NULL; fts_t* fts = table->fts; - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "FTS start optimize " << table->name; } @@ -2481,7 +2469,7 @@ fts_optimize_table( if (error == DB_SUCCESS && optim->n_completed == ib_vector_size(fts->indexes)) { - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "FTS_OPTIMIZE: Completed" " Optimize, cleanup DELETED table"; } @@ -2504,7 +2492,7 @@ fts_optimize_table( fts_optimize_free(optim); - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "FTS end optimize " << table->name; } @@ -2689,7 +2677,7 @@ static bool fts_optimize_del_table(const dict_table_t* table) slot = static_cast(ib_vector_get(fts_slots, i)); if (slot->table == table) { - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "FTS Optimize Removing table " << table->name; } diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 57ab4c4379f..81018f57619 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, 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 @@ -2447,9 +2447,8 @@ fts_query_match_document( get_doc, match->doc_id, NULL, FTS_FETCH_DOC_BY_ID_EQUAL, fts_query_fetch_document, &phrase); - if (error != DB_SUCCESS) { - ib::error() << "(" << ut_strerr(error) - << ") matching document."; + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { + ib::error() << "(" << error << ") matching document."; } else { *found = phrase.found; } @@ -2495,8 +2494,8 @@ fts_query_is_in_proximity_range( &get_doc, match[0]->doc_id, NULL, FTS_FETCH_DOC_BY_ID_EQUAL, fts_query_fetch_document, &phrase); - if (err != DB_SUCCESS) { - ib::error() << "(" << ut_strerr(err) << ") in verification" + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { + ib::error() << "(" << err << ") in verification" " phase of proximity search"; } @@ -3501,14 +3500,6 @@ fts_query_calculate_idf( / (double) word_freq->doc_count); } } - - if (fts_enable_diag_print) { - ib::info() << "'" << word_freq->word.f_str << "' -> " - << query->total_docs << "/" - << word_freq->doc_count << " " - << std::setw(6) << std::setprecision(5) - << word_freq->idf; - } } } @@ -3884,7 +3875,7 @@ fts_query_parse( } else { query->root = state.root; - if (fts_enable_diag_print && query->root != NULL) { + if (UNIV_UNLIKELY(fts_enable_diag_print) && query->root) { fts_ast_node_print(query->root); } } @@ -4108,7 +4099,7 @@ fts_query( ut_free(lc_query_str); - if (fts_enable_diag_print && (*result)) { + if (UNIV_UNLIKELY(fts_enable_diag_print) && (*result)) { ulint diff_time = ut_time_ms() - start_time_ms; ib::info() << "FTS Search Processing time: " @@ -4264,7 +4255,7 @@ fts_expand_query( query->total_size += SIZEOF_RBT_CREATE; - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { fts_print_doc_id(query); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 7e2e477cce3..bcb02704158 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -8128,8 +8128,7 @@ ha_innobase::write_row( if (high_level_read_only) { ib_senderrf(ha_thd(), IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE); DBUG_RETURN(HA_ERR_TABLE_READONLY); - } else if (m_prebuilt->trx != trx) { - + } else if (UNIV_UNLIKELY(m_prebuilt->trx != trx)) { ib::error() << "The transaction object for the table handle is" " at " << static_cast(m_prebuilt->trx) << ", but for the current thread it is at " @@ -9989,7 +9988,7 @@ ha_innobase::ft_init_ext( const CHARSET_INFO* char_set = key->charset(); const char* query = key->ptr(); - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { { ib::info out; out << "keynr=" << keynr << ", '"; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index d347d0e51a4..d057afef9b5 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -8826,7 +8826,7 @@ foreign_fail: trx_start_for_ddl(trx, TRX_DICT_OP_TABLE); dberr_t error = row_merge_drop_table(trx, ctx->old_table); - if (error != DB_SUCCESS) { + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { ib::error() << "Inplace alter table " << ctx->old_table->name << " dropping copy of the old table failed error " << error diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index 960bd8113db..584f6e05714 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -3474,7 +3474,7 @@ i_s_fts_index_table_fill_selected( for (;;) { error = fts_eval_sql(trx, graph); - if (error == DB_SUCCESS) { + if (UNIV_LIKELY(error == DB_SUCCESS)) { fts_sql_commit(trx); break; @@ -3488,7 +3488,7 @@ i_s_fts_index_table_fill_selected( trx->error_state = DB_SUCCESS; } else { ib::error() << "Error occurred while reading" - " FTS index: " << ut_strerr(error); + " FTS index: " << error; break; } } @@ -8086,9 +8086,7 @@ i_s_dict_fill_sys_tablespaces( break; default: - ib::error() - << "File '" << filepath << "' " - << ut_strerr(err); + ib::error() << "File '" << filepath << "' " << err; break; } diff --git a/storage/innobase/include/btr0pcur.ic b/storage/innobase/include/btr0pcur.ic index b5b57050832..6bc5b356dab 100644 --- a/storage/innobase/include/btr0pcur.ic +++ b/storage/innobase/include/btr0pcur.ic @@ -458,7 +458,7 @@ btr_pcur_open_low( index, level, tuple, mode, latch_mode, btr_cursor, 0, file, line, mtr, autoinc); - if (err != DB_SUCCESS) { + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::warn() << " Error code: " << err << " btr_pcur_open_low " << " level: " << level diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index 2ff8d74a024..edde6bf516e 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -571,6 +571,7 @@ lock_has_to_wait( locks are record locks */ /*********************************************************************//** Reports that a transaction id is insensible, i.e., in the future. */ +ATTRIBUTE_COLD void lock_report_trx_id_insanity( /*========================*/ diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index 741687c07d7..a19f3db188d 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2019, MariaDB Corporation. +Copyright (c) 2019, 2020, 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 @@ -389,48 +389,41 @@ operator<<( It contains a std::ostringstream object. The main purpose of this class is to forward operator<< to the underlying std::ostringstream object. Do not use this class directly, instead use one of the derived classes. */ -class logger { -public: - template - ATTRIBUTE_COLD - logger& operator<<(const T& rhs) - { - m_oss << rhs; - return(*this); - } - - /** Write the given buffer to the internal string stream object. - @param[in] buf the buffer whose contents will be logged. - @param[in] count the length of the buffer buf. - @return the output stream into which buffer was written. */ - ATTRIBUTE_COLD - std::ostream& - write( - const char* buf, - std::streamsize count) - { - return(m_oss.write(buf, count)); - } - - /** Write the given buffer to the internal string stream object. - @param[in] buf the buffer whose contents will be logged. - @param[in] count the length of the buffer buf. - @return the output stream into which buffer was written. */ - ATTRIBUTE_COLD - std::ostream& - write( - const byte* buf, - std::streamsize count) - { - return(m_oss.write(reinterpret_cast(buf), count)); - } - - std::ostringstream m_oss; +class logger +{ protected: - /* This class must not be used directly, hence making the default - constructor protected. */ - ATTRIBUTE_COLD - logger() {} + /* This class must not be used directly */ + ATTRIBUTE_COLD ATTRIBUTE_NOINLINE logger() {} +public: + template ATTRIBUTE_COLD ATTRIBUTE_NOINLINE + logger& operator<<(const T& rhs) + { + m_oss << rhs; + return *this; + } + + /** Handle a fixed character string in the same way as a pointer to + an unknown-length character string, to reduce object code bloat. */ + template logger& operator<<(const char (&rhs)[N]) + { return *this << static_cast(rhs); } + + /** Output an error code name */ + ATTRIBUTE_COLD logger& operator<<(dberr_t err); + + /** Append a string. + @param buf string buffer + @param size buffer size + @return the output stream */ + ATTRIBUTE_COLD __attribute__((noinline)) + std::ostream &write(const char *buf, std::streamsize size) + { + return m_oss.write(buf, size); + } + + std::ostream &write(const byte *buf, std::streamsize size) + { return write(reinterpret_cast(buf), size); } + + std::ostringstream m_oss; }; /** The class info is used to emit informational log messages. It is to be diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 11c080066d6..c4c045ffba3 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -320,6 +320,7 @@ static FILE* lock_latest_err_file; /*********************************************************************//** Reports that a transaction id is insensible, i.e., in the future. */ +ATTRIBUTE_COLD void lock_report_trx_id_insanity( /*========================*/ @@ -330,7 +331,7 @@ lock_report_trx_id_insanity( trx_id_t max_trx_id) /*!< in: trx_sys_get_max_trx_id() */ { ib::error() - << "Transaction id " << trx_id + << "Transaction id " << ib::hex(trx_id) << " associated with record" << rec_offsets_print(rec, offsets) << " in index " << index->name << " of table " << index->table->name @@ -359,7 +360,7 @@ lock_check_trx_id_sanity( trx_id_t max_trx_id = trx_sys_get_max_trx_id(); bool is_ok = trx_id < max_trx_id; - if (!is_ok) { + if (UNIV_UNLIKELY(!is_ok)) { lock_report_trx_id_insanity( trx_id, rec, index, offsets, max_trx_id); } @@ -756,7 +757,7 @@ lock_rec_has_to_wait( wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { mtr_t mtr; - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "BF-BF lock conflict, locking: " << for_locking; lock_rec_print(stderr, lock2, mtr); @@ -770,7 +771,7 @@ lock_rec_has_to_wait( lock2->trx->mysql_thd) && (type_mode & LOCK_MODE_MASK) == LOCK_X && (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) { - if (for_locking || wsrep_debug) { + if (UNIV_UNLIKELY(for_locking || wsrep_debug)) { /* exclusive lock conflicts are not accepted */ ib::info() << @@ -797,7 +798,7 @@ lock_rec_has_to_wait( lock2->index->n_user_defined_cols operation is on uniq index */ - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "BF conflict, modes: " << type_mode << ":" << lock2->type_mode @@ -1111,7 +1112,7 @@ wsrep_kill_victim( trx->mysql_thd, lock->trx->mysql_thd))) { if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: BF victim waiting\n"; } /* cannot release lock, until our lock @@ -1344,13 +1345,14 @@ lock_number_of_tables_locked( /*============== RECORD LOCK CREATION AND QUEUE MANAGEMENT =============*/ #ifdef WITH_WSREP +ATTRIBUTE_COLD static void wsrep_print_wait_locks( /*===================*/ lock_t* c_lock) /* conflicting lock to print */ { - if (wsrep_debug && c_lock->trx->lock.wait_lock != c_lock) { + if (c_lock->trx->lock.wait_lock != c_lock) { mtr_t mtr; ib::info() << "WSREP: c_lock != wait lock"; ib::info() << " SQL: " @@ -1502,7 +1504,7 @@ lock_rec_create_low( c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { wsrep_print_wait_locks(c_lock); } @@ -1529,7 +1531,7 @@ lock_rec_create_low( trx_mutex_exit(c_lock->trx); - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: c_lock canceled " << ib::hex(c_lock->trx->id) << " SQL: " @@ -1794,7 +1796,7 @@ lock_rec_enqueue_waiting( transaction as a victim, it is possible that we already have the lock now granted! */ #ifdef WITH_WSREP - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: BF thread got lock granted early, ID " << ib::hex(trx->id) << " query: " << wsrep_thd_query(trx->mysql_thd); } @@ -2213,7 +2215,7 @@ lock_rec_has_to_wait_in_queue( #ifdef WITH_WSREP if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) && wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE)) { - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { mtr_t mtr; ib::info() << "WSREP: waiting BF trx: " << ib::hex(wait_lock->trx->id) << " query: " << wsrep_thd_query(wait_lock->trx->mysql_thd); @@ -3657,7 +3659,7 @@ lock_table_create( if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { ut_list_insert(table->locks, c_lock, lock, TableLockGetNode()); - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "table lock BF conflict for " << ib::hex(c_lock->trx->id) << " SQL: " @@ -3673,7 +3675,7 @@ lock_table_create( if (c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { wsrep_print_wait_locks(c_lock); } @@ -3684,7 +3686,7 @@ lock_table_create( c_lock->trx->lock.wait_lock); trx_mutex_enter(trx); - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: c_lock canceled " << ib::hex(c_lock->trx->id) << " SQL: " @@ -3957,9 +3959,9 @@ lock_table_other_has_incompatible( #ifdef WITH_WSREP if (lock->trx->is_wsrep()) { - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: table lock abort for table:" - << table->name.m_name; + << table->name; ib::info() << " SQL: " << wsrep_thd_query(lock->trx->mysql_thd); } diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 4ef22468f05..2d0f3c83e3b 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -589,7 +589,7 @@ fil_name_parse( ut_ad(0); // the caller checked this /* fall through */ case MLOG_FILE_NAME: - if (corrupt) { + if (UNIV_UNLIKELY(corrupt)) { ib::error() << "MLOG_FILE_NAME incorrect:" << ptr; recv_sys->found_corrupt_log = true; break; @@ -599,7 +599,7 @@ fil_name_parse( reinterpret_cast(ptr), len, space_id, false); break; case MLOG_FILE_DELETE: - if (corrupt) { + if (UNIV_UNLIKELY(corrupt)) { ib::error() << "MLOG_FILE_DELETE incorrect:" << ptr; recv_sys->found_corrupt_log = true; break; @@ -627,7 +627,7 @@ fil_name_parse( } break; case MLOG_FILE_RENAME2: - if (corrupt) { + if (UNIV_UNLIKELY(corrupt)) { ib::error() << "MLOG_FILE_RENAME2 incorrect:" << ptr; recv_sys->found_corrupt_log = true; } @@ -668,7 +668,7 @@ fil_name_parse( } } - if (corrupt) { + if (UNIV_UNLIKELY(corrupt)) { ib::error() << "MLOG_FILE_RENAME2 new_name incorrect:" << ptr << " new_name: " << new_name; recv_sys->found_corrupt_log = true; @@ -2697,6 +2697,7 @@ recv_calc_lsn_on_data_add( @param[in] space tablespace ID (could be garbage) @param[in] page_no page number (could be garbage) @return whether processing should continue */ +ATTRIBUTE_COLD static bool recv_report_corrupt_log( @@ -2713,7 +2714,8 @@ recv_report_corrupt_log( ib::info() << "Log record type " << type << ", page " << space << ":" << page_no << ". Log parsing proceeded successfully up to " << recv_sys->recovered_lsn << ". Previous log record type " - << recv_previous_parsed_rec_type << ", is multi " + << recv_previous_parsed_rec_type + << ", is multi " << recv_previous_parsed_rec_is_multi << " Recv offset " << ptr_offset << ", prev " << recv_previous_parsed_rec_offset; @@ -2853,12 +2855,12 @@ loop: len = recv_parse_log_rec(&type, ptr, end_ptr, &space, &page_no, apply, &body); - if (recv_sys->found_corrupt_log) { + if (UNIV_UNLIKELY(recv_sys->found_corrupt_log)) { recv_report_corrupt_log(ptr, type, space, page_no); return(true); } - if (recv_sys->found_corrupt_fs) { + if (UNIV_UNLIKELY(recv_sys->found_corrupt_fs)) { return(true); } @@ -2982,7 +2984,7 @@ loop: &type, ptr, end_ptr, &space, &page_no, false, &body); - if (recv_sys->found_corrupt_log) { + if (UNIV_UNLIKELY(recv_sys->found_corrupt_log)) { corrupted_log: recv_report_corrupt_log( ptr, type, space, page_no); @@ -3075,13 +3077,13 @@ corrupted_log: &type, ptr, end_ptr, &space, &page_no, apply, &body); - if (recv_sys->found_corrupt_log + if (UNIV_UNLIKELY(recv_sys->found_corrupt_log) && !recv_report_corrupt_log( ptr, type, space, page_no)) { return(true); } - if (recv_sys->found_corrupt_fs) { + if (UNIV_UNLIKELY(recv_sys->found_corrupt_fs)) { return(true); } @@ -3597,7 +3599,7 @@ recv_validate_tablespace(bool rescan, bool& missing_tablespace) for (recv_spaces_t::iterator i = recv_spaces.begin(); i != recv_spaces.end(); i++) { - if (i->second.status != file_name_t::MISSING) { + if (UNIV_LIKELY(i->second.status != file_name_t::MISSING)) { continue; } diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index fa0239b4259..d28d2f9a082 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2438,7 +2438,10 @@ page_validate( if (UNIV_UNLIKELY((ibool) !!page_is_comp(page) != dict_table_is_comp(index->table))) { ib::error() << "'compact format' flag mismatch"; - goto func_exit2; +func_exit2: + ib::error() << "Apparent corruption in space " + << page_get_space_id(page) << " page " + << page_get_page_no(page) << " index " << index->name; } if (page_is_comp(page)) { if (UNIV_UNLIKELY(!page_simple_validate_new(page))) { @@ -2480,15 +2483,14 @@ page_validate( n_slots = page_dir_get_n_slots(page); - if (UNIV_UNLIKELY(!(page_header_get_ptr(page, PAGE_HEAP_TOP) - <= page_dir_get_nth_slot(page, n_slots - 1)))) { + const void* top = page_header_get_ptr(page, PAGE_HEAP_TOP); + const void* last_slot = page_dir_get_nth_slot(page, n_slots - 1); + if (UNIV_UNLIKELY(top > last_slot)) { ib::warn() << "Record heap and dir overlap on space " << page_get_space_id(page) << " page " << page_get_page_no(page) << " index " << index->name - << ", " << page_header_get_ptr(page, PAGE_HEAP_TOP) - << ", " << page_dir_get_nth_slot(page, n_slots - 1); - + << ", " << top << ", " << last_slot; goto func_exit; } @@ -2747,10 +2749,7 @@ func_exit: mem_heap_free(heap); if (UNIV_UNLIKELY(ret == FALSE)) { -func_exit2: - ib::error() << "Apparent corruption in space " - << page_get_space_id(page) << " page " - << page_get_page_no(page) << " index " << index->name; + goto func_exit2; } return(ret); diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 2bd99a48628..c7c86fb337b 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -864,7 +864,8 @@ loop: num_doc_processed++; - if (fts_enable_diag_print && num_doc_processed % 10000 == 1) { + if (UNIV_UNLIKELY(fts_enable_diag_print) + && num_doc_processed % 10000 == 1) { ib::info() << "Number of documents processed: " << num_doc_processed; #ifdef FTS_INTERNAL_DIAG_PRINT @@ -1009,7 +1010,7 @@ exit: } } - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { DEBUG_FTS_SORT_PRINT(" InnoDB_FTS: start merge sort\n"); } @@ -1040,7 +1041,7 @@ exit: } func_exit: - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { DEBUG_FTS_SORT_PRINT(" InnoDB_FTS: complete merge sort\n"); } @@ -1215,11 +1216,9 @@ row_merge_write_fts_word( error = row_merge_write_fts_node(ins_ctx, &word->text, fts_node); - if (error != DB_SUCCESS) { - ib::error() << "Failed to write word " - << word->text.f_str << " to FTS auxiliary" - " index table, error (" << ut_strerr(error) - << ")"; + if (UNIV_UNLIKELY(error != DB_SUCCESS)) { + ib::error() << "Failed to write word to FTS auxiliary" + " index table, error " << error; ret = error; } @@ -1633,7 +1632,7 @@ row_fts_merge_insert( count_diag += (int) psort_info[i].merge_file[id]->n_rec; } - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "InnoDB_FTS: to insert " << count_diag << " records"; } @@ -1801,7 +1800,7 @@ exit: mem_heap_free(heap); - if (fts_enable_diag_print) { + if (UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "InnoDB_FTS: inserted " << count << " records"; } diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index d92bcb761e4..ed78b2a154d 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1885,7 +1885,7 @@ PageConverter::update_index_page( row_index_t* index = find_index(id); - if (index == 0) { + if (UNIV_UNLIKELY(!index)) { ib::error() << "Page for tablespace " << m_space << " is index page with id " << id << " but that index is not found from" @@ -2132,7 +2132,7 @@ row_import_discard_changes( ib::info() << "Discarding tablespace of table " << prebuilt->table->name - << ": " << ut_strerr(err); + << ": " << err; if (trx->dict_operation_lock_mode != RW_X_LATCH) { ut_a(trx->dict_operation_lock_mode == 0); diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 8c8f1674374..e44b9aae626 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -4917,7 +4917,8 @@ wait_again: goto func_exit; } - if (indexes[i]->type & DICT_FTS && fts_enable_diag_print) { + if (indexes[i]->type & DICT_FTS + && UNIV_UNLIKELY(fts_enable_diag_print)) { ib::info() << "Finished building full-text index " << indexes[i]->name; } diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 9bbd531cb9a..d3efc5fc256 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -782,8 +782,7 @@ handle_new_error: " foreign constraints and try again"; goto rollback_to_savept; default: - ib::fatal() << "Unknown error code " << err << ": " - << ut_strerr(err); + ib::fatal() << "Unknown error " << err; } if (trx->error_state != DB_SUCCESS) { @@ -3161,10 +3160,10 @@ row_drop_ancillary_fts_tables( dberr_t err = fts_drop_tables(trx, table); - if (err != DB_SUCCESS) { + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::error() << " Unable to remove ancillary FTS" " tables for table " - << table->name << " : " << ut_strerr(err); + << table->name << " : " << err; return(err); } @@ -4009,10 +4008,10 @@ loop: table_name, trx, SQLCOM_DROP_DB); trx_commit_for_mysql(trx); - if (err != DB_SUCCESS) { + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::error() << "DROP DATABASE " << ut_get_name(trx, name) << " failed" - " with error (" << ut_strerr(err) << ") for" + " with error (" << err << ") for" " table " << ut_get_name(trx, table_name); ut_free(table_name); break; diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index 5f3e3de7f8d..b65b173fedb 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -358,15 +358,8 @@ row_undo_step( trx->error_state = err; - if (err != DB_SUCCESS) { - /* SQL error detected */ - - if (err == DB_OUT_OF_FILE_SPACE) { - ib::fatal() << "Out of tablespace during rollback." - " Consider increasing your tablespace."; - } - - ib::fatal() << "Error (" << ut_strerr(err) << ") in rollback."; + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { + ib::fatal() << "Error (" << err << ") in rollback."; } return(thr); diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index a1e840a9cb9..a7cd06d25fd 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2472,7 +2472,7 @@ row_upd_sec_index_entry( err = DB_SUCCESS; break; case DB_LOCK_WAIT: - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::warn() << "WSREP: sec index FK lock wait" << " index " << index->name << " table " << index->table->name @@ -2480,7 +2480,7 @@ row_upd_sec_index_entry( } break; case DB_DEADLOCK: - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name @@ -2488,7 +2488,7 @@ row_upd_sec_index_entry( } break; default: - ib::error() << "WSREP: referenced FK check fail: " << ut_strerr(err) + ib::error() << "WSREP: referenced FK check fail: " << err << " index " << index->name << " table " << index->table->name << " query " << wsrep_thd_query(trx->mysql_thd); @@ -2787,14 +2787,14 @@ check_fk: err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; } goto err_exit; default: - ib::error() << "WSREP: referenced FK check fail: " << ut_strerr(err) + ib::error() << "WSREP: referenced FK check fail: " << err << " index " << index->name << " table " << index->table->name; goto err_exit; @@ -3013,14 +3013,14 @@ row_upd_del_mark_clust_rec( err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; } break; default: - ib::error() << "WSREP: referenced FK check fail: " << ut_strerr(err) + ib::error() << "WSREP: referenced FK check fail: " << err << " index " << index->name << " table " << index->table->name; diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 3627c659231..09509444ea4 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -119,7 +119,7 @@ row_vers_impl_x_locked_low( if (trx == 0) { /* The transaction that modified or inserted clust_rec is no longer active, or it is corrupt: no implicit lock on rec */ - if (corrupt) { + if (UNIV_UNLIKELY(corrupt)) { lock_report_trx_id_insanity( trx_id, clust_rec, clust_index, clust_offsets, trx_sys_get_max_trx_id()); diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc index 9936635a055..b420ca6d8ee 100644 --- a/storage/innobase/srv/srv0conc.cc +++ b/storage/innobase/srv/srv0conc.cc @@ -123,7 +123,7 @@ srv_conc_enter_innodb_with_atomics( ulint sleep_in_us; #ifdef WITH_WSREP if (trx->is_wsrep() && wsrep_trx_is_aborting(trx->mysql_thd)) { - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "srv_conc_enter due to MUST_ABORT"; } @@ -324,14 +324,14 @@ wsrep_srv_conc_cancel_wait( srv_conc_enter_innodb_with_atomics(). No need to cancel here, thr will wake up after os_sleep and let to enter innodb */ - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: conc slot cancel, no atomics"; } #else // JAN: TODO: MySQL 5.7 //os_fast_mutex_lock(&srv_conc_mutex); if (trx->wsrep_event) { - if (wsrep_debug) { + if (UNIV_UNLIKELY(wsrep_debug)) { ib::info() << "WSREP: conc slot cancel"; } os_event_set(trx->wsrep_event); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 964da389ca5..d6ad7bf437a 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1329,7 +1329,7 @@ srv_init_abort_low( #ifdef UNIV_DEBUG " at " << innobase_basename(file) << "[" << line << "]" #endif /* UNIV_DEBUG */ - " with error " << ut_strerr(err) << ". You may need" + " with error " << err << ". You may need" " to delete the ibdata1 file before trying to start" " up again."; } else { @@ -1337,7 +1337,7 @@ srv_init_abort_low( #ifdef UNIV_DEBUG " at " << innobase_basename(file) << "[" << line << "]" #endif /* UNIV_DEBUG */ - " with error " << ut_strerr(err); + " with error " << err; } srv_shutdown_all_bg_threads(); diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 81ba1b731bf..2f728b22fb2 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -698,12 +698,11 @@ namespace undo { os_file_close(handle); - if (err != DB_SUCCESS) { - + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { ib::info() << "Unable to read '" << log_file_name << "' : " - << ut_strerr(err); + << err; os_file_delete( innodb_log_file_key, log_file_name); diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 0ad9ff0dae8..ee022b4f1fd 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1565,9 +1565,7 @@ trx_undo_update_rec_get_update( << " fields " << BUG_REPORT_MSG << ". Run also CHECK TABLE " << index->table->name << "." - " n_fields = " << n_fields << ", i = " << i - << ", ptr " << ptr; - + " n_fields = " << n_fields << ", i = " << i; ut_ad(0); *upd = NULL; return(NULL); diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 5768f0fc890..a19ab2c9c98 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -478,9 +478,8 @@ trx_validate_state_before_free(trx_t* trx) ut_ad(!trx->mysql_n_tables_locked); ut_ad(!trx->internal); - if (trx->declared_to_be_inside_innodb) { - - ib::error() << "Freeing a trx (" << trx << ", " + if (UNIV_UNLIKELY(trx->declared_to_be_inside_innodb)) { + ib::error() << "Freeing a trx (" << trx_get_id_for_print(trx) << ") which is declared" " to be processing inside InnoDB"; diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index b50735a391d..c6822c1d74e 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, 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 @@ -614,6 +614,12 @@ ut_basename_noext( namespace ib { +ATTRIBUTE_COLD logger& logger::operator<<(dberr_t err) +{ + m_oss << ut_strerr(err); + return *this; +} + info::~info() { sql_print_information("InnoDB: %s", m_oss.str().c_str()); From 05693cf2149f8792863a32325090e789015286fc Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Thu, 4 Jun 2020 12:12:49 +0300 Subject: [PATCH 04/13] MDEV-22112 Assertion `tab_part_info->part_type == RANGE_PARTITION || tab_part_info->part_type == LIST_PARTITION' failed in prep_alter_part_table Incorrect syntax for SYSTEM_TIME partition. work_part_info is detected as HASH partition. We cannot add partition of different type neither we cannot reorganize SYSTEM_TIME into/from different type partitioning. The sidefix for version until 10.5 corrects the message: "For LIST partitions each partition must be defined" --- mysql-test/suite/versioning/r/partition.result | 10 ++++++++++ mysql-test/suite/versioning/t/partition.test | 17 +++++++++++++++++ sql/partition_info.cc | 2 ++ sql/sql_partition.cc | 3 ++- 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mysql-test/suite/versioning/r/partition.result b/mysql-test/suite/versioning/r/partition.result index ab206db1213..a89053369a7 100644 --- a/mysql-test/suite/versioning/r/partition.result +++ b/mysql-test/suite/versioning/r/partition.result @@ -673,4 +673,14 @@ delete from v1; ERROR HY000: Table 't1' was locked with a READ lock and can't be updated drop view v1; drop table t1; +# +# MDEV-22112 Assertion `tab_part_info->part_type == RANGE_PARTITION || tab_part_info->part_type == LIST_PARTITION' failed in prep_alter_part_table +# +create table t1 (a int) with system versioning partition by system_time; +ERROR HY000: For SYSTEM_TIME partitions each partition must be defined +create table t1 (a int) with system versioning partition by system_time +(partition p1 history, partition pn current); +alter table t1 add partition (partition p2); +ERROR HY000: Wrong partitioning type, expected type: `SYSTEM_TIME` +drop table t1; # End of 10.3 tests diff --git a/mysql-test/suite/versioning/t/partition.test b/mysql-test/suite/versioning/t/partition.test index 726b991c00e..957fddc730d 100644 --- a/mysql-test/suite/versioning/t/partition.test +++ b/mysql-test/suite/versioning/t/partition.test @@ -635,6 +635,23 @@ delete from v1; drop view v1; drop table t1; +--echo # +--echo # MDEV-22112 Assertion `tab_part_info->part_type == RANGE_PARTITION || tab_part_info->part_type == LIST_PARTITION' failed in prep_alter_part_table +--echo # + +### TMP: Please remove this error check in 10.5 (MDEV-19903) +--error ER_PARTITIONS_MUST_BE_DEFINED_ERROR +create table t1 (a int) with system versioning partition by system_time; +### TMP end + +create table t1 (a int) with system versioning partition by system_time +(partition p1 history, partition pn current); +--error ER_PARTITION_WRONG_TYPE +alter table t1 add partition (partition p2); + +# Cleanup +drop table t1; + --echo # End of 10.3 tests --source suite/versioning/common_finish.inc diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 66ec6a70b12..8989a918c0c 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -451,6 +451,8 @@ bool partition_info::set_up_default_partitions(THD *thd, handler *file, const char *error_string; if (part_type == RANGE_PARTITION) error_string= "RANGE"; + else if (part_type == VERSIONING_PARTITION) + error_string= "SYSTEM_TIME"; else error_string= "LIST"; my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), error_string); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index f7158a2b1ee..4e9c78480b5 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -5135,7 +5135,8 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0), "LIST", "IN"); } - else if (thd->work_part_info->part_type == VERSIONING_PARTITION) + else if (thd->work_part_info->part_type == VERSIONING_PARTITION || + tab_part_info->part_type == VERSIONING_PARTITION) { my_error(ER_PARTITION_WRONG_TYPE, MYF(0), "SYSTEM_TIME"); } From f69278bcd0a1ffba767918b040f6e8465c37397b Mon Sep 17 00:00:00 2001 From: Varun Gupta Date: Tue, 2 Jun 2020 16:31:53 +0530 Subject: [PATCH 05/13] MDEV-16230: Server crashes when Analyze format=json is run with a window function with empty PARTITION BY and ORDER BY clauses Currently when both PARTITION BY and ORDER BY clauses are empty then we create a Item with the first field in the select list and sort with that field. It should be created as an Item_temptable_field instead of Item_field because the print() function continues to work even if the table has been dropped. --- mysql-test/r/win.result | 45 +++++++++++++++++++++++++++++++++++++++++ mysql-test/t/win.test | 13 ++++++++++++ sql/sql_window.cc | 3 ++- 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result index 35371f49a50..c73f9f8ce6b 100644 --- a/mysql-test/r/win.result +++ b/mysql-test/r/win.result @@ -3743,5 +3743,50 @@ a ROW_NUMBER() OVER v2 1 1 drop table t0; # +# MDEV-16230:Server crashes when Analyze format=json is run with a window function with +# empty PARTITION BY and ORDER BY clauses +# +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +ANALYZE FORMAT=JSON SELECT row_number() OVER() FROM t1; +ANALYZE +{ + "query_block": { + "select_id": 1, + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "window_functions_computation": { + "sorts": { + "filesort": { + "sort_key": "`row_number() OVER()`", + "r_loops": 1, + "r_total_time_ms": "REPLACED", + "r_used_priority_queue": false, + "r_output_rows": 3, + "r_buffer_size": "REPLACED" + } + }, + "temporary_table": { + "table": { + "table_name": "t1", + "access_type": "ALL", + "r_loops": 1, + "rows": 3, + "r_rows": 3, + "r_total_time_ms": "REPLACED", + "filtered": 100, + "r_filtered": 100 + } + } + } + } +} +SELECT row_number() OVER() FROM t1; +row_number() OVER() +1 +2 +3 +DROP TABLE t1; +# # End of 10.2 tests # diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test index e3025a400d7..37c107633d9 100644 --- a/mysql-test/t/win.test +++ b/mysql-test/t/win.test @@ -2446,6 +2446,19 @@ WINDOW v2 AS ( PARTITION BY a ORDER BY a DESC ); drop table t0; +--echo # +--echo # MDEV-16230:Server crashes when Analyze format=json is run with a window function with +--echo # empty PARTITION BY and ORDER BY clauses +--echo # + +CREATE TABLE t1(a INT, b INT); +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); + +--source include/analyze-format.inc +ANALYZE FORMAT=JSON SELECT row_number() OVER() FROM t1; +SELECT row_number() OVER() FROM t1; +DROP TABLE t1; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/sql_window.cc b/sql/sql_window.cc index b258b8f56c9..18075d179d5 100644 --- a/sql/sql_window.cc +++ b/sql/sql_window.cc @@ -2872,7 +2872,8 @@ bool Window_funcs_sort::setup(THD *thd, SQL_SELECT *sel, */ ORDER *order= (ORDER *)alloc_root(thd->mem_root, sizeof(ORDER)); memset(order, 0, sizeof(*order)); - Item *item= new (thd->mem_root) Item_field(thd, join_tab->table->field[0]); + Item *item= new (thd->mem_root) Item_temptable_field(thd, + join_tab->table->field[0]); order->item= (Item **)alloc_root(thd->mem_root, 2 * sizeof(Item *)); order->item[1]= NULL; order->item[0]= item; From c5883debd6ef440a037011c11873b396923e93c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 4 Jun 2020 16:31:29 +0300 Subject: [PATCH 06/13] dict_check_sys_tables(): Do not rely on buf_page_optimistic_get() We are supposed to commit and restart the mini-transaction between records. There is no point to store and restore the persistent cursor position otherwise. If buf_page_optimistic_get() is patched to always fail, the debug build would fail to start up due to trying to re-acquire an already S-latched block. This bug (which should not have visible impact to users, because the code is only executed during startup, while no other threads are accessing B-trees or causing pages to be evicted from the buffer pool) was caught as part of a debugging effort for something else. The debugging approach was: Make buf_page_optimistic_get() always return FALSE, and add ut_a(block->lock.lock_word == X_LOCK_DECR) to both buf_LRU_get_free_only() and buf_LRU_block_free_non_file_page(). This would catch misuse of the buffer pool. If it were not for buf_page_optimistic_get(), no buf_block_t::lock of any BUF_BLOCK_NOT_USED block would ever be acquired. --- storage/innobase/dict/dict0load.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc index 96309329ad4..63ccf6bbb96 100644 --- a/storage/innobase/dict/dict0load.cc +++ b/storage/innobase/dict/dict0load.cc @@ -1388,6 +1388,7 @@ static ulint dict_check_sys_tables() for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES); rec != NULL; + mtr.commit(), mtr.start(), rec = dict_getnext_system(&pcur, &mtr)) { const byte* field; ulint len; From dce4c0f9790f3b3e6f3309b52869ed97963a4eee Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 23 Apr 2020 21:58:52 +0400 Subject: [PATCH 07/13] MDEV-22339 - Assertion `str_length < len' failed When acquiring SNW/SNRW/X MDL lock DDL/admin statements may abort pending thr lock in concurrent connection with open HANDLER (or delayed insert thread). This may lead to a race condition when table->alias is accessed concurrently by such threads. Either assertion failure or memory leak is a practical consequence of this race condition. Specifically HANDLER is opening a table and issuing alias.copy(), while DDL executing get_lock_data()/alias.c_ptr()/realloc()/realloc_raw(). Fixed by perforimg table->init() before it is published via thd->open_tables. --- mysql-test/suite/stress/r/misc.result | 9 ++++++++ mysql-test/suite/stress/t/misc.test | 32 +++++++++++++++++++++++++++ sql/sql_base.cc | 8 +++---- 3 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 mysql-test/suite/stress/r/misc.result create mode 100644 mysql-test/suite/stress/t/misc.test diff --git a/mysql-test/suite/stress/r/misc.result b/mysql-test/suite/stress/r/misc.result new file mode 100644 index 00000000000..6d0a3ea5050 --- /dev/null +++ b/mysql-test/suite/stress/r/misc.result @@ -0,0 +1,9 @@ +# +# MDEV-22339 - Assertion `str_length < len' failed in +# Binary_string::realloc_raw +# +CREATE TABLE t1(a INT) ENGINE=MyISAM; +connect con1, localhost, root; +disconnect con1; +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/stress/t/misc.test b/mysql-test/suite/stress/t/misc.test new file mode 100644 index 00000000000..e8255cb3a81 --- /dev/null +++ b/mysql-test/suite/stress/t/misc.test @@ -0,0 +1,32 @@ +--echo # +--echo # MDEV-22339 - Assertion `str_length < len' failed in +--echo # Binary_string::realloc_raw +--echo # +CREATE TABLE t1(a INT) ENGINE=MyISAM; +connect con1, localhost, root; +let $i=1000; +disable_query_log; +disable_result_log; +while ($i) +{ + connection default; + HANDLER t1 OPEN; + send SELECT * FROM t1, t1 t1a1over8, t1 t1a2over8, t1 t1a3over8, t1 t1a4over8, t1 t1a5over8, t1 t1a6over8; + + connection con1; + send REPAIR TABLE t1; + + connection default; + reap; + HANDLER t1 CLOSE; + + connection con1; + reap; + dec $i; +} +enable_query_log; +enable_result_log; +disconnect con1; + +connection default; +DROP TABLE t1; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6c7ef7a85c9..436f753557e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1675,6 +1675,7 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx) { table= best_table; table->query_id= thd->query_id; + table->init(thd, table_list); DBUG_PRINT("info",("Using locked table")); goto reset; } @@ -1959,12 +1960,13 @@ retry_share: } table->mdl_ticket= mdl_ticket; + table->reginfo.lock_type=TL_READ; /* Assume read */ + + table->init(thd, table_list); table->next= thd->open_tables; /* Link into simple list */ thd->set_open_tables(table); - table->reginfo.lock_type=TL_READ; /* Assume read */ - reset: /* Check that there is no reference to a condition from an earlier query @@ -1989,8 +1991,6 @@ retry_share: } #endif - table->init(thd, table_list); - DBUG_RETURN(FALSE); err_lock: From 29ed04cb6d8e930c2b2bad7baf4cdae02cf712cd Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 3 Jun 2020 14:43:13 +0200 Subject: [PATCH 08/13] add stress suite to the list of default suites to run --- mysql-test/mysql-test-run.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 29294590ae3..2d4f3df3f5d 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -200,6 +200,7 @@ my @DEFAULT_SUITES= qw( plugins- roles- rpl- + stress- sys_vars- unit- vcol- From 1828196f73a66ef0e4594cdf32c6652149f8b3f8 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Fri, 5 Jun 2020 13:29:01 +0200 Subject: [PATCH 09/13] Windows, build tweak. Allow targets for building "noinstall" zip, and debuginfo zip. --- win/packaging/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/win/packaging/CMakeLists.txt b/win/packaging/CMakeLists.txt index 130f74118ca..1935874995f 100644 --- a/win/packaging/CMakeLists.txt +++ b/win/packaging/CMakeLists.txt @@ -212,10 +212,17 @@ IF(SIGNCODE) ENDIF() ADD_CUSTOM_TARGET( - win_package + win_package_zip ${SIGN_COMMAND} COMMAND ${CMAKE_CPACK_COMMAND} ${CPACK_CONFIG_PARAM} --config ${CMAKE_CURRENT_SOURCE_DIR}/CPackZipConfig.cmake + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} +) + +ADD_CUSTOM_TARGET( + win_package_debuginfo COMMAND ${CMAKE_CPACK_COMMAND} ${CPACK_CONFIG_PARAM} --config ${CMAKE_CURRENT_SOURCE_DIR}/CPackZipDebugInfoConfig.cmake WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) +ADD_CUSTOM_TARGET(win_package DEPENDS win_package_zip win_package_debuginfo) + From 3677dd5cb438e7b3ddb46a547f36fc2691c031a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 5 Jun 2020 15:20:20 +0300 Subject: [PATCH 10/13] MDEV-22646: Fix a memory leak btr_search_sys_free(): Free btr_search_sys->hash_tables. The leak was introduced in commit ad2bf1129cfa85c00072b46e0355fe14bf69ee54. --- storage/innobase/btr/btr0sea.cc | 34 +++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 5614adc082a..ff1241740a4 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -203,23 +203,33 @@ btr_search_sys_create(ulint hash_size) } /** Frees the adaptive search system at a database shutdown. */ -void -btr_search_sys_free() +void btr_search_sys_free() { - ut_ad(btr_search_sys != NULL && btr_search_latches != NULL); + ut_ad(btr_search_sys); + ut_ad(btr_search_latches); - ut_free(btr_search_sys); - btr_search_sys = NULL; + if (btr_search_sys->hash_tables) + { + for (ulint i= 0; i < btr_ahi_parts; ++i) + { + mem_heap_free(btr_search_sys->hash_tables[i]->heap); + hash_table_free(btr_search_sys->hash_tables[i]); + } + ut_free(btr_search_sys->hash_tables); + } - /* Free all latches. */ - for (ulint i = 0; i < btr_ahi_parts; ++i) { + ut_free(btr_search_sys); + btr_search_sys= NULL; - rw_lock_free(btr_search_latches[i]); - ut_free(btr_search_latches[i]); - } + /* Free all latches. */ + for (ulint i= 0; i < btr_ahi_parts; ++i) + { + rw_lock_free(btr_search_latches[i]); + ut_free(btr_search_latches[i]); + } - ut_free(btr_search_latches); - btr_search_latches = NULL; + ut_free(btr_search_latches); + btr_search_latches= NULL; } /** Set index->ref_count = 0 on all indexes of a table. From 138c11cce59304ba67b9229d267eef1503a968fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 4 Jun 2020 12:29:32 +0300 Subject: [PATCH 11/13] MDEV-22790 Race between btr_page_mtr_lock() dropping AHI on the same block This race condition was introduced by commit ad6171b91cac33e70bb28fa6865488b2c65e858c (MDEV-22456). In the observed case, two threads were executing btr_search_drop_page_hash_index() on the same block, to free a stale entry that was attached to a dropped index. Both threads were holding an S latch on the block. We must prevent the double-free of block->index by holding block->lock in exclusive mode. btr_search_guess_on_hash(): Do not invoke btr_search_drop_page_hash_index(block) to get rid of stale entries, because we are not necessarily holding an exclusive block->lock here. buf_defer_drop_ahi(): New function, to safely drop stale entries in buf_page_mtr_lock(). We will skip the call to btr_search_drop_page_hash_index(block) when only requesting bufferfixing (no page latch), because in that case, we should not be accessing the adaptive hash index, and we might get a deadlock if we acquired the page latch. --- storage/innobase/btr/btr0sea.cc | 1 - storage/innobase/buf/buf0buf.cc | 42 ++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index ff1241740a4..491a3e375d3 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -989,7 +989,6 @@ fail: buf_block_dbg_add_level(block, SYNC_TREE_NODE_FROM_HASH); if (UNIV_UNLIKELY(fail)) { - btr_search_drop_page_hash_index(block); goto fail_and_release_page; } } else if (UNIV_UNLIKELY(index != block->index diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 4b78cb38b42..802e67de1b0 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -4125,6 +4125,46 @@ buf_wait_for_read( } } +#ifdef BTR_CUR_HASH_ADAPT +/** If a stale adaptive hash index exists on the block, drop it. +Multiple executions of btr_search_drop_page_hash_index() on the +same block must be prevented by exclusive page latch. */ +ATTRIBUTE_COLD +static void buf_defer_drop_ahi(buf_block_t *block, mtr_memo_type_t fix_type) +{ + switch (fix_type) { + case MTR_MEMO_BUF_FIX: + /* We do not drop the adaptive hash index, because safely doing + so would require acquiring block->lock, and that is not safe + to acquire in some RW_NO_LATCH access paths. Those code paths + should have no business accessing the adaptive hash index anyway. */ + break; + case MTR_MEMO_PAGE_S_FIX: + /* Temporarily release our S-latch. */ + rw_lock_s_unlock(&block->lock); + rw_lock_x_lock(&block->lock); + if (dict_index_t *index= block->index) + if (index->freed()) + btr_search_drop_page_hash_index(block); + rw_lock_x_unlock(&block->lock); + rw_lock_s_lock(&block->lock); + break; + case MTR_MEMO_PAGE_SX_FIX: + rw_lock_sx_unlock(&block->lock); + rw_lock_x_lock(&block->lock); + if (dict_index_t *index= block->index) + if (index->freed()) + btr_search_drop_page_hash_index(block); + rw_lock_x_unlock(&block->lock); + rw_lock_sx_lock(&block->lock); + break; + default: + ut_ad(fix_type == MTR_MEMO_PAGE_X_FIX); + btr_search_drop_page_hash_index(block); + } +} +#endif /* BTR_CUR_HASH_ADAPT */ + /** Lock the page with the given latch type. @param[in,out] block block to be locked @param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH @@ -4163,7 +4203,7 @@ static buf_block_t* buf_page_mtr_lock(buf_block_t *block, { dict_index_t *index= block->index; if (index && index->freed()) - btr_search_drop_page_hash_index(block); + buf_defer_drop_ahi(block, fix_type); } #endif /* BTR_CUR_HASH_ADAPT */ From efc70da5fd0459ff44153529d13651741cc32bc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 5 Jun 2020 14:59:33 +0300 Subject: [PATCH 12/13] MDEV-22769 Shutdown hang or crash due to XA breaking locks The background drop table queue in InnoDB is a work-around for cases where the SQL layer is requesting DDL on tables on which transactional locks exist. One such case are XA transactions. Our test case exploits the fact that the recovery of XA PREPARE transactions will only resurrect InnoDB table locks, but not MDL that should block any concurrent DDL. srv_shutdown_t: Introduce the srv_shutdown_state=SRV_SHUTDOWN_INITIATED for the initial part of shutdown, to wait for the background drop table queue to be emptied. srv_shutdown_bg_undo_sources(): Assign srv_shutdown_state=SRV_SHUTDOWN_INITIATED before waiting for the background drop table queue to be emptied. row_drop_tables_for_mysql_in_background(): On slow shutdown, if no active transactions exist (excluding ones that are in XA PREPARE state), skip any tables on which locks exist. row_drop_table_for_mysql(): Do not unnecessarily attempt to drop InnoDB persistent statistics for tables that have already been added to the background drop table queue. row_mysql_close(): Relax an assertion, and free all memory even if innodb_force_recovery=2 would prevent the background drop table queue from being emptied. --- mysql-test/suite/innodb/r/xa_recovery.result | 10 +++ mysql-test/suite/innodb/t/xa_recovery.test | 13 +++- storage/innobase/buf/buf0flu.cc | 6 +- storage/innobase/fil/fil0crypt.cc | 1 + storage/innobase/fts/fts0opt.cc | 3 +- storage/innobase/ibuf/ibuf0ibuf.cc | 2 +- storage/innobase/include/srv0start.h | 2 + storage/innobase/log/log0log.cc | 8 +-- storage/innobase/os/os0file.cc | 4 +- storage/innobase/row/row0mysql.cc | 65 +++++++++++++------- storage/innobase/row/row0purge.cc | 4 +- storage/innobase/srv/srv0srv.cc | 25 ++++---- storage/innobase/srv/srv0start.cc | 1 + 13 files changed, 94 insertions(+), 50 deletions(-) diff --git a/mysql-test/suite/innodb/r/xa_recovery.result b/mysql-test/suite/innodb/r/xa_recovery.result index a93afcb07f8..a618154804c 100644 --- a/mysql-test/suite/innodb/r/xa_recovery.result +++ b/mysql-test/suite/innodb/r/xa_recovery.result @@ -5,11 +5,19 @@ XA START 'x'; UPDATE t1 set a=2; XA END 'x'; XA PREPARE 'x'; +connect con2,localhost,root; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +XA START 'y'; +INSERT INTO t2 VALUES (1); +XA END 'y'; +XA PREPARE 'y'; connection default; disconnect con1; +disconnect con2; connect con1,localhost,root; SELECT * FROM t1 LOCK IN SHARE MODE; connection default; +DROP TABLE t2; disconnect con1; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SELECT * FROM t1; @@ -20,3 +28,5 @@ SELECT * FROM t1; a 1 DROP TABLE t1; +SET GLOBAL innodb_fast_shutdown=0; +XA ROLLBACK 'y'; diff --git a/mysql-test/suite/innodb/t/xa_recovery.test b/mysql-test/suite/innodb/t/xa_recovery.test index 20bb52c22f2..bb8e3316860 100644 --- a/mysql-test/suite/innodb/t/xa_recovery.test +++ b/mysql-test/suite/innodb/t/xa_recovery.test @@ -5,7 +5,7 @@ # MDEV-8841 - close tables opened by previous tests, # so they don't get marked crashed when the server gets crashed --disable_query_log -call mtr.add_suppression("Found 1 prepared XA transactions"); +call mtr.add_suppression("Found [12] prepared XA transactions"); FLUSH TABLES; --enable_query_log @@ -13,6 +13,9 @@ CREATE TABLE t1 (a INT) ENGINE=InnoDB; INSERT INTO t1 VALUES (1); connect (con1,localhost,root); XA START 'x'; UPDATE t1 set a=2; XA END 'x'; XA PREPARE 'x'; +connect (con2,localhost,root); +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +XA START 'y'; INSERT INTO t2 VALUES (1); XA END 'y'; XA PREPARE 'y'; connection default; # innodb_force_recovery=2 prevents the purge and tests that the fix of @@ -25,6 +28,7 @@ connection default; --let $shutdown_timeout= disconnect con1; +disconnect con2; connect (con1,localhost,root); --send SELECT * FROM t1 LOCK IN SHARE MODE @@ -35,6 +39,8 @@ let $wait_condition= info = 'SELECT * FROM t1 LOCK IN SHARE MODE'; --source include/wait_condition.inc +DROP TABLE t2; + --source include/restart_mysqld.inc disconnect con1; @@ -45,3 +51,8 @@ XA ROLLBACK 'x'; SELECT * FROM t1; DROP TABLE t1; + +SET GLOBAL innodb_fast_shutdown=0; +--source include/restart_mysqld.inc + +XA ROLLBACK 'y'; diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index 7318d4f1eb6..77bbc530637 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -3150,7 +3150,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*) ulint last_activity = srv_get_activity_count(); ulint last_pages = 0; - while (srv_shutdown_state == SRV_SHUTDOWN_NONE) { + while (srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { ulint curr_time = ut_time_ms(); /* The page_cleaner skips sleep if the server is @@ -3168,7 +3168,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*) ret_sleep = 0; } - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { break; } @@ -3335,7 +3335,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*) ut_d(buf_flush_page_cleaner_disabled_loop()); } - ut_ad(srv_shutdown_state > 0); + ut_ad(srv_shutdown_state > SRV_SHUTDOWN_INITIATED); if (srv_fast_shutdown == 2 || srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { /* In very fast shutdown or when innodb failed to start, we diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc index 331516e868a..8243fa5801d 100644 --- a/storage/innobase/fil/fil0crypt.cc +++ b/storage/innobase/fil/fil0crypt.cc @@ -1076,6 +1076,7 @@ struct rotate_thread_t { case SRV_SHUTDOWN_EXIT_THREADS: /* srv_init_abort() must have been invoked */ case SRV_SHUTDOWN_CLEANUP: + case SRV_SHUTDOWN_INITIATED: return true; case SRV_SHUTDOWN_FLUSH_PHASE: case SRV_SHUTDOWN_LAST_PHASE: diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc index ae943577348..39720b07bd1 100644 --- a/storage/innobase/fts/fts0opt.cc +++ b/storage/innobase/fts/fts0opt.cc @@ -2790,8 +2790,7 @@ fts_optimize_thread( /* Assign number of tables added in fts_slots_t to n_tables */ n_tables = ib_vector_size(fts_slots); - while (!done && srv_shutdown_state == SRV_SHUTDOWN_NONE) { - + while (!done && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { /* If there is no message in the queue and we have tables to optimize then optimize the tables. */ diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index 1ee1624ca8b..2eea443a434 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -2614,7 +2614,7 @@ ibuf_merge( when a slow shutdown is being executed. During a slow shutdown, the insert buffer merge must be completed. */ - if (ibuf->empty && !srv_shutdown_state) { + if (ibuf->empty && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { return(0); #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG } else if (ibuf_debug) { diff --git a/storage/innobase/include/srv0start.h b/storage/innobase/include/srv0start.h index 8b39733335d..e559814b33d 100644 --- a/storage/innobase/include/srv0start.h +++ b/storage/innobase/include/srv0start.h @@ -113,6 +113,8 @@ extern ibool srv_start_raw_disk_in_use; /** Shutdown state */ enum srv_shutdown_t { SRV_SHUTDOWN_NONE = 0, /*!< Database running normally */ + /** Shutdown initiated in srv_shutdown_bg_undo_sources() */ + SRV_SHUTDOWN_INITIATED, SRV_SHUTDOWN_CLEANUP, /*!< Cleaning up in logs_empty_and_mark_files_at_shutdown() */ SRV_SHUTDOWN_FLUSH_PHASE,/*!< At this phase the master and the diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 9ad551f805d..ea657e49d07 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -1203,7 +1203,7 @@ loop: } } - if (UNIV_UNLIKELY(srv_shutdown_state != SRV_SHUTDOWN_NONE)) { + if (UNIV_UNLIKELY(srv_shutdown_state > SRV_SHUTDOWN_INITIATED)) { service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, "InnoDB log write: " LSN_PF "," LSN_PF, @@ -1430,7 +1430,7 @@ log_group_checkpoint(lsn_t end_lsn) ut_ad(end_lsn == 0 || end_lsn >= log_sys->next_checkpoint_lsn); ut_ad(end_lsn <= log_sys->lsn); ut_ad(end_lsn + SIZE_OF_MLOG_CHECKPOINT <= log_sys->lsn - || srv_shutdown_state != SRV_SHUTDOWN_NONE); + || srv_shutdown_state > SRV_SHUTDOWN_INITIATED); DBUG_PRINT("ib_log", ("checkpoint " UINT64PF " at " LSN_PF " written", @@ -1600,7 +1600,7 @@ bool log_checkpoint(bool sync) if (oldest_lsn > log_sys->last_checkpoint_lsn + SIZE_OF_MLOG_CHECKPOINT) { /* Some log has been written since the previous checkpoint. */ - } else if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + } else if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { /* MariaDB 10.3 startup expects the redo log file to be logically empty (not even containing a MLOG_CHECKPOINT record) after a clean shutdown. Perform an extra checkpoint at @@ -1625,7 +1625,7 @@ bool log_checkpoint(bool sync) lsn_t flush_lsn = oldest_lsn; const lsn_t end_lsn = log_sys->lsn; const bool do_write - = srv_shutdown_state == SRV_SHUTDOWN_NONE + = srv_shutdown_state <= SRV_SHUTDOWN_INITIATED || flush_lsn != end_lsn; if (fil_names_clear(flush_lsn, do_write)) { diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index e468b842ce2..56b42700be4 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -5435,7 +5435,7 @@ fallback: ? 0 : posix_fallocate(file, current_size, size - current_size); } while (err == EINTR - && srv_shutdown_state == SRV_SHUTDOWN_NONE); + && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED); switch (err) { case 0: @@ -5475,7 +5475,7 @@ fallback: os_offset_t current_size = os_file_get_size(file); while (current_size < size - && srv_shutdown_state == SRV_SHUTDOWN_NONE) { + && srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { ulint n_bytes; if (size - current_size < (os_offset_t) buf_size) { diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index d3efc5fc256..3989095d6c6 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -100,7 +100,7 @@ static UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list; static ib_mutex_t row_drop_list_mutex; /** Flag: has row_mysql_drop_list been initialized? */ -static ibool row_mysql_drop_list_inited = FALSE; +static bool row_mysql_drop_list_inited; /*******************************************************************//** Determine if the given name is a name reserved for MySQL system tables. @@ -2572,15 +2572,33 @@ next: ut_a(!table->can_be_evicted); + bool skip = false; + if (!table->to_be_dropped) { +skip: dict_table_close(table, FALSE, FALSE); mutex_enter(&row_drop_list_mutex); UT_LIST_REMOVE(row_mysql_drop_list, drop); - UT_LIST_ADD_LAST(row_mysql_drop_list, drop); + if (!skip) { + UT_LIST_ADD_LAST(row_mysql_drop_list, drop); + } else { + ut_free(drop); + } goto next; } + if (!srv_fast_shutdown && !trx_sys_any_active_transactions()) { + lock_mutex_enter(); + skip = UT_LIST_GET_LEN(table->locks) != 0; + lock_mutex_exit(); + if (skip) { + /* We cannot drop tables that are locked by XA + PREPARE transactions. */ + goto skip; + } + } + char* name = mem_strdup(table->name.m_name); dict_table_close(table, FALSE, FALSE); @@ -3390,15 +3408,15 @@ row_drop_table_for_mysql( btr_defragment_remove_table(table); } - /* Remove stats for this table and all of its indexes from the - persistent storage if it exists and if there are stats for this - table in there. This function creates its own trx and commits - it. */ - char errstr[1024]; - err = dict_stats_drop_table(name, errstr, sizeof(errstr)); - - if (err != DB_SUCCESS) { - ib::warn() << errstr; + if (UNIV_LIKELY(!strstr(name, "/" TEMP_FILE_PREFIX_INNODB))) { + /* Remove any persistent statistics for this table, + in a separate transaction. */ + char errstr[1024]; + err = dict_stats_drop_table(name, errstr, + sizeof errstr); + if (err != DB_SUCCESS) { + ib::warn() << errstr; + } } } @@ -4808,19 +4826,22 @@ row_mysql_init(void) row_mysql_drop_list, &row_mysql_drop_t::row_mysql_drop_list); - row_mysql_drop_list_inited = TRUE; + row_mysql_drop_list_inited = true; } -/*********************************************************************//** -Close this module */ -void -row_mysql_close(void) -/*================*/ +void row_mysql_close() { - ut_a(UT_LIST_GET_LEN(row_mysql_drop_list) == 0); + ut_ad(!UT_LIST_GET_LEN(row_mysql_drop_list) || + srv_force_recovery >= SRV_FORCE_NO_BACKGROUND); + if (row_mysql_drop_list_inited) + { + row_mysql_drop_list_inited= false; + mutex_free(&row_drop_list_mutex); - if (row_mysql_drop_list_inited) { - mutex_free(&row_drop_list_mutex); - row_mysql_drop_list_inited = FALSE; - } + while (row_mysql_drop_t *drop= UT_LIST_GET_FIRST(row_mysql_drop_list)) + { + UT_LIST_REMOVE(row_mysql_drop_list, drop); + ut_free(drop); + } + } } diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index f4fd617f154..e79784a5a5f 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -1004,7 +1004,7 @@ try_again: dict_table_close(node->table, FALSE, FALSE); rw_lock_s_unlock(&dict_operation_lock); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return(false); } os_thread_sleep(1000000); @@ -1167,7 +1167,7 @@ row_purge( ut_ad(!rw_lock_own(&dict_operation_lock, RW_LOCK_S)); if (purged - || srv_shutdown_state != SRV_SHUTDOWN_NONE + || srv_shutdown_state > SRV_SHUTDOWN_INITIATED || node->vcol_op_failed()) { return; } diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 19d4c7fb7d7..cc85416aac7 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1802,7 +1802,7 @@ loop: srv_refresh_innodb_monitor_stats(); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { goto exit_func; } @@ -1914,7 +1914,7 @@ loop: os_event_wait_time_low(srv_error_event, 1000000, sig_count); - if (srv_shutdown_state == SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { goto loop; } @@ -1964,7 +1964,7 @@ srv_get_active_thread_type(void) srv_sys_mutex_exit(); - if (ret == SRV_NONE && srv_shutdown_state != SRV_SHUTDOWN_NONE + if (ret == SRV_NONE && srv_shutdown_state > SRV_SHUTDOWN_INITIATED && purge_sys != NULL) { /* Check only on shutdown. */ switch (trx_purge_state()) { @@ -2219,7 +2219,7 @@ srv_master_do_active_tasks(void) ut_d(srv_master_do_disabled_loop()); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -2244,7 +2244,7 @@ srv_master_do_active_tasks(void) /* Now see if various tasks that are performed at defined intervals need to be performed. */ - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -2269,7 +2269,7 @@ srv_master_do_active_tasks(void) early and often to avoid those situations. */ DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", return;); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -2312,7 +2312,7 @@ srv_master_do_idle_tasks(void) ut_d(srv_master_do_disabled_loop()); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -2328,7 +2328,7 @@ srv_master_do_idle_tasks(void) MONITOR_INC_TIME_IN_MICRO_SECS( MONITOR_SRV_IBUF_MERGE_MICROSECOND, counter_time); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -2356,7 +2356,7 @@ srv_master_do_idle_tasks(void) early and often to avoid those situations. */ DBUG_EXECUTE_IF("ib_log_checkpoint_avoid", return;); - if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + if (srv_shutdown_state > SRV_SHUTDOWN_INITIATED) { return; } @@ -2454,8 +2454,7 @@ DECLARE_THREAD(srv_master_thread)( ut_a(slot == srv_sys.sys_threads); loop: - while (srv_shutdown_state == SRV_SHUTDOWN_NONE) { - + while (srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) { srv_master_sleep(); MONITOR_INC(MONITOR_MASTER_THREAD_SLEEP); @@ -2470,6 +2469,7 @@ loop: switch (srv_shutdown_state) { case SRV_SHUTDOWN_NONE: + case SRV_SHUTDOWN_INITIATED: break; case SRV_SHUTDOWN_FLUSH_PHASE: case SRV_SHUTDOWN_LAST_PHASE: @@ -2508,8 +2508,7 @@ static bool srv_purge_should_exit(ulint n_purged) { - ut_ad(srv_shutdown_state == SRV_SHUTDOWN_NONE - || srv_shutdown_state == SRV_SHUTDOWN_CLEANUP); + ut_ad(srv_shutdown_state <= SRV_SHUTDOWN_CLEANUP); if (srv_undo_sources) { return(false); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index d6ad7bf437a..8efae318ee0 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2757,6 +2757,7 @@ srv_shutdown_bg_undo_sources() { if (srv_undo_sources) { ut_ad(!srv_read_only_mode); + srv_shutdown_state = SRV_SHUTDOWN_INITIATED; fts_optimize_shutdown(); dict_stats_shutdown(); while (row_get_background_drop_list_len_low()) { From 286e52e948eee9e5f908c5944467149df35d25e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 5 Jun 2020 17:45:27 +0300 Subject: [PATCH 13/13] After-merge fix: GCC -Wmaybe-uninitialized --- storage/innobase/page/page0page.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc index c9a51ed7bce..ba2e08df2d2 100644 --- a/storage/innobase/page/page0page.cc +++ b/storage/innobase/page/page0page.cc @@ -2,7 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2017, 2019, MariaDB Corporation. +Copyright (c) 2017, 2020, 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 @@ -2409,7 +2409,7 @@ bool page_validate(const page_t* page, const dict_index_t* index) const rec_t* rec; const rec_t* old_rec = NULL; const rec_t* first_rec = NULL; - ulint offs; + ulint offs = 0; ulint n_slots; ibool ret = TRUE; ulint i;