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.
parent ca3aa679
......@@ -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);
}
}
......
This diff is collapsed.
......@@ -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 @@ buf_pool_resize()
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 @@ buf_pool_resize()
#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 */
......
......@@ -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();
......
......@@ -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);
}
......
......@@ -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 */
void
btr_search_disable(
bool need_mutex);
/** Enable the adaptive hash search system. */
/** 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_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
......
......@@ -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",
......
......@@ -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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment