diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2022-10-13 10:05:29 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2022-10-13 10:05:29 +0300 |
commit | 588efca2374536aab956e6366f96082f2886c73c (patch) | |
tree | af1b126c795cd1255d7c7d72c201c01339119755 /storage/innobase/row | |
parent | b6ebadaa66ee68b1880c0e10669543d1ba058c18 (diff) | |
parent | 1feccb505f9ec5cada8f8e2c544f736c1a533633 (diff) | |
download | mariadb-git-588efca2374536aab956e6366f96082f2886c73c.tar.gz |
Merge 10.6 into 10.7
Diffstat (limited to 'storage/innobase/row')
-rw-r--r-- | storage/innobase/row/row0ins.cc | 10 | ||||
-rw-r--r-- | storage/innobase/row/row0log.cc | 6 | ||||
-rw-r--r-- | storage/innobase/row/row0merge.cc | 6 | ||||
-rw-r--r-- | storage/innobase/row/row0mysql.cc | 2 | ||||
-rw-r--r-- | storage/innobase/row/row0purge.cc | 190 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.cc | 50 |
6 files changed, 195 insertions, 69 deletions
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index f3a64ca7ae8..1db661963f6 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1140,7 +1140,7 @@ row_ins_foreign_check_on_constraint( tmp_heap); err = btr_pcur_open_with_no_init(clust_index, ref, PAGE_CUR_LE, BTR_SEARCH_LEAF, - cascade->pcur, 0, mtr); + cascade->pcur, mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { goto nonstandard_exit_func; } @@ -2905,7 +2905,7 @@ row_ins_sec_index_entry_low( err = btr_cur_search_to_nth_level( index, 0, entry, PAGE_CUR_RTREE_INSERT, search_mode, - &cursor, 0, &mtr); + &cursor, &mtr); if (err == DB_SUCCESS && search_mode == BTR_MODIFY_LEAF && rtr_info.mbr_adj) { @@ -2924,7 +2924,7 @@ row_ins_sec_index_entry_low( err = btr_cur_search_to_nth_level( index, 0, entry, PAGE_CUR_RTREE_INSERT, search_mode, - &cursor, 0, &mtr); + &cursor, &mtr); } DBUG_EXECUTE_IF( @@ -2939,7 +2939,7 @@ row_ins_sec_index_entry_low( err = btr_cur_search_to_nth_level( index, 0, entry, PAGE_CUR_LE, search_mode, - &cursor, 0, &mtr); + &cursor, &mtr); } if (err != DB_SUCCESS) { @@ -3019,7 +3019,7 @@ row_ins_sec_index_entry_low( index, 0, entry, PAGE_CUR_LE, (search_mode & ~(BTR_INSERT | BTR_IGNORE_SEC_UNIQUE)), - &cursor, 0, &mtr); + &cursor, &mtr); if (err != DB_SUCCESS) { goto func_exit; } diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 15835ff4afd..ccfcac63fdb 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -3081,7 +3081,7 @@ row_log_apply_op_low( has_index_lock ? BTR_MODIFY_TREE : BTR_MODIFY_LEAF, - &cursor, 0, &mtr); + &cursor, &mtr); if (UNIV_UNLIKELY(*error != DB_SUCCESS)) { goto func_exit; } @@ -3133,7 +3133,7 @@ row_log_apply_op_low( index->set_modified(mtr); *error = btr_cur_search_to_nth_level( index, 0, entry, PAGE_CUR_LE, - BTR_MODIFY_TREE, &cursor, 0, &mtr); + BTR_MODIFY_TREE, &cursor, &mtr); if (UNIV_UNLIKELY(*error != DB_SUCCESS)) { goto func_exit; } @@ -3237,7 +3237,7 @@ insert_the_rec: index->set_modified(mtr); *error = btr_cur_search_to_nth_level( index, 0, entry, PAGE_CUR_LE, - BTR_MODIFY_TREE, &cursor, 0, &mtr); + BTR_MODIFY_TREE, &cursor, &mtr); if (*error != DB_SUCCESS) { break; } diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 3ef3076abdc..5afb8665d01 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -160,7 +160,7 @@ public: error = btr_cur_search_to_nth_level( m_index, 0, dtuple, PAGE_CUR_RTREE_INSERT, - BTR_MODIFY_LEAF, &ins_cur, 0, &mtr); + BTR_MODIFY_LEAF, &ins_cur, &mtr); /* It need to update MBR in parent entry, so change search mode to BTR_MODIFY_TREE */ @@ -175,7 +175,7 @@ public: error = btr_cur_search_to_nth_level( m_index, 0, dtuple, PAGE_CUR_RTREE_INSERT, - BTR_MODIFY_TREE, &ins_cur, 0, &mtr); + BTR_MODIFY_TREE, &ins_cur, &mtr); } if (error == DB_SUCCESS) { @@ -201,7 +201,7 @@ public: m_index, 0, dtuple, PAGE_CUR_RTREE_INSERT, BTR_MODIFY_TREE, - &ins_cur, 0, &mtr); + &ins_cur, &mtr); if (error == DB_SUCCESS) { error = btr_cur_pessimistic_insert( diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 0e982f59545..10fe321a702 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2869,7 +2869,7 @@ row_rename_table_for_mysql( dict_names_t fk_tables; err = dict_load_foreigns( - new_name, nullptr, false, trx->id, + new_name, nullptr, trx->id, !old_is_tmp || trx->check_foreigns, use_fk ? DICT_ERR_IGNORE_NONE diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc index 8bbb0a36144..434ea7cfd20 100644 --- a/storage/innobase/row/row0purge.cc +++ b/storage/innobase/row/row0purge.cc @@ -869,6 +869,138 @@ skip_secondaries: row_purge_upd_exist_or_extern_func(node,undo_rec) #endif /* UNIV_DEBUG */ +/** Build a partial row from an update undo log record for purge. +Any columns which occur as ordering in any index of the table are present. +Any missing columns are indicated by col->mtype == DATA_MISSING. + +@param ptr remaining part of the undo log record +@param index clustered index +@param node purge node +@return pointer to remaining part of undo record */ +static byte *row_purge_get_partial(const byte *ptr, const dict_index_t &index, + purge_node_t *node) +{ + bool first_v_col= true; + bool is_undo_log= true; + + ut_ad(index.is_primary()); + ut_ad(index.n_uniq == node->ref->n_fields); + + node->row= dtuple_create_with_vcol(node->heap, index.table->n_cols, + index.table->n_v_cols); + + /* Mark all columns in the row uninitialized, so that + we can distinguish missing fields from fields that are SQL NULL. */ + for (ulint i= 0; i < index.table->n_cols; i++) + node->row->fields[i].type.mtype= DATA_MISSING; + + dtuple_init_v_fld(node->row); + + for (const upd_field_t *uf= node->update->fields, *const ue= + node->update->fields + node->update->n_fields; uf != ue; uf++) + { + if (!uf->old_v_val) + { + const dict_col_t &c= *dict_index_get_nth_col(&index, uf->field_no); + if (!c.is_dropped()) + node->row->fields[c.ind]= uf->new_val; + } + } + + const byte *end_ptr= ptr + mach_read_from_2(ptr); + ptr+= 2; + + while (ptr != end_ptr) + { + dfield_t *dfield; + const byte *field; + const dict_col_t *col; + uint32_t len, orig_len, field_no= mach_read_next_compressed(&ptr); + + if (field_no >= REC_MAX_N_FIELDS) + { + ptr= trx_undo_read_v_idx(index.table, ptr, first_v_col, &is_undo_log, + &field_no); + first_v_col= false; + + ptr= trx_undo_rec_get_col_val(ptr, &field, &len, &orig_len); + + if (field_no == FIL_NULL) + continue; /* there no longer is an index on the virtual column */ + + dict_v_col_t *vcol= dict_table_get_nth_v_col(index.table, field_no); + col =&vcol->m_col; + dfield= dtuple_get_nth_v_field(node->row, vcol->v_pos); + dict_col_copy_type(&vcol->m_col, &dfield->type); + } + else + { + ptr= trx_undo_rec_get_col_val(ptr, &field, &len, &orig_len); + col= dict_index_get_nth_col(&index, field_no); + if (col->is_dropped()) + continue; + dfield= dtuple_get_nth_field(node->row, col->ind); + ut_ad(dfield->type.mtype == DATA_MISSING || + dict_col_type_assert_equal(col, &dfield->type)); + ut_ad(dfield->type.mtype == DATA_MISSING || + dfield->len == len || + (len != UNIV_SQL_NULL && len >= UNIV_EXTERN_STORAGE_FIELD)); + dict_col_copy_type(dict_table_get_nth_col(index.table, col->ind), + &dfield->type); + } + + dfield_set_data(dfield, field, len); + + if (len == UNIV_SQL_NULL || len < UNIV_EXTERN_STORAGE_FIELD) + continue; + + spatial_status_t spatial_status= static_cast<spatial_status_t> + ((len & SPATIAL_STATUS_MASK) >> SPATIAL_STATUS_SHIFT); + len&= ~SPATIAL_STATUS_MASK; + + /* Keep compatible with 5.7.9 format. */ + if (spatial_status == SPATIAL_UNKNOWN) + spatial_status= dict_col_get_spatial_status(col); + + switch (UNIV_EXPECT(spatial_status, SPATIAL_NONE)) { + case SPATIAL_ONLY: + ut_ad(len - UNIV_EXTERN_STORAGE_FIELD == DATA_MBR_LEN); + dfield_set_len(dfield, len - UNIV_EXTERN_STORAGE_FIELD); + break; + + case SPATIAL_MIXED: + dfield_set_len(dfield, len - UNIV_EXTERN_STORAGE_FIELD - DATA_MBR_LEN); + break; + + default: + dfield_set_len(dfield, len - UNIV_EXTERN_STORAGE_FIELD); + break; + } + + dfield_set_ext(dfield); + dfield_set_spatial_status(dfield, spatial_status); + + if (!col->ord_part || spatial_status == SPATIAL_ONLY || + node->rec_type == TRX_UNDO_UPD_DEL_REC) + continue; + /* If the prefix of this BLOB column is indexed, ensure that enough + prefix is stored in the undo log record. */ + ut_a(dfield_get_len(dfield) >= BTR_EXTERN_FIELD_REF_SIZE); + ut_a(dict_table_has_atomic_blobs(index.table) || + dfield_get_len(dfield) >= + REC_ANTELOPE_MAX_INDEX_COL_LEN + BTR_EXTERN_FIELD_REF_SIZE); + } + + for (ulint i= 0; i < index.n_uniq; i++) + { + dfield_t &field= node->row->fields[index.fields[i].col->ind]; + if (field.type.mtype == DATA_MISSING) + field= node->ref->fields[i]; + } + + return const_cast<byte*>(ptr); +} + MY_ATTRIBUTE((nonnull,warn_unused_result)) /** Parses the row reference and other info in a modify undo log record. @param[in] node row undo node @@ -1020,10 +1152,7 @@ err_exit: if (!(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { ut_ad(!(node->update->info_bits & REC_INFO_MIN_REC_FLAG)); - ptr = trx_undo_rec_get_partial_row( - ptr, clust_index, node->update, &node->row, - type == TRX_UNDO_UPD_DEL_REC, - node->heap); + ptr = row_purge_get_partial(ptr, *clust_index, node); } else if (node->update->info_bits & REC_INFO_MIN_REC_FLAG) { node->ref = &trx_undo_metadata; } @@ -1135,25 +1264,39 @@ row_purge( } } -/***********************************************************//** -Reset the purge query thread. */ -UNIV_INLINE -void -row_purge_end( -/*==========*/ - que_thr_t* thr) /*!< in: query thread */ +inline void purge_node_t::start() { - ut_ad(thr); - - thr->run_node = static_cast<purge_node_t*>(thr->run_node)->end(); + ut_ad(in_progress); + DBUG_ASSERT(common.type == QUE_NODE_PURGE); + + row= nullptr; + ref= nullptr; + index= nullptr; + update= nullptr; + found_clust= FALSE; + rec_type= ULINT_UNDEFINED; + cmpl_info= ULINT_UNDEFINED; + if (!purge_thd) + purge_thd= current_thd; +} - ut_a(thr->run_node != NULL); +/** Reset the state at end +@return the query graph parent */ +inline que_node_t *purge_node_t::end() +{ + DBUG_ASSERT(common.type == QUE_NODE_PURGE); + close_table(); + ut_ad(undo_recs.empty()); + ut_d(in_progress= false); + purge_thd= nullptr; + mem_heap_empty(heap); + return common.parent; } + /***********************************************************//** -Does the purge operation for a single undo log record. This is a high-level -function used in an SQL execution graph. -@return query thread to run next or NULL */ +Does the purge operation. +@return query thread to run next */ que_thr_t* row_purge_step( /*===========*/ @@ -1165,22 +1308,15 @@ row_purge_step( node->start(); - if (!node->undo_recs.empty()) { + while (!node->undo_recs.empty()) { trx_purge_rec_t purge_rec = node->undo_recs.front(); node->undo_recs.pop(); node->roll_ptr = purge_rec.roll_ptr; row_purge(node, purge_rec.undo_rec, thr); - - if (node->undo_recs.empty()) { - row_purge_end(thr); - } else { - thr->run_node = node; - } - } else { - row_purge_end(thr); } + thr->run_node = node->end(); return(thr); } diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index ec4d09115f6..614376d4a7a 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -1007,7 +1007,7 @@ row_sel_get_clust_rec( dberr_t err = btr_pcur_open_with_no_init(index, plan->clust_ref, PAGE_CUR_LE, BTR_SEARCH_LEAF, - &plan->clust_pcur, 0, mtr); + &plan->clust_pcur, mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { goto err_exit; } @@ -1412,7 +1412,7 @@ row_sel_open_pcur( err = btr_pcur_open_with_no_init(index, plan->tuple, plan->mode, BTR_SEARCH_LEAF, - &plan->pcur, nullptr, mtr); + &plan->pcur, mtr); } else { err = btr_pcur_open_at_index_side(plan->asc, index, BTR_SEARCH_LEAF, &plan->pcur, @@ -1562,8 +1562,7 @@ row_sel_try_search_shortcut( const rec_t* rec = btr_pcur_get_rec(&(plan->pcur)); if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, *index)) { -retry: - return(SEL_RETRY); + return SEL_RETRY; } ut_ad(plan->mode == PAGE_CUR_GE); @@ -1573,14 +1572,13 @@ retry: fields in the user record matched to the search tuple */ if (btr_pcur_get_up_match(&(plan->pcur)) < plan->n_exact_match) { -exhausted: - return(SEL_EXHAUSTED); + return SEL_EXHAUSTED; } if (trx_id_t bulk_trx_id = index->table->bulk_trx_id) { /* See row_search_mvcc() for a comment on bulk_trx_id */ if (!node->read_view->changes_visible(bulk_trx_id)) { - goto exhausted; + return SEL_EXHAUSTED; } } @@ -1597,18 +1595,18 @@ exhausted: if (dict_index_is_clust(index)) { if (!row_sel_clust_sees(rec, *index, offsets, *node->read_view)) { - goto retry; + return SEL_RETRY; } } else if (!srv_read_only_mode) { trx_id_t trx_id = page_get_max_trx_id(page_align(rec)); ut_ad(trx_id); if (!node->read_view->sees(trx_id)) { - goto retry; + return SEL_RETRY; } } if (rec_get_deleted_flag(rec, dict_table_is_comp(plan->table))) { - goto exhausted; + return SEL_EXHAUSTED; } /* Fetch the columns needed in test conditions. The index @@ -1622,7 +1620,7 @@ exhausted: /* Test the rest of search conditions */ if (!row_sel_test_other_conds(plan)) { - goto exhausted; + return SEL_EXHAUSTED; } ut_ad(plan->pcur.latch_mode == BTR_SEARCH_LEAF); @@ -1632,7 +1630,7 @@ exhausted: if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } - return(SEL_FOUND); + return SEL_FOUND; } #endif /* BTR_CUR_HASH_ADAPT */ @@ -3360,7 +3358,7 @@ Row_sel_get_clust_rec_for_mysql::operator()( dberr_t err = btr_pcur_open_with_no_init(clust_index, prebuilt->clust_ref, PAGE_CUR_LE, BTR_SEARCH_LEAF, - prebuilt->clust_pcur, 0, mtr); + prebuilt->clust_pcur, mtr); if (UNIV_UNLIKELY(err != DB_SUCCESS)) { return err; } @@ -3945,20 +3943,16 @@ row_sel_try_search_shortcut_for_mysql( ut_ad(!prebuilt->templ_contains_blob); ut_ad(trx->read_view.is_open()); - srw_spin_lock* ahi_latch = btr_search_sys.get_latch(*index); - ahi_latch->rd_lock(SRW_LOCK_CALL); if (btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE, - BTR_SEARCH_LEAF, pcur, ahi_latch, mtr) + BTR_SEARCH_LEAF, pcur, mtr) != DB_SUCCESS) { - goto retry; + return SEL_RETRY; } rec = btr_pcur_get_rec(pcur); if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, *index)) { -retry: - ahi_latch->rd_unlock(); - return(SEL_RETRY); + return SEL_RETRY; } /* As the cursor is now placed on a user record after a search with @@ -3966,16 +3960,14 @@ retry: fields in the user record matched to the search tuple */ if (btr_pcur_get_up_match(pcur) < dtuple_get_n_fields(search_tuple)) { -exhausted: - ahi_latch->rd_unlock(); - return(SEL_EXHAUSTED); + return SEL_EXHAUSTED; } if (trx->isolation_level == TRX_ISO_READ_UNCOMMITTED) { } else if (trx_id_t bulk_trx_id = index->table->bulk_trx_id) { /* See row_search_mvcc() for a comment on bulk_trx_id */ if (!trx->read_view.changes_visible(bulk_trx_id)) { - goto exhausted; + return SEL_EXHAUSTED; } } @@ -3986,20 +3978,19 @@ exhausted: ULINT_UNDEFINED, heap); if (!row_sel_clust_sees(rec, *index, *offsets, trx->read_view)) { - goto retry; + return SEL_RETRY; } if (rec_get_deleted_flag(rec, dict_table_is_comp(index->table))) { /* In delete-marked records, DB_TRX_ID must always refer to an existing undo log record. */ ut_ad(row_get_rec_trx_id(rec, index, *offsets)); - goto exhausted; + return SEL_EXHAUSTED; } *out_rec = rec; - ahi_latch->rd_unlock(); - return(SEL_FOUND); + return SEL_FOUND; } #endif /* BTR_CUR_HASH_ADAPT */ @@ -4772,8 +4763,7 @@ wait_table_again: } err = btr_pcur_open_with_no_init(index, search_tuple, mode, - BTR_SEARCH_LEAF, - pcur, 0, &mtr); + BTR_SEARCH_LEAF, pcur, &mtr); if (err != DB_SUCCESS) { page_corrupted: |