summaryrefslogtreecommitdiff
path: root/storage/innobase/row
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2022-10-13 10:05:29 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2022-10-13 10:05:29 +0300
commit588efca2374536aab956e6366f96082f2886c73c (patch)
treeaf1b126c795cd1255d7c7d72c201c01339119755 /storage/innobase/row
parentb6ebadaa66ee68b1880c0e10669543d1ba058c18 (diff)
parent1feccb505f9ec5cada8f8e2c544f736c1a533633 (diff)
downloadmariadb-git-588efca2374536aab956e6366f96082f2886c73c.tar.gz
Merge 10.6 into 10.7
Diffstat (limited to 'storage/innobase/row')
-rw-r--r--storage/innobase/row/row0ins.cc10
-rw-r--r--storage/innobase/row/row0log.cc6
-rw-r--r--storage/innobase/row/row0merge.cc6
-rw-r--r--storage/innobase/row/row0mysql.cc2
-rw-r--r--storage/innobase/row/row0purge.cc190
-rw-r--r--storage/innobase/row/row0sel.cc50
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: