diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-05-29 16:36:16 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-05-29 16:52:12 +0300 |
commit | 18934fb58309f4491b34273b2781cce68f6d6e22 (patch) | |
tree | e9e43e81979561fd5aec9d17dddd5cb6ea02e93f /storage/innobase | |
parent | 8a42ad7a5d3168b7ce92a38652d77424336a32b8 (diff) | |
parent | 6aa50bad3947a0eab24fb029cd58f5945439e365 (diff) | |
download | mariadb-git-18934fb58309f4491b34273b2781cce68f6d6e22.tar.gz |
Merge 10.1 into 10.2
Diffstat (limited to 'storage/innobase')
-rw-r--r-- | storage/innobase/btr/btr0sea.cc | 20 | ||||
-rw-r--r-- | storage/innobase/buf/buf0buf.cc | 5 | ||||
-rw-r--r-- | storage/innobase/buf/buf0lru.cc | 70 | ||||
-rw-r--r-- | storage/innobase/dict/dict0dict.cc | 27 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 12 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0fsp.cc | 5 | ||||
-rw-r--r-- | storage/innobase/include/btr0sea.h | 14 | ||||
-rw-r--r-- | storage/innobase/include/buf0lru.h | 18 | ||||
-rw-r--r-- | storage/innobase/row/row0import.cc | 12 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 14 |
10 files changed, 90 insertions, 107 deletions
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc index 750c2506ff5..278062afa78 100644 --- a/storage/innobase/btr/btr0sea.cc +++ b/storage/innobase/btr/btr0sea.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1177,7 +1177,8 @@ retry: #endif ut_ad(btr_search_enabled); - ut_ad(block->page.id.space() == index->space); + ut_ad(index->space == FIL_NULL + || block->page.id.space() == index->space); ut_a(index_id == index->id); ut_a(!dict_index_is_ibuf(index)); #ifdef UNIV_DEBUG @@ -1300,15 +1301,10 @@ cleanup: ut_free(folds); } -/** Drop any adaptive hash index entries that may point to an index -page that may be in the buffer pool, when a page is evicted from the -buffer pool or freed in a file segment. -@param[in] page_id page id -@param[in] page_size page size */ -void -btr_search_drop_page_hash_when_freed( - const page_id_t& page_id, - const page_size_t& page_size) +/** Drop possible adaptive hash index entries when a page is evicted +from the buffer pool or freed in a file, or the index is being dropped. +@param[in] page_id page id */ +void btr_search_drop_page_hash_when_freed(const page_id_t& page_id) { buf_block_t* block; mtr_t mtr; @@ -1324,7 +1320,7 @@ btr_search_drop_page_hash_when_freed( are possibly holding, we cannot s-latch the page, but must (recursively) x-latch it, even though we are only reading. */ - block = buf_page_get_gen(page_id, page_size, RW_X_LATCH, NULL, + block = buf_page_get_gen(page_id, univ_page_size, RW_X_LATCH, NULL, BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__, &mtr, &err); diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 2f385b6f8e6..845bb17bfa5 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -4203,10 +4203,12 @@ buf_page_get_gen( #ifdef UNIV_DEBUG switch (mode) { case BUF_EVICT_IF_IN_POOL: + case BUF_PEEK_IF_IN_POOL: /* After DISCARD TABLESPACE, the tablespace would not exist, but in IMPORT TABLESPACE, PageConverter::operator() must replace any old pages, which were not evicted during DISCARD. - Skip the assertion on space_page_size. */ + Similarly, btr_search_drop_page_hash_when_freed() must + remove any old pages. Skip the assertion on page_size. */ break; default: ut_error; @@ -4215,7 +4217,6 @@ buf_page_get_gen( /* fall through */ case BUF_GET: case BUF_GET_IF_IN_POOL: - case BUF_PEEK_IF_IN_POOL: case BUF_GET_IF_IN_POOL_OR_WATCH: case BUF_GET_POSSIBLY_FREED: bool found; diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index cdea41ff191..60970331b25 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -224,30 +224,21 @@ buf_LRU_evict_from_unzip_LRU( /** Attempts to drop page hash index on a batch of pages belonging to a particular space id. @param[in] space_id space id -@param[in] page_size page size @param[in] arr array of page_no @param[in] count number of entries in array */ static void -buf_LRU_drop_page_hash_batch( - ulint space_id, - const page_size_t& page_size, - const ulint* arr, - ulint count) +buf_LRU_drop_page_hash_batch(ulint space_id, const ulint* arr, ulint count) { ut_ad(count <= BUF_LRU_DROP_SEARCH_SIZE); - for (ulint i = 0; i < count; ++i, ++arr) { + for (const ulint* const end = arr + count; arr != end; ) { /* While our only caller buf_LRU_drop_page_hash_for_tablespace() is being executed for DROP TABLE or similar, - the table cannot be evicted from the buffer pool. - Note: this should not be executed for DROP TABLESPACE, - because DROP TABLESPACE would be refused if tables existed - in the tablespace, and a previous DROP TABLE would have - already removed the AHI entries. */ + the table cannot be evicted from the buffer pool. */ btr_search_drop_page_hash_when_freed( - page_id_t(space_id, *arr), page_size); + page_id_t(space_id, *arr++)); } } @@ -263,15 +254,6 @@ buf_LRU_drop_page_hash_for_tablespace( buf_pool_t* buf_pool, /*!< in: buffer pool instance */ ulint id) /*!< in: space id */ { - bool found; - const page_size_t page_size(fil_space_get_page_size(id, &found)); - - if (!found) { - /* Somehow, the tablespace does not exist. Nothing to drop. */ - ut_ad(0); - return; - } - ulint* page_arr = static_cast<ulint*>(ut_malloc_nokey( sizeof(ulint) * BUF_LRU_DROP_SEARCH_SIZE)); @@ -338,8 +320,7 @@ next_page: the latching order. */ buf_pool_mutex_exit(buf_pool); - buf_LRU_drop_page_hash_batch( - id, page_size, page_arr, num_entries); + buf_LRU_drop_page_hash_batch(id, page_arr, num_entries); num_entries = 0; @@ -371,9 +352,31 @@ next_page: buf_pool_mutex_exit(buf_pool); /* Drop any remaining batch of search hashed pages. */ - buf_LRU_drop_page_hash_batch(id, page_size, page_arr, num_entries); + buf_LRU_drop_page_hash_batch(id, page_arr, num_entries); ut_free(page_arr); } + +/** Drop the adaptive hash index for a tablespace. +@param[in,out] table table */ +void buf_LRU_drop_page_hash_for_tablespace(dict_table_t* table) +{ + for (dict_index_t* index = dict_table_get_first_index(table); + index != NULL; + index = dict_table_get_next_index(index)) { + if (btr_search_info_get_ref_count(btr_search_get_info(index), + index)) { + goto drop_ahi; + } + } + + return; +drop_ahi: + ulint id = table->space; + for (ulint i = 0; i < srv_buf_pool_instances; i++) { + buf_LRU_drop_page_hash_for_tablespace(buf_pool_from_array(i), + id); + } +} #endif /* BTR_CUR_HASH_ADAPT */ /******************************************************************//** @@ -697,26 +700,13 @@ buf_flush_dirty_pages( @param[in] id tablespace identifier @param[in] observer flush observer, or NULL if nothing is to be written */ -void -buf_LRU_flush_or_remove_pages( - ulint id, - FlushObserver* observer -#ifdef BTR_CUR_HASH_ADAPT - , bool drop_ahi /*!< whether to drop the adaptive hash index */ -#endif /* BTR_CUR_HASH_ADAPT */ - ) +void buf_LRU_flush_or_remove_pages(ulint id, FlushObserver* observer) { /* Pages in the system tablespace must never be discarded. */ ut_ad(id || observer); for (ulint i = 0; i < srv_buf_pool_instances; i++) { - buf_pool_t* buf_pool = buf_pool_from_array(i); -#ifdef BTR_CUR_HASH_ADAPT - if (drop_ahi) { - buf_LRU_drop_page_hash_for_tablespace(buf_pool, id); - } -#endif /* BTR_CUR_HASH_ADAPT */ - buf_flush_dirty_pages(buf_pool, id, observer); + buf_flush_dirty_pages(buf_pool_from_array(i), id, observer); } if (observer && !observer->is_interrupted()) { diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 4751add93d5..9a7d9eef092 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1649,11 +1649,7 @@ dict_table_rename_in_cache( return(DB_OUT_OF_MEMORY); } - fil_delete_tablespace(table->space -#ifdef BTR_CUR_HASH_ADAPT - , true -#endif /* BTR_CUR_HASH_ADAPT */ - ); + fil_delete_tablespace(table->space); /* Delete any temp file hanging around. */ if (os_file_status(filepath, &exists, &ftype) @@ -2657,28 +2653,13 @@ dict_index_remove_from_cache_low( zero. See also: dict_table_can_be_evicted() */ do { - ulint ref_count = btr_search_info_get_ref_count(info, index); - - if (ref_count == 0) { + if (!btr_search_info_get_ref_count(info, index)) { break; } - /* Sleep for 10ms before trying again. */ - os_thread_sleep(10000); - ++retries; - - if (retries % 500 == 0) { - /* No luck after 5 seconds of wait. */ - ib::error() << "Waited for " << retries / 100 - << " secs for hash index" - " ref_count (" << ref_count << ") to drop to 0." - " index: " << index->name - << " table: " << table->name; - } + buf_LRU_drop_page_hash_for_tablespace(table); - /* To avoid a hang here we commit suicide if the - ref_count doesn't drop to zero in 600 seconds. */ - ut_a(retries < 60000); + ut_a(++retries < 10000); } while (srv_shutdown_state == SRV_SHUTDOWN_NONE || !lru_evict); #endif /* BTR_CUR_HASH_ADAPT */ diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 240a453ff5d..c889e8f688e 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -3030,11 +3030,7 @@ fil_delete_tablespace( To deal with potential read requests, we will check the ::stop_new_ops flag in fil_io(). */ - buf_LRU_flush_or_remove_pages(id, NULL -#ifdef BTR_CUR_HASH_ADAPT - , drop_ahi -#endif /* BTR_CUR_HASH_ADAPT */ - ); + buf_LRU_flush_or_remove_pages(id, NULL); /* If it is a delete then also delete any generated files, otherwise when we drop the database the remove directory will fail. */ @@ -3314,11 +3310,7 @@ fil_discard_tablespace( { dberr_t err; - switch (err = fil_delete_tablespace(id -#ifdef BTR_CUR_HASH_ADAPT - , true -#endif /* BTR_CUR_HASH_ADAPT */ - )) { + switch (err = fil_delete_tablespace(id)) { case DB_SUCCESS: break; diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 50d5fc84384..d4d5abeb32f 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -3057,7 +3057,7 @@ fseg_free_page_low( if (ahi) { btr_search_drop_page_hash_when_freed( - page_id_t(space->id, offset), page_size); + page_id_t(space->id, offset)); } #endif /* BTR_CUR_HASH_ADAPT */ @@ -3261,8 +3261,7 @@ fseg_free_extent( btr_search_drop_page_hash_when_freed( page_id_t(space->id, - first_page_in_extent + i), - page_size); + first_page_in_extent + i)); } } } diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h index fad0dac93c4..e6983cacffb 100644 --- a/storage/innobase/include/btr0sea.h +++ b/storage/innobase/include/btr0sea.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, 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 @@ -129,15 +130,10 @@ btr_search_move_or_delete_hash_entries( void btr_search_drop_page_hash_index(buf_block_t* block); -/** Drop any adaptive hash index entries that may point to an index -page that may be in the buffer pool, when a page is evicted from the -buffer pool or freed in a file segment. -@param[in] page_id page id -@param[in] page_size page size */ -void -btr_search_drop_page_hash_when_freed( - const page_id_t& page_id, - const page_size_t& page_size); +/** Drop possible adaptive hash index entries when a page is evicted +from the buffer pool or freed in a file, or the index is being dropped. +@param[in] page_id page id */ +void btr_search_drop_page_hash_when_freed(const page_id_t& page_id); /** Updates the page hash index when a single record is inserted on a page. @param[in] cursor cursor which was positioned to the place to insert diff --git a/storage/innobase/include/buf0lru.h b/storage/innobase/include/buf0lru.h index f6a7695a2b5..7ef62e6436d 100644 --- a/storage/innobase/include/buf0lru.h +++ b/storage/innobase/include/buf0lru.h @@ -50,18 +50,20 @@ These are low-level functions /** Minimum LRU list length for which the LRU_old pointer is defined */ #define BUF_LRU_OLD_MIN_LEN 512 /* 8 megabytes of 16k pages */ +#ifdef BTR_CUR_HASH_ADAPT +struct dict_table_t; +/** Drop the adaptive hash index for a tablespace. +@param[in,out] table table */ +void buf_LRU_drop_page_hash_for_tablespace(dict_table_t* table); +#else +# define buf_LRU_drop_page_hash_for_tablespace(table) +#endif /* BTR_CUR_HASH_ADAPT */ + /** Empty the flush list for all pages belonging to a tablespace. @param[in] id tablespace identifier @param[in,out] observer flush observer, or NULL if nothing is to be written */ -void -buf_LRU_flush_or_remove_pages( - ulint id, - FlushObserver* observer -#ifdef BTR_CUR_HASH_ADAPT - , bool drop_ahi = false /*!< whether to drop the adaptive hash index */ -#endif /* BTR_CUR_HASH_ADAPT */ - ); +void buf_LRU_flush_or_remove_pages(ulint id, FlushObserver* observer); #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG /********************************************************************//** diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 0d6f2461c5e..07bd07db864 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -28,6 +28,7 @@ Created 2012-02-08 by Sunny Bains. #include "row0import.h" #include "btr0pcur.h" +#include "btr0sea.h" #include "que0que.h" #include "dict0boot.h" #include "ibuf0ibuf.h" @@ -3883,6 +3884,17 @@ row_import_for_mysql( return(row_import_cleanup(prebuilt, trx, err)); } + /* On DISCARD TABLESPACE, we did not drop any adaptive hash + index entries. If we replaced the discarded tablespace with a + smaller one here, there could still be some adaptive hash + index entries that point to cached garbage pages in the buffer + pool, because PageConverter::operator() only evicted those + pages that were replaced by the imported pages. We must + discard all remaining adaptive hash index entries, because the + adaptive hash index must be a subset of the table contents; + false positives are not tolerated. */ + buf_LRU_drop_page_hash_for_tablespace(table); + row_mysql_lock_data_dictionary(trx); /* If the table is stored in a remote tablespace, we need to diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 80097130cb7..a06fa1ddf47 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -3626,6 +3626,20 @@ row_drop_table_for_mysql( /* As we don't insert entries to SYSTEM TABLES for temp-tables we need to avoid running removal of these entries. */ if (!dict_table_is_temporary(table)) { + if (table->space != TRX_SYS_SPACE) { + /* On DISCARD TABLESPACE, we would not drop the + adaptive hash index entries. If the tablespace is + missing here, delete-marking the record in SYS_INDEXES + would not free any pages in the buffer pool. Thus, + dict_index_remove_from_cache() would hang due to + adaptive hash index entries existing in the buffer + pool. To prevent this hang, and also to guarantee + that btr_search_drop_page_hash_when_freed() will avoid + calling btr_search_drop_page_hash_index() while we + hold the InnoDB dictionary lock, we will drop any + adaptive hash index entries upfront. */ + buf_LRU_drop_page_hash_for_tablespace(table); + } /* We use the private SQL parser of Innobase to generate the query graphs needed in deleting the dictionary data from system |