diff options
author | Marko Mäkelä <marko.makela@oracle.com> | 2016-09-02 17:28:54 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-04-26 23:03:27 +0300 |
commit | e63ead68bf4ef14f836181c834aa010d471abe9c (patch) | |
tree | c056b2143146e6af508097a29c1fe32790c1f4d0 /storage/innobase/ha | |
parent | a6adf567fd64b5566948ca029f68c613b6b703cc (diff) | |
download | mariadb-git-e63ead68bf4ef14f836181c834aa010d471abe9c.tar.gz |
Bug#24346574 PAGE CLEANER THREAD, ASSERT BLOCK->N_POINTERS == 0
btr_search_drop_page_hash_index(): Do not return before ensuring
that block->index=NULL, even if !btr_search_enabled. We would
typically still skip acquiring the AHI latch when the AHI is
disabled, because block->index would already be NULL. Only if the AHI
is in the process of being disabled, we would wait for the AHI latch
and then notice that block->index=NULL and return.
The above bug was a regression caused in MySQL 5.7.9 by the fix of
Bug#21407023: DISABLING AHI SHOULD AVOID TAKING AHI LATCH
The rest of this patch improves diagnostics by adding assertions.
assert_block_ahi_valid(): A debug predicate for checking that
block->n_pointers!=0 implies block->index!=NULL.
assert_block_ahi_empty(): A debug predicate for checking that
block->n_pointers==0.
buf_block_init(): Instead of assigning block->n_pointers=0,
assert_block_ahi_empty(block).
buf_pool_clear_hash_index(): Clarify comments, and assign
block->n_pointers=0 before assigning block->index=NULL.
The wrong ordering could make block->n_pointers appear incorrect in
debug assertions. This bug was introduced in MySQL 5.1.52 by
Bug#13006367 62487: INNODB TAKES 3 MINUTES TO CLEAN UP THE
ADAPTIVE HASH INDEX AT SHUTDOWN
i_s_innodb_buffer_page_get_info(): Add a comment that
the IS_HASHED column in the INFORMATION_SCHEMA views
INNODB_BUFFER_POOL_PAGE and INNODB_BUFFER_PAGE_LRU may
show false positives (there may be no pointers after all.)
ha_insert_for_fold_func(), ha_delete_hash_node(),
ha_search_and_update_if_found_func(): Use atomics for
updating buf_block_t::n_pointers. While buf_block_t::index is
always protected by btr_search_x_lock(index), in
ha_insert_for_fold_func() the n_pointers-- may belong to
another dict_index_t whose btr_search_latches[] we are not holding.
RB: 13879
Reviewed-by: Jimmy Yang <jimmy.yang@oracle.com>
Diffstat (limited to 'storage/innobase/ha')
-rw-r--r-- | storage/innobase/ha/ha0ha.cc | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/storage/innobase/ha/ha0ha.cc b/storage/innobase/ha/ha0ha.cc index 5822bd6755c..f620db6f62e 100644 --- a/storage/innobase/ha/ha0ha.cc +++ b/storage/innobase/ha/ha0ha.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 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 @@ -189,6 +190,12 @@ ha_clear( } #ifdef BTR_CUR_HASH_ADAPT +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG +/** Maximum number of records in a page */ +static const lint MAX_N_POINTERS + = UNIV_PAGE_SIZE_MAX / REC_N_NEW_EXTRA_BYTES; +# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ + /*************************************************************//** Inserts an entry into a hash table. If an entry with the same fold number is found, its node is updated to point to the new data, and no new node @@ -235,9 +242,11 @@ ha_insert_for_fold_func( buf_block_t* prev_block = prev_node->block; ut_a(prev_block->frame == page_align(prev_node->data)); - ut_a(prev_block->n_pointers > 0); - prev_block->n_pointers--; - block->n_pointers++; + ut_a(my_atomic_addlint( + &prev_block->n_pointers, -1) + < MAX_N_POINTERS); + ut_a(my_atomic_addlint(&block->n_pointers, 1) + < MAX_N_POINTERS); } prev_node->block = block; @@ -268,7 +277,8 @@ ha_insert_for_fold_func( #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG if (table->adaptive) { - block->n_pointers++; + ut_a(my_atomic_addlint(&block->n_pointers, 1) + < MAX_N_POINTERS); } #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ @@ -329,8 +339,8 @@ ha_delete_hash_node( #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG if (table->adaptive) { ut_a(del_node->block->frame = page_align(del_node->data)); - ut_a(del_node->block->n_pointers > 0); - del_node->block->n_pointers--; + ut_a(my_atomic_addlint(&del_node->block->n_pointers, -1) + < MAX_N_POINTERS); } #endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ @@ -372,9 +382,10 @@ ha_search_and_update_if_found_func( if (node) { #if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG if (table->adaptive) { - ut_a(node->block->n_pointers > 0); - node->block->n_pointers--; - new_block->n_pointers++; + ut_a(my_atomic_addlint(&node->block->n_pointers, -1) + < MAX_N_POINTERS); + ut_a(my_atomic_addlint(&new_block->n_pointers, 1) + < MAX_N_POINTERS); } node->block = new_block; |