diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-11-06 13:14:31 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-11-06 13:14:31 +0200 |
commit | 908ca4668d5cb415f4737c8617ffb84f2c15855d (patch) | |
tree | 97b0b5322c3833d5d66e6a8b0c6de195aca18320 /storage | |
parent | 5d3bd2b75b5bf32e69a9b32333cbf8dffe7a2541 (diff) | |
parent | 90451a59811b415a443aab97230e694856392cb5 (diff) | |
download | mariadb-git-908ca4668d5cb415f4737c8617ffb84f2c15855d.tar.gz |
Merge 10.2 into 10.3
Diffstat (limited to 'storage')
-rw-r--r-- | storage/heap/_check.c | 27 | ||||
-rw-r--r-- | storage/innobase/dict/dict0boot.cc | 23 | ||||
-rw-r--r-- | storage/innobase/dict/dict0crea.cc | 4 | ||||
-rw-r--r-- | storage/innobase/dict/dict0dict.cc | 34 | ||||
-rw-r--r-- | storage/innobase/dict/dict0load.cc | 7 | ||||
-rw-r--r-- | storage/innobase/handler/handler0alter.cc | 5 | ||||
-rw-r--r-- | storage/innobase/ibuf/ibuf0ibuf.cc | 82 | ||||
-rw-r--r-- | storage/innobase/include/dict0dict.h | 17 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 8 |
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)); |