summaryrefslogtreecommitdiff
path: root/storage/innobase/row
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/row')
-rw-r--r--storage/innobase/row/row0ins.cc51
-rw-r--r--storage/innobase/row/row0log.cc93
-rw-r--r--storage/innobase/row/row0merge.cc9
-rw-r--r--storage/innobase/row/row0purge.cc6
-rw-r--r--storage/innobase/row/row0sel.cc10
-rw-r--r--storage/innobase/row/row0uins.cc9
-rw-r--r--storage/innobase/row/row0undo.cc1
7 files changed, 161 insertions, 18 deletions
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 5e41d037b6c..87e64b3951e 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -2555,15 +2555,20 @@ row_ins_clust_index_entry_low(
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
rec_offs* offsets = offsets_;
rec_offs_init(offsets_);
+ trx_t* trx = thr_get_trx(thr);
+ buf_block_t* block;
DBUG_ENTER("row_ins_clust_index_entry_low");
+ DEBUG_SYNC_C("row_ins_clust_index_entry_low_enter");
+
ut_ad(dict_index_is_clust(index));
ut_ad(!dict_index_is_unique(index)
|| n_uniq == dict_index_get_n_unique(index));
ut_ad(!n_uniq || n_uniq == dict_index_get_n_unique(index));
- ut_ad(!thr_get_trx(thr)->in_rollback);
+ ut_ad(!trx->in_rollback);
+start_read:
mtr_start(&mtr);
if (index->table->is_temporary()) {
@@ -2634,6 +2639,44 @@ row_ins_clust_index_entry_low(
}
#endif /* UNIV_DEBUG */
+ block = btr_cur_get_block(cursor);
+
+ if (block->page.id().page_no() == index->page
+ && !(flags & BTR_NO_UNDO_LOG_FLAG)
+ && !index->table->is_temporary()
+ && !entry->is_metadata() && !trx->duplicates
+ && !trx->ddl && !trx->internal
+ && page_is_empty(block->frame)) {
+
+ DEBUG_SYNC_C("empty_root_page_insert");
+
+ err = lock_table(0, index->table, LOCK_X, thr);
+
+ if (err == DB_LOCK_WAIT) {
+ mtr_commit(&mtr);
+
+ trx->error_state = err;
+
+ que_thr_stop_for_mysql(thr);
+
+ thr->lock_state = QUE_THR_LOCK_ROW;
+
+ lock_wait_suspend_thread(thr);
+
+ thr->lock_state = QUE_THR_LOCK_NOLOCK;
+
+ err = trx->error_state;
+
+ if (err != DB_SUCCESS) {
+ goto func_exit;
+ }
+
+ goto start_read;
+ }
+
+ index->table->bulk_trx_id = trx->id;
+ }
+
if (UNIV_UNLIKELY(entry->info_bits != 0)) {
ut_ad(entry->is_metadata());
ut_ad(flags == BTR_NO_LOCKING_FLAG);
@@ -2644,7 +2687,7 @@ row_ins_clust_index_entry_low(
if (rec_get_info_bits(rec, page_rec_is_comp(rec))
& REC_INFO_MIN_REC_FLAG) {
- thr_get_trx(thr)->error_info = index;
+ trx->error_info = index;
err = DB_DUPLICATE_KEY;
goto err_exit;
}
@@ -2677,7 +2720,7 @@ row_ins_clust_index_entry_low(
/* fall through */
case DB_SUCCESS_LOCKED_REC:
case DB_DUPLICATE_KEY:
- thr_get_trx(thr)->error_info = cursor->index;
+ trx->error_info = cursor->index;
}
} else {
/* Note that the following may return also
@@ -2761,7 +2804,7 @@ do_insert:
log_write_up_to(mtr.commit_lsn(), true););
err = row_ins_index_entry_big_rec(
entry, big_rec, offsets, &offsets_heap, index,
- thr_get_trx(thr)->mysql_thd);
+ trx->mysql_thd);
dtuple_convert_back_big_rec(index, entry, big_rec);
} else {
if (err == DB_SUCCESS
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index 4a98ac24185..0010cf86d86 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -54,7 +54,9 @@ enum row_tab_op {
/** Update a record in place */
ROW_T_UPDATE,
/** Delete (purge) a record */
- ROW_T_DELETE
+ ROW_T_DELETE,
+ /** Empty the table */
+ ROW_T_EMPTY
};
/** Index record modification operations during online index creation */
@@ -62,7 +64,9 @@ enum row_op {
/** Insert a record */
ROW_OP_INSERT = 0x61,
/** Delete a record */
- ROW_OP_DELETE
+ ROW_OP_DELETE,
+ /** Empy the index */
+ ROW_OP_EMPTY
};
/** Size of the modification log entry header, in bytes */
@@ -339,8 +343,8 @@ row_log_online_op(
ulint avail_size;
row_log_t* log;
- ut_ad(dtuple_validate(tuple));
- ut_ad(dtuple_get_n_fields(tuple) == dict_index_get_n_fields(index));
+ ut_ad(!tuple || dtuple_validate(tuple));
+ ut_ad(!tuple || dtuple_get_n_fields(tuple) == dict_index_get_n_fields(index));
ut_ad(rw_lock_own_flagged(&index->lock,
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
@@ -354,14 +358,19 @@ row_log_online_op(
row_merge_buf_encode(), because here we do not encode
extra_size+1 (and reserve 0 as the end-of-chunk marker). */
- size = rec_get_converted_size_temp(
- index, tuple->fields, tuple->n_fields, &extra_size);
- ut_ad(size >= extra_size);
- ut_ad(size <= sizeof log->tail.buf);
+ if (!tuple) {
+ mrec_size = 4;
+ extra_size = 0;
+ } else {
+ size = rec_get_converted_size_temp(
+ index, tuple->fields, tuple->n_fields, &extra_size);
+ ut_ad(size >= extra_size);
+ ut_ad(size <= sizeof log->tail.buf);
- mrec_size = ROW_LOG_HEADER_SIZE
- + (extra_size >= 0x80) + size
- + (trx_id ? DATA_TRX_ID_LEN : 0);
+ mrec_size = ROW_LOG_HEADER_SIZE
+ + (extra_size >= 0x80) + size
+ + (trx_id ? DATA_TRX_ID_LEN : 0);
+ }
log = index->online_log;
mutex_enter(&log->mutex);
@@ -390,6 +399,8 @@ row_log_online_op(
*b++ = ROW_OP_INSERT;
trx_write_trx_id(b, trx_id);
b += DATA_TRX_ID_LEN;
+ } else if (tuple == nullptr) {
+ *b++ = ROW_OP_EMPTY;
} else {
*b++ = ROW_OP_DELETE;
}
@@ -402,9 +413,15 @@ row_log_online_op(
*b++ = (byte) extra_size;
}
- rec_convert_dtuple_to_temp(
- b + extra_size, index, tuple->fields, tuple->n_fields);
- b += size;
+ if (tuple) {
+ rec_convert_dtuple_to_temp(
+ b + extra_size, index, tuple->fields,
+ tuple->n_fields);
+ b += size;
+ } else {
+ *b++ = 0;
+ *b++ = 0;
+ }
if (mrec_size >= avail_size) {
const os_offset_t byte_offset
@@ -2399,6 +2416,18 @@ func_exit_committed:
goto func_exit;
}
+/** Applies the empty table to a table that was rebuilt.
+@param index clustered index
+@retrun success if index gets emptied */
+static
+dberr_t
+row_log_table_apply_empty(dict_index_t* index, que_thr_t *thr)
+{
+ dict_table_t* new_table= index->online_log->table;
+ new_table->empty_table(thr);
+ return DB_SUCCESS;
+}
+
/******************************************************//**
Applies an operation to a table that was rebuilt.
@return NULL on failure (mrec corruption) or when out of data;
@@ -2669,6 +2698,11 @@ row_log_table_apply_op(
thr, new_trx_id_col,
mrec, offsets, offsets_heap, heap, dup, old_pk);
break;
+ case ROW_T_EMPTY:
+ *error = row_log_table_apply_empty(dup->index, thr);
+ log->head.total += 4;
+ next_mrec = mrec + 3;
+ break;
}
ut_ad(log->head.total <= log->tail.total);
@@ -3454,6 +3488,9 @@ row_log_apply_op_low(
}
goto duplicate;
+ case ROW_OP_EMPTY:
+ ut_ad(0);
+ break;
}
} else {
switch (op) {
@@ -3525,6 +3562,9 @@ insert_the_rec:
0, NULL, &mtr);
ut_ad(!big_rec);
break;
+ case ROW_OP_EMPTY:
+ ut_ad(0);
+ break;
}
mem_heap_empty(offsets_heap);
}
@@ -3600,6 +3640,17 @@ row_log_apply_op(
op = static_cast<enum row_op>(*mrec++);
trx_id = 0;
break;
+ case ROW_OP_EMPTY:
+ {
+ mem_heap_t* heap = mem_heap_create(512);
+ que_fork_t* fork = que_fork_create(
+ NULL, NULL, QUE_FORK_MYSQL_INTERFACE, heap);
+ que_thr_t* thr = que_thr_create(fork, heap, nullptr);
+ index->empty(thr);
+ *error = DB_SUCCESS;
+ mem_heap_free(heap);
+ return mrec + 4;
+ }
default:
corrupted:
ut_ad(0);
@@ -4042,3 +4093,17 @@ row_log_apply(
DBUG_RETURN(error);
}
+
+void row_log_table_empty(dict_index_t *index)
+{
+ row_log_t* log= index->online_log;
+ ulint avail_size;
+ if (byte* b = row_log_table_open(log, 4, &avail_size))
+ {
+ *b++ = ROW_T_EMPTY;
+ *b++= 0;
+ *b++= 0;
+ *b++= 0;
+ row_log_table_close(index, b, 4, avail_size);
+ }
+}
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index e306cb3429b..604425d82dd 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -1754,6 +1754,15 @@ row_merge_read_clustered_index(
/* There is no previous tuple yet. */
prev_mtuple.fields = NULL;
+ if (trx_id_t bulk_trx_id = old_table->bulk_trx_id) {
+ if (trx->read_view.is_open()
+ && !trx->read_view.changes_visible(
+ bulk_trx_id, old_table->name)) {
+ trx->op_info="";
+ DBUG_RETURN(DB_SUCCESS);
+ }
+ }
+
for (ulint i = 0; i < n_index; i++) {
if (index[i]->type & DICT_FTS) {
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index 5579e53b6c1..b856da86fc1 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -896,6 +896,7 @@ row_purge_parse_undo_rec(
switch (type) {
case TRX_UNDO_RENAME_TABLE:
return false;
+ case TRX_UNDO_EMPTY:
case TRX_UNDO_INSERT_METADATA:
case TRX_UNDO_INSERT_REC:
/* These records do not store any transaction identifier.
@@ -986,6 +987,9 @@ err_exit:
if (type == TRX_UNDO_INSERT_METADATA) {
node->ref = &trx_undo_metadata;
return(true);
+ } else if (type == TRX_UNDO_EMPTY) {
+ node->ref = nullptr;
+ return true;
}
ptr = trx_undo_rec_get_row_ref(ptr, clust_index, &(node->ref),
@@ -1043,6 +1047,8 @@ row_purge_record_func(
ut_ad(!trx_undo_roll_ptr_is_insert(node->roll_ptr));
switch (node->rec_type) {
+ case TRX_UNDO_EMPTY:
+ break;
case TRX_UNDO_DEL_MARK_REC:
purged = row_purge_del_mark(node);
if (purged) {
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index 7a859ab8b09..16b5e43e9c5 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -4397,6 +4397,16 @@ early_not_found:
DBUG_RETURN(DB_END_OF_INDEX);
}
+ if (trx_id_t bulk_trx_id = index->table->bulk_trx_id) {
+ if (trx->isolation_level != TRX_ISO_READ_UNCOMMITTED
+ && trx->read_view.is_open()
+ && !trx->read_view.changes_visible(
+ bulk_trx_id, index->table->name)) {
+ trx->op_info = "";
+ DBUG_RETURN(DB_END_OF_INDEX);
+ }
+ }
+
/* if the query is a plain locking SELECT, and the isolation level
is <= TRX_ISO_READ_COMMITTED, then this is set to FALSE */
bool did_semi_consistent_read = false;
diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc
index 0ce136c5906..f4c37d26d76 100644
--- a/storage/innobase/row/row0uins.cc
+++ b/storage/innobase/row/row0uins.cc
@@ -384,6 +384,7 @@ static bool row_undo_ins_parse_undo_rec(undo_node_t* node, bool dict_locked)
goto close_table;
case TRX_UNDO_INSERT_METADATA:
case TRX_UNDO_INSERT_REC:
+ case TRX_UNDO_EMPTY:
break;
case TRX_UNDO_RENAME_TABLE:
dict_table_t* table = node->table;
@@ -424,6 +425,9 @@ close_table:
ptr = trx_undo_rec_get_row_ref(
ptr, clust_index, &node->ref,
node->heap);
+ } else if (node->rec_type == TRX_UNDO_EMPTY) {
+ node->ref = nullptr;
+ return true;
} else {
node->ref = &trx_undo_metadata;
if (!row_undo_search_clust_to_pcur(node)) {
@@ -596,6 +600,11 @@ row_undo_ins(
log_free_check();
ut_ad(!node->table->is_temporary());
err = row_undo_ins_remove_clust_rec(node);
+ break;
+ case TRX_UNDO_EMPTY:
+ node->table->empty_table(thr);
+ err = DB_SUCCESS;
+ break;
}
dict_table_close(node->table, dict_locked, FALSE);
diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc
index 375de331255..0ef870714c1 100644
--- a/storage/innobase/row/row0undo.cc
+++ b/storage/innobase/row/row0undo.cc
@@ -363,6 +363,7 @@ static bool row_undo_rec_get(undo_node_t* node)
switch (trx_undo_rec_get_type(node->undo_rec)) {
case TRX_UNDO_INSERT_METADATA:
+ case TRX_UNDO_EMPTY:
/* This record type was introduced in MDEV-11369
instant ADD COLUMN, which was implemented after
MDEV-12288 removed the insert_undo log. There is no