summaryrefslogtreecommitdiff
path: root/storage/innobase
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-05-29 16:36:16 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-05-29 16:52:12 +0300
commit18934fb58309f4491b34273b2781cce68f6d6e22 (patch)
treee9e43e81979561fd5aec9d17dddd5cb6ea02e93f /storage/innobase
parent8a42ad7a5d3168b7ce92a38652d77424336a32b8 (diff)
parent6aa50bad3947a0eab24fb029cd58f5945439e365 (diff)
downloadmariadb-git-18934fb58309f4491b34273b2781cce68f6d6e22.tar.gz
Merge 10.1 into 10.2
Diffstat (limited to 'storage/innobase')
-rw-r--r--storage/innobase/btr/btr0sea.cc20
-rw-r--r--storage/innobase/buf/buf0buf.cc5
-rw-r--r--storage/innobase/buf/buf0lru.cc70
-rw-r--r--storage/innobase/dict/dict0dict.cc27
-rw-r--r--storage/innobase/fil/fil0fil.cc12
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc5
-rw-r--r--storage/innobase/include/btr0sea.h14
-rw-r--r--storage/innobase/include/buf0lru.h18
-rw-r--r--storage/innobase/row/row0import.cc12
-rw-r--r--storage/innobase/row/row0mysql.cc14
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