summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-11-06 13:44:56 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-11-06 13:44:56 +0200
commit928abd6967b7925c3cd7fdf53f31d0b0fb307e41 (patch)
tree805f388e65be49f60193bc470c0dd2b581e03198 /storage
parentd9899ce671b7a1d1c55993ab00c6b40d79d61b48 (diff)
parent908ca4668d5cb415f4737c8617ffb84f2c15855d (diff)
downloadmariadb-git-928abd6967b7925c3cd7fdf53f31d0b0fb307e41.tar.gz
Merge 10.3 into 10.4
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 c8538543b3e..ada2062dfbf 100644
--- a/storage/innobase/dict/dict0boot.cc
+++ b/storage/innobase/dict/dict0boot.cc
@@ -89,8 +89,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);
@@ -323,9 +322,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));
@@ -335,9 +334,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,
@@ -365,9 +364,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));
@@ -408,9 +407,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));
@@ -437,9 +436,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 24662eed8af..539bbdc205c 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -1243,9 +1243,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 a6b55600ebd..abaa4f60ffe 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -1462,8 +1462,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) {
@@ -1485,8 +1484,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';
}
@@ -1936,23 +1934,19 @@ add_field_size:
/** 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;
@@ -1973,8 +1967,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,
@@ -2006,8 +2000,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. */
@@ -2085,8 +2079,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 c4b93fde2b0..27b3f5f2e5c 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -2571,8 +2571,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;
}
}
@@ -3085,7 +3086,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_sys.prevent_eviction(table);
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 4f9df049c5e..8028b1d7e49 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -6559,9 +6559,8 @@ new_clustered_failed:
trx_is_strict(ctx->trx))) {
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);
}
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 83a047dbd47..a3a169f39c7 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -4277,6 +4277,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
@@ -4297,9 +4362,7 @@ ibuf_merge_or_delete_for_page(
ulint zip_size,
bool 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 */
@@ -4357,9 +4420,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;
}
}
@@ -4372,9 +4442,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 901a9ad415a..4933ee90d6c 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -973,26 +973,21 @@ dict_make_room_in_cache(
/** 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 63e59956989..5a4317292be 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -2566,10 +2566,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));