summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-11-06 13:14:31 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-11-06 13:14:31 +0200
commit908ca4668d5cb415f4737c8617ffb84f2c15855d (patch)
tree97b0b5322c3833d5d66e6a8b0c6de195aca18320 /storage
parent5d3bd2b75b5bf32e69a9b32333cbf8dffe7a2541 (diff)
parent90451a59811b415a443aab97230e694856392cb5 (diff)
downloadmariadb-git-908ca4668d5cb415f4737c8617ffb84f2c15855d.tar.gz
Merge 10.2 into 10.3
Diffstat (limited to 'storage')
-rw-r--r--storage/heap/_check.c27
-rw-r--r--storage/innobase/dict/dict0boot.cc23
-rw-r--r--storage/innobase/dict/dict0crea.cc4
-rw-r--r--storage/innobase/dict/dict0dict.cc34
-rw-r--r--storage/innobase/dict/dict0load.cc7
-rw-r--r--storage/innobase/handler/handler0alter.cc5
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc82
-rw-r--r--storage/innobase/include/dict0dict.h17
-rw-r--r--storage/innobase/row/row0mysql.cc8
9 files changed, 132 insertions, 75 deletions
diff --git a/storage/heap/_check.c b/storage/heap/_check.c
index 883e67046e7..1a640fa13da 100644
--- a/storage/heap/_check.c
+++ b/storage/heap/_check.c
@@ -18,10 +18,8 @@
#include "heapdef.h"
-static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
- ulong blength, my_bool print_status);
-static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
- my_bool print_status);
+static int check_one_key(HP_KEYDEF *, uint, ulong, ulong, my_bool);
+static int check_one_rb_key(const HP_INFO *, uint, ulong, my_bool);
/*
@@ -40,13 +38,13 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
1 error
*/
-int heap_check_heap(HP_INFO *info, my_bool print_status)
+int heap_check_heap(const HP_INFO *info, my_bool print_status)
{
int error;
uint key;
ulong records=0, deleted=0, pos, next_block;
HP_SHARE *share=info->s;
- HP_INFO save_info= *info; /* Needed because scan_init */
+ uchar *current_ptr= info->current_ptr;
DBUG_ENTER("heap_check_heap");
for (error=key= 0 ; key < share->keys ; key++)
@@ -65,7 +63,7 @@ int heap_check_heap(HP_INFO *info, my_bool print_status)
{
if (pos < next_block)
{
- info->current_ptr+= share->block.recbuffer;
+ current_ptr+= share->block.recbuffer;
}
else
{
@@ -77,9 +75,9 @@ int heap_check_heap(HP_INFO *info, my_bool print_status)
break; /* End of file */
}
}
- hp_find_record(info,pos);
+ current_ptr= hp_find_block(&share->block, pos);
- if (!info->current_ptr[share->visible])
+ if (!current_ptr[share->visible])
deleted++;
else
records++;
@@ -92,7 +90,6 @@ int heap_check_heap(HP_INFO *info, my_bool print_status)
deleted, (ulong) share->deleted));
error= 1;
}
- *info= save_info;
DBUG_RETURN(error);
}
@@ -165,7 +162,7 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
return error;
}
-static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
+static int check_one_rb_key(const HP_INFO *info, uint keynr, ulong records,
my_bool print_status)
{
HP_KEYDEF *keydef= info->s->keydef + keynr;
@@ -174,9 +171,11 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
uchar *key, *recpos;
uint key_length;
uint not_used[2];
+ TREE_ELEMENT **last_pos;
+ TREE_ELEMENT *parents[MAX_TREE_HEIGHT+1];
- if ((key= tree_search_edge(&keydef->rb_tree, info->parents,
- &info->last_pos, offsetof(TREE_ELEMENT, left))))
+ if ((key= tree_search_edge(&keydef->rb_tree, parents,
+ &last_pos, offsetof(TREE_ELEMENT, left))))
{
do
{
@@ -191,7 +190,7 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
}
else
found++;
- key= tree_search_next(&keydef->rb_tree, &info->last_pos,
+ key= tree_search_next(&keydef->rb_tree, &last_pos,
offsetof(TREE_ELEMENT, left),
offsetof(TREE_ELEMENT, right));
} while (key);
diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc
index 2104aff83cd..f62bed52990 100644
--- a/storage/innobase/dict/dict0boot.cc
+++ b/storage/innobase/dict/dict0boot.cc
@@ -127,8 +127,7 @@ dict_hdr_get_new_id(
}
if (space_id) {
- *space_id = mtr_read_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID,
- MLOG_4BYTES, &mtr);
+ *space_id = mach_read_from_4(dict_hdr + DICT_HDR_MAX_SPACE_ID);
if (fil_assign_new_space_id(space_id)) {
mlog_write_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID,
*space_id, MLOG_4BYTES, &mtr);
@@ -361,9 +360,9 @@ dict_boot(void)
dict_mem_index_add_field(index, "NAME", 0);
index->id = DICT_TABLES_ID;
- index = dict_index_add_to_cache(
+ dberr_t error = dict_index_add_to_cache(
index, mach_read_from_4(dict_hdr + DICT_HDR_TABLES));
- ut_a(index);
+ ut_a(error == DB_SUCCESS);
ut_ad(!table->is_instant());
table->indexes.start->n_core_null_bytes = UT_BITS_IN_BYTES(
unsigned(table->indexes.start->n_nullable));
@@ -373,9 +372,9 @@ dict_boot(void)
dict_mem_index_add_field(index, "ID", 0);
index->id = DICT_TABLE_IDS_ID;
- index = dict_index_add_to_cache(
+ error = dict_index_add_to_cache(
index, mach_read_from_4(dict_hdr + DICT_HDR_TABLE_IDS));
- ut_a(index);
+ ut_a(error == DB_SUCCESS);
/*-------------------------*/
table = dict_mem_table_create("SYS_COLUMNS", fil_system.sys_space,
@@ -403,9 +402,9 @@ dict_boot(void)
dict_mem_index_add_field(index, "POS", 0);
index->id = DICT_COLUMNS_ID;
- index = dict_index_add_to_cache(
+ error = dict_index_add_to_cache(
index, mach_read_from_4(dict_hdr + DICT_HDR_COLUMNS));
- ut_a(index);
+ ut_a(error == DB_SUCCESS);
ut_ad(!table->is_instant());
table->indexes.start->n_core_null_bytes = UT_BITS_IN_BYTES(
unsigned(table->indexes.start->n_nullable));
@@ -446,9 +445,9 @@ dict_boot(void)
dict_mem_index_add_field(index, "ID", 0);
index->id = DICT_INDEXES_ID;
- index = dict_index_add_to_cache(
+ error = dict_index_add_to_cache(
index, mach_read_from_4(dict_hdr + DICT_HDR_INDEXES));
- ut_a(index);
+ ut_a(error == DB_SUCCESS);
ut_ad(!table->is_instant());
table->indexes.start->n_core_null_bytes = UT_BITS_IN_BYTES(
unsigned(table->indexes.start->n_nullable));
@@ -475,9 +474,9 @@ dict_boot(void)
dict_mem_index_add_field(index, "POS", 0);
index->id = DICT_FIELDS_ID;
- index = dict_index_add_to_cache(
+ error = dict_index_add_to_cache(
index, mach_read_from_4(dict_hdr + DICT_HDR_FIELDS));
- ut_a(index);
+ ut_a(error == DB_SUCCESS);
ut_ad(!table->is_instant());
table->indexes.start->n_core_null_bytes = UT_BITS_IN_BYTES(
unsigned(table->indexes.start->n_nullable));
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index b5f7a389f4d..d424446ba87 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -1350,9 +1350,9 @@ dict_create_index_step(
if (node->state == INDEX_ADD_TO_CACHE) {
ut_ad(node->index->table == node->table);
- node->index = dict_index_add_to_cache(
+ err = dict_index_add_to_cache(
node->index, FIL_NULL, trx_is_strict(trx),
- &err, node->add_v);
+ node->add_v);
ut_ad((node->index == NULL) == (err != DB_SUCCESS));
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index c84356f40c8..17d2c6c68eb 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -1765,8 +1765,7 @@ dict_table_rename_in_cache(
/* The old table name in my_charset_filename is stored
in old_name_cs_filename */
- strncpy(old_name_cs_filename, old_name,
- MAX_FULL_NAME_LEN);
+ strcpy(old_name_cs_filename, old_name);
old_name_cs_filename[MAX_FULL_NAME_LEN] = '\0';
if (strstr(old_name, TEMP_TABLE_PATH_PREFIX) == NULL) {
@@ -1788,8 +1787,7 @@ dict_table_rename_in_cache(
} else {
/* Old name already in
my_charset_filename */
- strncpy(old_name_cs_filename, old_name,
- MAX_FULL_NAME_LEN);
+ strcpy(old_name_cs_filename, old_name);
old_name_cs_filename[MAX_FULL_NAME_LEN]
= '\0';
}
@@ -2291,23 +2289,19 @@ void dict_index_remove_from_v_col_list(dict_index_t* index)
/** Adds an index to the dictionary cache, with possible indexing newly
added column.
-@param[in] index index; NOTE! The index memory
+@param[in,out] index index; NOTE! The index memory
object is freed in this function!
@param[in] page_no root page number of the index
-@param[in] strict TRUE=refuse to create the index
+@param[in] strict true=refuse to create the index
if records could be too big to fit in
an B-tree page
-@param[out] err DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION
-@param[in] add_v new virtual column that being added along with
- an add index call
-@return the added index
-@retval NULL on error */
-dict_index_t*
+@param[in] add_v virtual columns being added along with ADD INDEX
+@return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */
+dberr_t
dict_index_add_to_cache(
- dict_index_t* index,
+ dict_index_t*& index,
ulint page_no,
bool strict,
- dberr_t* err,
const dict_add_v_col_t* add_v)
{
dict_index_t* new_index;
@@ -2328,8 +2322,8 @@ dict_index_add_to_cache(
if (!dict_index_find_cols(index, add_v)) {
dict_mem_index_free(index);
- if (err) *err = DB_CORRUPTION;
- return NULL;
+ index = NULL;
+ return DB_CORRUPTION;
}
/* Build the cache internal representation of the index,
@@ -2361,8 +2355,8 @@ dict_index_add_to_cache(
if (strict) {
dict_mem_index_free(new_index);
dict_mem_index_free(index);
- if (err) *err = DB_TOO_BIG_RECORD;
- return NULL;
+ index = NULL;
+ return DB_TOO_BIG_RECORD;
} else if (current_thd != NULL) {
/* Avoid the warning to be printed
during recovery. */
@@ -2440,8 +2434,8 @@ dict_index_add_to_cache(
new_index->n_core_fields = new_index->n_fields;
dict_mem_index_free(index);
- if (err) *err = DB_SUCCESS;
- return new_index;
+ index = new_index;
+ return DB_SUCCESS;
}
/**********************************************************************//**
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index 71cdee691b8..c8ba71e0c06 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -2574,8 +2574,9 @@ corrupted:
and simply did not load this index definition, the
.frm file would disagree with the index definitions
inside InnoDB. */
- if (!dict_index_add_to_cache(
- index, index->page, false, &error)) {
+ if ((error = dict_index_add_to_cache(index,
+ index->page))
+ != DB_SUCCESS) {
goto func_exit;
}
}
@@ -3089,7 +3090,7 @@ func_exit:
fts_free(table);
} else if (fts_optimize_wq) {
fts_optimize_add_table(table);
- } else {
+ } else if (table->can_be_evicted) {
/* fts_optimize_thread is not started yet.
So make the table as non-evictable from cache. */
dict_table_move_from_lru_to_non_lru(table);
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 7b7afa6d1df..567285b0a68 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -5299,9 +5299,8 @@ new_clustered_failed:
for (uint a = 0; a < ctx->num_to_add_index; a++) {
ctx->add_index[a]->table = ctx->new_table;
- ctx->add_index[a] = dict_index_add_to_cache(
- ctx->add_index[a], FIL_NULL, false,
- &error, add_v);
+ error = dict_index_add_to_cache(
+ ctx->add_index[a], FIL_NULL, false, add_v);
ut_a(error == DB_SUCCESS);
}
DBUG_ASSERT(ha_alter_info->key_count
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 41ad08be63f..92d0aadca18 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -4313,6 +4313,71 @@ func_exit:
return(TRUE);
}
+/**
+Delete any buffered entries for a page.
+This prevents an infinite loop on slow shutdown
+in the case where the change buffer bitmap claims that no buffered
+changes exist, while entries exist in the change buffer tree.
+@param page_id page number for which there should be no unbuffered changes */
+ATTRIBUTE_COLD static void ibuf_delete_recs(const page_id_t page_id)
+{
+ ulint dops[IBUF_OP_COUNT];
+ mtr_t mtr;
+ btr_pcur_t pcur;
+ mem_heap_t* heap = mem_heap_create(512);
+ const dtuple_t* tuple = ibuf_search_tuple_build(
+ page_id.space(), page_id.page_no(), heap);
+ memset(dops, 0, sizeof(dops));
+
+loop:
+ ibuf_mtr_start(&mtr);
+ btr_pcur_open(ibuf->index, tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF,
+ &pcur, &mtr);
+
+ if (!btr_pcur_is_on_user_rec(&pcur)) {
+ ut_ad(btr_pcur_is_after_last_in_tree(&pcur));
+ goto func_exit;
+ }
+
+ for (;;) {
+ ut_ad(btr_pcur_is_on_user_rec(&pcur));
+
+ const rec_t* ibuf_rec = btr_pcur_get_rec(&pcur);
+
+ if (ibuf_rec_get_space(&mtr, ibuf_rec)
+ != page_id.space()
+ || ibuf_rec_get_page_no(&mtr, ibuf_rec)
+ != page_id.page_no()) {
+ break;
+ }
+
+ dops[ibuf_rec_get_op_type(&mtr, ibuf_rec)]++;
+
+ /* Delete the record from ibuf */
+ if (ibuf_delete_rec(page_id.space(), page_id.page_no(),
+ &pcur, tuple, &mtr)) {
+ /* Deletion was pessimistic and mtr was committed:
+ we start from the beginning again */
+ ut_ad(mtr.has_committed());
+ goto loop;
+ }
+
+ if (btr_pcur_is_after_last_on_page(&pcur)) {
+ ibuf_mtr_commit(&mtr);
+ btr_pcur_close(&pcur);
+ goto loop;
+ }
+ }
+
+func_exit:
+ ibuf_mtr_commit(&mtr);
+ btr_pcur_close(&pcur);
+
+ ibuf_add_ops(ibuf->n_discarded_ops, dops);
+
+ mem_heap_free(heap);
+}
+
/** When an index page is read from a disk to the buffer pool, this function
applies any buffered operations to the page and deletes the entries from the
insert buffer. If the page is not read, but created in the buffer pool, this
@@ -4332,9 +4397,7 @@ ibuf_merge_or_delete_for_page(
const page_size_t* page_size,
ibool update_ibuf_bitmap)
{
- mem_heap_t* heap;
btr_pcur_t pcur;
- dtuple_t* search_tuple;
#ifdef UNIV_IBUF_DEBUG
ulint volume = 0;
#endif /* UNIV_IBUF_DEBUG */
@@ -4407,9 +4470,16 @@ ibuf_merge_or_delete_for_page(
ibuf_mtr_commit(&mtr);
if (!bitmap_bits) {
- /* No inserts buffered for this page */
-
+ /* No changes are buffered for this page. */
space->release();
+ if (UNIV_UNLIKELY(srv_shutdown_state)
+ && !srv_fast_shutdown) {
+ /* Prevent an infinite loop on slow
+ shutdown, in case the bitmap bits are
+ wrongly clear even though buffered
+ changes exist. */
+ ibuf_delete_recs(page_id);
+ }
return;
}
}
@@ -4422,9 +4492,9 @@ ibuf_merge_or_delete_for_page(
space = NULL;
}
- heap = mem_heap_create(512);
+ mem_heap_t* heap = mem_heap_create(512);
- search_tuple = ibuf_search_tuple_build(
+ const dtuple_t* search_tuple = ibuf_search_tuple_build(
page_id.space(), page_id.page_no(), heap);
if (block != NULL) {
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 8d12cccec32..a015c176a78 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -1067,26 +1067,21 @@ void dict_index_remove_from_v_col_list(dict_index_t* index);
/** Adds an index to the dictionary cache, with possible indexing newly
added column.
-@param[in] index index; NOTE! The index memory
+@param[in,out] index index; NOTE! The index memory
object is freed in this function!
@param[in] page_no root page number of the index
@param[in] strict true=refuse to create the index
if records could be too big to fit in
an B-tree page
-@param[out] err DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION
-@param[in] add_v new virtual column that being added along with
- an add index call
-@return the added index
-@retval NULL on error */
-dict_index_t*
+@param[in] add_v virtual columns being added along with ADD INDEX
+@return DB_SUCCESS, DB_TOO_BIG_RECORD, or DB_CORRUPTION */
+dberr_t
dict_index_add_to_cache(
- dict_index_t* index,
+ dict_index_t*& index,
ulint page_no,
bool strict = false,
- dberr_t* err = NULL,
const dict_add_v_col_t* add_v = NULL)
- MY_ATTRIBUTE((nonnull(1)));
-
+ MY_ATTRIBUTE((warn_unused_result));
/********************************************************************//**
Gets the number of fields in the internal representation of an index,
including fields added by the dictionary system.
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index af1dcfdb0c1..7bf2655c196 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -2580,10 +2580,10 @@ row_create_index_for_mysql(
} else {
dict_build_index_def(table, index, trx);
- /* add index to dictionary cache and also free index object. */
- index = dict_index_add_to_cache(
- index, FIL_NULL, trx_is_strict(trx), &err);
- if (index) {
+ err = dict_index_add_to_cache(
+ index, FIL_NULL, trx_is_strict(trx));
+ ut_ad((index == NULL) == (err != DB_SUCCESS));
+ if (UNIV_LIKELY(err == DB_SUCCESS)) {
ut_ad(!index->is_instant());
index->n_core_null_bytes = UT_BITS_IN_BYTES(
unsigned(index->n_nullable));