summaryrefslogtreecommitdiff
path: root/storage/innobase/row/row0ins.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/row/row0ins.cc')
-rw-r--r--storage/innobase/row/row0ins.cc704
1 files changed, 321 insertions, 383 deletions
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 79a255dfc8f..d9bc72bee28 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2016, 2022, MariaDB Corporation.
+Copyright (c) 2016, 2023, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -35,7 +35,6 @@ Created 4/20/1996 Heikki Tuuri
#include "que0que.h"
#include "row0upd.h"
#include "row0sel.h"
-#include "row0log.h"
#include "rem0cmp.h"
#include "lock0lock.h"
#include "log0log.h"
@@ -44,9 +43,13 @@ Created 4/20/1996 Heikki Tuuri
#include "buf0lru.h"
#include "fts0fts.h"
#include "fts0types.h"
+#ifdef BTR_CUR_HASH_ADAPT
+# include "btr0sea.h"
+#endif
#ifdef WITH_WSREP
#include <wsrep.h>
#include <mysql/service_wsrep.h>
+#include "ha_prototypes.h"
#endif /* WITH_WSREP */
/*************************************************************************
@@ -172,7 +175,7 @@ dberr_t
row_ins_sec_index_entry_by_modify(
/*==============================*/
ulint flags, /*!< in: undo logging and locking flags */
- ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
+ ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE,
depending on whether mtr holds just a leaf
latch or also a tree latch */
btr_cur_t* cursor, /*!< in: B-tree cursor */
@@ -192,8 +195,8 @@ row_ins_sec_index_entry_by_modify(
rec = btr_cur_get_rec(cursor);
- ut_ad(!dict_index_is_clust(cursor->index));
- ut_ad(rec_offs_validate(rec, cursor->index, *offsets));
+ ut_ad(!cursor->index()->is_clust());
+ ut_ad(rec_offs_validate(rec, cursor->index(), *offsets));
ut_ad(!entry->info_bits);
/* We know that in the alphabetical ordering, entry and rec are
@@ -202,7 +205,7 @@ row_ins_sec_index_entry_by_modify(
difference. */
update = row_upd_build_sec_rec_difference_binary(
- rec, cursor->index, *offsets, entry, heap);
+ rec, cursor->index(), *offsets, entry, heap);
if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets))) {
/* We should never insert in place of a record that
@@ -216,8 +219,8 @@ row_ins_sec_index_entry_by_modify(
returns. After that point, set_committed(true)
would be invoked in commit_inplace_alter_table(). */
ut_a(update->n_fields == 0);
- ut_a(!cursor->index->is_committed());
- ut_ad(!dict_index_is_online_ddl(cursor->index));
+ ut_a(!cursor->index()->is_committed());
+ ut_ad(!dict_index_is_online_ddl(cursor->index()));
return(DB_SUCCESS);
}
@@ -239,7 +242,7 @@ row_ins_sec_index_entry_by_modify(
break;
}
} else {
- ut_a(mode == BTR_MODIFY_TREE);
+ ut_ad(mode == BTR_INSERT_TREE);
if (buf_pool.running_out()) {
return(DB_LOCK_TABLE_FULL);
@@ -286,15 +289,15 @@ row_ins_clust_index_entry_by_modify(
dberr_t err = DB_SUCCESS;
btr_cur_t* cursor = btr_pcur_get_btr_cur(pcur);
TABLE* mysql_table = NULL;
- ut_ad(dict_index_is_clust(cursor->index));
+ ut_ad(cursor->index()->is_clust());
rec = btr_cur_get_rec(cursor);
ut_ad(rec_get_deleted_flag(rec,
- dict_table_is_comp(cursor->index->table)));
+ cursor->index()->table->not_redundant()));
/* In delete-marked records, DB_TRX_ID must
always refer to an existing undo log record. */
- ut_ad(rec_get_trx_id(rec, cursor->index));
+ ut_ad(rec_get_trx_id(rec, cursor->index()));
/* Build an update vector containing all the fields to be modified;
NOTE that this vector may NOT contain system columns trx_id or
@@ -305,15 +308,17 @@ row_ins_clust_index_entry_by_modify(
}
update = row_upd_build_difference_binary(
- cursor->index, entry, rec, NULL, true, true,
+ cursor->index(), entry, rec, NULL, true, true,
thr_get_trx(thr), heap, mysql_table, &err);
if (err != DB_SUCCESS) {
return(err);
}
if (mode != BTR_MODIFY_TREE) {
- ut_ad((mode & ulint(~BTR_ALREADY_S_LATCHED))
- == BTR_MODIFY_LEAF);
+ ut_ad(mode == BTR_MODIFY_LEAF
+ || mode == BTR_MODIFY_LEAF_ALREADY_LATCHED
+ || mode == BTR_MODIFY_ROOT_AND_LEAF
+ || mode == BTR_MODIFY_ROOT_AND_LEAF_ALREADY_LATCHED);
/* Try optimistic updating of the record, keeping changes
within the page */
@@ -672,7 +677,7 @@ row_ins_set_detailed(
{
ut_ad(!srv_read_only_mode);
- mutex_enter(&srv_misc_tmpfile_mutex);
+ mysql_mutex_lock(&srv_misc_tmpfile_mutex);
rewind(srv_misc_tmpfile);
if (os_file_set_eof(srv_misc_tmpfile)) {
@@ -686,13 +691,14 @@ row_ins_set_detailed(
trx_set_detailed_error(trx, "temp file operation failed");
}
- mutex_exit(&srv_misc_tmpfile_mutex);
+ mysql_mutex_unlock(&srv_misc_tmpfile_mutex);
}
/*********************************************************************//**
Acquires dict_foreign_err_mutex, rewinds dict_foreign_err_file
and displays information about the given transaction.
The caller must release dict_foreign_err_mutex. */
+TRANSACTIONAL_TARGET
static
void
row_ins_foreign_trx_print(
@@ -705,13 +711,14 @@ row_ins_foreign_trx_print(
ut_ad(!srv_read_only_mode);
- lock_mutex_enter();
- n_rec_locks = lock_number_of_rows_locked(&trx->lock);
- n_trx_locks = UT_LIST_GET_LEN(trx->lock.trx_locks);
- heap_size = mem_heap_get_size(trx->lock.lock_heap);
- lock_mutex_exit();
+ {
+ TMLockMutexGuard g{SRW_LOCK_CALL};
+ n_rec_locks = trx->lock.n_rec_locks;
+ n_trx_locks = UT_LIST_GET_LEN(trx->lock.trx_locks);
+ heap_size = mem_heap_get_size(trx->lock.lock_heap);
+ }
- mutex_enter(&dict_foreign_err_mutex);
+ mysql_mutex_lock(&dict_foreign_err_mutex);
rewind(dict_foreign_err_file);
ut_print_timestamp(dict_foreign_err_file);
fputs(" Transaction:\n", dict_foreign_err_file);
@@ -719,7 +726,7 @@ row_ins_foreign_trx_print(
trx_print_low(dict_foreign_err_file, trx, 600,
n_rec_locks, n_trx_locks, heap_size);
- ut_ad(mutex_own(&dict_foreign_err_mutex));
+ mysql_mutex_assert_owner(&dict_foreign_err_mutex);
}
/*********************************************************************//**
@@ -777,7 +784,7 @@ row_ins_foreign_report_err(
}
putc('\n', ef);
- mutex_exit(&dict_foreign_err_mutex);
+ mysql_mutex_unlock(&dict_foreign_err_mutex);
}
/*********************************************************************//**
@@ -843,7 +850,7 @@ row_ins_foreign_report_add_err(
}
putc('\n', ef);
- mutex_exit(&dict_foreign_err_mutex);
+ mysql_mutex_unlock(&dict_foreign_err_mutex);
}
/*********************************************************************//**
@@ -993,7 +1000,8 @@ row_ins_foreign_check_on_constraint(
{
upd_node_t* node;
upd_node_t* cascade;
- dict_table_t* table = foreign->foreign_table;
+ dict_table_t*const*const fktable = &foreign->foreign_table;
+ dict_table_t* table = *fktable;
dict_index_t* index;
dict_index_t* clust_index;
dtuple_t* ref;
@@ -1013,8 +1021,8 @@ row_ins_foreign_check_on_constraint(
/* Since we are going to delete or update a row, we have to invalidate
the MySQL query cache for table. A deadlock of threads is not possible
here because the caller of this function does not hold any latches with
- the mutex rank above the lock_sys_t::mutex. The query cache mutex
- has a rank just above the lock_sys_t::mutex. */
+ the mutex rank above the lock_sys.latch. The query cache mutex
+ has a rank just above the lock_sys.latch. */
row_ins_invalidate_query_cache(thr, table->name.m_name);
@@ -1106,7 +1114,7 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
- index = btr_pcur_get_btr_cur(pcur)->index;
+ index = pcur->index();
ut_a(index == foreign->foreign_index);
@@ -1129,9 +1137,14 @@ row_ins_foreign_check_on_constraint(
ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec,
tmp_heap);
- btr_pcur_open_with_no_init(clust_index, ref,
- PAGE_CUR_LE, BTR_SEARCH_LEAF,
- cascade->pcur, mtr);
+ cascade->pcur->old_rec = nullptr;
+ cascade->pcur->btr_cur.page_cur.index = clust_index;
+ err = btr_pcur_open_with_no_init(ref,
+ PAGE_CUR_LE, BTR_SEARCH_LEAF,
+ cascade->pcur, mtr);
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
+ goto nonstandard_exit_func;
+ }
clust_rec = btr_pcur_get_rec(cascade->pcur);
clust_block = btr_pcur_get_block(cascade->pcur);
@@ -1161,7 +1174,7 @@ row_ins_foreign_check_on_constraint(
/* Set an X-lock on the row to delete or update in the child table */
- err = lock_table(0, table, LOCK_IX, thr);
+ err = lock_table(table, fktable, LOCK_IX, thr);
if (err == DB_SUCCESS) {
/* Here it suffices to use a LOCK_REC_NOT_GAP type lock;
@@ -1338,21 +1351,14 @@ row_ins_foreign_check_on_constraint(
err = row_update_cascade_for_mysql(thr, cascade,
foreign->foreign_table);
- /* Release the data dictionary latch for a while, so that we do not
- starve other threads from doing CREATE TABLE etc. if we have a huge
- cascaded operation running. */
-
- row_mysql_unfreeze_data_dictionary(thr_get_trx(thr));
-
- DEBUG_SYNC_C("innodb_dml_cascade_dict_unfreeze");
-
- row_mysql_freeze_data_dictionary(thr_get_trx(thr));
-
mtr_start(mtr);
/* Restore pcur position */
- btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
+ if (pcur->restore_position(BTR_SEARCH_LEAF, mtr)
+ != btr_pcur_t::SAME_ALL) {
+ err = DB_CORRUPTION;
+ }
if (tmp_heap) {
mem_heap_free(tmp_heap);
@@ -1371,7 +1377,10 @@ nonstandard_exit_func:
mtr_commit(mtr);
mtr_start(mtr);
- btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
+ if (pcur->restore_position(BTR_SEARCH_LEAF, mtr)
+ != btr_pcur_t::SAME_ALL && err == DB_SUCCESS) {
+ err = DB_CORRUPTION;
+ }
DBUG_RETURN(err);
}
@@ -1457,10 +1466,7 @@ row_ins_check_foreign_constraint(
dtuple_t* entry, /*!< in: index entry for index */
que_thr_t* thr) /*!< in: query thread */
{
- dberr_t err;
upd_node_t* upd_node;
- dict_table_t* check_table;
- dict_index_t* check_index;
ulint n_fields_cmp;
btr_pcur_t pcur;
int cmp;
@@ -1482,14 +1488,10 @@ row_ins_check_foreign_constraint(
upd_node= NULL;
#endif /* WITH_WSREP */
- ut_ad(rw_lock_own(&dict_sys.latch, RW_LOCK_S));
-
- err = DB_SUCCESS;
-
- if (trx->check_foreigns == FALSE) {
+ if (!trx->check_foreigns) {
/* The user has suppressed foreign key checks currently for
this session */
- goto exit_func;
+ DBUG_RETURN(DB_SUCCESS);
}
/* If any of the foreign key fields in entry is SQL NULL, we
@@ -1498,12 +1500,12 @@ row_ins_check_foreign_constraint(
for (ulint i = 0; i < entry->n_fields; i++) {
dfield_t* field = dtuple_get_nth_field(entry, i);
if (i < foreign->n_fields && dfield_is_null(field)) {
- goto exit_func;
+ DBUG_RETURN(DB_SUCCESS);
}
/* System Versioning: if row_end != Inf, we
suppress the foreign key check */
if (field->type.vers_sys_end() && field->vers_history_row()) {
- goto exit_func;
+ DBUG_RETURN(DB_SUCCESS);
}
}
@@ -1528,7 +1530,7 @@ row_ins_check_foreign_constraint(
another, and the user has problems predicting in
which order they are performed. */
- goto exit_func;
+ DBUG_RETURN(DB_SUCCESS);
}
}
@@ -1540,23 +1542,32 @@ row_ins_check_foreign_constraint(
dfield_t* row_end = dtuple_get_nth_field(
insert_node->row, table->vers_end);
if (row_end->vers_history_row()) {
- goto exit_func;
+ DBUG_RETURN(DB_SUCCESS);
}
}
}
- if (check_ref) {
- check_table = foreign->referenced_table;
- check_index = foreign->referenced_index;
- } else {
- check_table = foreign->foreign_table;
- check_index = foreign->foreign_index;
+ dict_table_t *check_table;
+ dict_index_t *check_index;
+ dberr_t err = DB_SUCCESS;
+
+ {
+ dict_table_t*& fktable = check_ref
+ ? foreign->referenced_table : foreign->foreign_table;
+ check_table = fktable;
+ if (check_table) {
+ err = lock_table(check_table, &fktable, LOCK_IS, thr);
+ if (err != DB_SUCCESS) {
+ goto do_possible_lock_wait;
+ }
+ }
+ check_table = fktable;
}
- if (check_table == NULL
- || !check_table->is_readable()
- || check_index == NULL) {
+ check_index = check_ref
+ ? foreign->referenced_index : foreign->foreign_index;
+ if (!check_table || !check_table->is_readable() || !check_index) {
FILE* ef = dict_foreign_err_file;
std::string fk_str;
@@ -1601,22 +1612,10 @@ row_ins_check_foreign_constraint(
err = DB_ROW_IS_REFERENCED;
}
- mutex_exit(&dict_foreign_err_mutex);
+ mysql_mutex_unlock(&dict_foreign_err_mutex);
goto exit_func;
}
- if (check_table != table) {
- /* We already have a LOCK_IX on table, but not necessarily
- on check_table */
-
- err = lock_table(0, check_table, LOCK_IS, thr);
-
- if (err != DB_SUCCESS) {
-
- goto do_possible_lock_wait;
- }
- }
-
mtr_start(&mtr);
/* Store old value on n_fields_cmp */
@@ -1624,9 +1623,11 @@ row_ins_check_foreign_constraint(
n_fields_cmp = dtuple_get_n_fields_cmp(entry);
dtuple_set_n_fields_cmp(entry, foreign->n_fields);
-
- btr_pcur_open(check_index, entry, PAGE_CUR_GE,
- BTR_SEARCH_LEAF, &pcur, &mtr);
+ pcur.btr_cur.page_cur.index = check_index;
+ err = btr_pcur_open(entry, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr);
+ if (UNIV_UNLIKELY(err != DB_SUCCESS)) {
+ goto end_scan;
+ }
/* Scan index records and check if there is a matching record */
@@ -1812,9 +1813,8 @@ row_ins_check_foreign_constraint(
}
end_scan:
- btr_pcur_close(&pcur);
-
mtr_commit(&mtr);
+ ut_free(pcur.old_rec_buf);
/* Restore old value */
dtuple_set_n_fields_cmp(entry, n_fields_cmp);
@@ -1823,29 +1823,19 @@ do_possible_lock_wait:
if (err == DB_LOCK_WAIT) {
trx->error_state = err;
- que_thr_stop_for_mysql(thr);
-
thr->lock_state = QUE_THR_LOCK_ROW;
- check_table->inc_fk_checks();
-
- lock_wait_suspend_thread(thr);
+ err = lock_wait(thr);
thr->lock_state = QUE_THR_LOCK_NOLOCK;
- err = trx->error_state;
- if (err != DB_SUCCESS) {
- } else if (check_table->to_be_dropped) {
- err = DB_LOCK_WAIT_TIMEOUT;
- } else {
+ if (err == DB_SUCCESS) {
err = DB_LOCK_WAIT;
}
-
- check_table->dec_fk_checks();
}
exit_func:
- if (heap != NULL) {
+ if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@@ -1910,14 +1900,10 @@ row_ins_check_foreign_constraints(
{
dict_foreign_t* foreign;
dberr_t err = DB_SUCCESS;
- trx_t* trx;
- ibool got_s_lock = FALSE;
mem_heap_t* heap = NULL;
DBUG_ASSERT(index->is_primary() == pk);
- trx = thr_get_trx(thr);
-
DEBUG_SYNC_C_IF_THD(thr_get_trx(thr)->mysql_thd,
"foreign_constraint_check_for_ins");
@@ -1960,37 +1946,14 @@ row_ins_check_foreign_constraints(
ref_table = dict_table_open_on_name(
foreign->referenced_table_name_lookup,
- FALSE, FALSE, DICT_ERR_IGNORE_NONE);
- }
-
- if (0 == trx->dict_operation_lock_mode) {
- got_s_lock = TRUE;
-
- row_mysql_freeze_data_dictionary(trx);
+ false, DICT_ERR_IGNORE_NONE);
}
- if (referenced_table) {
- foreign->foreign_table->inc_fk_checks();
- }
-
- /* NOTE that if the thread ends up waiting for a lock
- we will release dict_sys.latch temporarily!
- But the counter on the table protects the referenced
- table from being dropped while the check is running. */
-
err = row_ins_check_foreign_constraint(
TRUE, foreign, table, ref_tuple, thr);
- if (referenced_table) {
- foreign->foreign_table->dec_fk_checks();
- }
-
- if (got_s_lock) {
- row_mysql_unfreeze_data_dictionary(trx);
- }
-
- if (ref_table != NULL) {
- dict_table_close(ref_table, FALSE, FALSE);
+ if (ref_table) {
+ dict_table_close(ref_table);
}
}
}
@@ -2118,7 +2081,6 @@ row_ins_scan_sec_index_for_duplicate(
dict_index_t* index, /*!< in: non-clustered unique index */
dtuple_t* entry, /*!< in: index entry */
que_thr_t* thr, /*!< in: query thread */
- bool s_latch,/*!< in: whether index->lock is being held */
mtr_t* mtr, /*!< in/out: mini-transaction */
mem_heap_t* offsets_heap)
/*!< in/out: memory heap that can be emptied */
@@ -2127,15 +2089,13 @@ row_ins_scan_sec_index_for_duplicate(
int cmp;
ulint n_fields_cmp;
btr_pcur_t pcur;
- dberr_t err = DB_SUCCESS;
rec_offs offsets_[REC_OFFS_SEC_INDEX_SIZE];
rec_offs* offsets = offsets_;
DBUG_ENTER("row_ins_scan_sec_index_for_duplicate");
rec_offs_init(offsets_);
- ut_ad(s_latch == rw_lock_own_flagged(
- &index->lock, RW_LOCK_FLAG_S | RW_LOCK_FLAG_SX));
+ ut_ad(!index->lock.have_any());
n_unique = dict_index_get_n_unique(index);
@@ -2158,14 +2118,13 @@ row_ins_scan_sec_index_for_duplicate(
n_fields_cmp = dtuple_get_n_fields_cmp(entry);
dtuple_set_n_fields_cmp(entry, n_unique);
-
- btr_pcur_open(index, entry, PAGE_CUR_GE,
- s_latch
- ? BTR_SEARCH_LEAF_ALREADY_S_LATCHED
- : BTR_SEARCH_LEAF,
- &pcur, mtr);
-
+ pcur.btr_cur.page_cur.index = index;
trx_t* const trx = thr_get_trx(thr);
+ dberr_t err = btr_pcur_open(entry, PAGE_CUR_GE, BTR_SEARCH_LEAF,
+ &pcur, mtr);
+ if (err != DB_SUCCESS) {
+ goto end_scan;
+ }
/* Scan index records and check if there is a duplicate */
@@ -2323,11 +2282,11 @@ row_ins_duplicate_error_in_clust_online(
dberr_t err = DB_SUCCESS;
const rec_t* rec = btr_cur_get_rec(cursor);
- ut_ad(!cursor->index->is_instant());
+ ut_ad(!cursor->index()->is_instant());
if (cursor->low_match >= n_uniq && !page_rec_is_infimum(rec)) {
- *offsets = rec_get_offsets(rec, cursor->index, *offsets,
- cursor->index->n_fields,
+ *offsets = rec_get_offsets(rec, cursor->index(), *offsets,
+ cursor->index()->n_fields,
ULINT_UNDEFINED, heap);
err = row_ins_duplicate_online(n_uniq, entry, rec, *offsets);
if (err != DB_SUCCESS) {
@@ -2335,11 +2294,13 @@ row_ins_duplicate_error_in_clust_online(
}
}
- rec = page_rec_get_next_const(btr_cur_get_rec(cursor));
+ if (!(rec = page_rec_get_next_const(btr_cur_get_rec(cursor)))) {
+ return DB_CORRUPTION;
+ }
if (cursor->up_match >= n_uniq && !page_rec_is_supremum(rec)) {
- *offsets = rec_get_offsets(rec, cursor->index, *offsets,
- cursor->index->n_fields,
+ *offsets = rec_get_offsets(rec, cursor->index(), *offsets,
+ cursor->index()->n_fields,
ULINT_UNDEFINED, heap);
err = row_ins_duplicate_online(n_uniq, entry, rec, *offsets);
}
@@ -2372,7 +2333,7 @@ row_ins_duplicate_error_in_clust(
rec_offs* offsets = offsets_;
rec_offs_init(offsets_);
- ut_ad(dict_index_is_clust(cursor->index));
+ ut_ad(cursor->index()->is_clust());
/* NOTE: For unique non-clustered indexes there may be any number
of delete marked records with the same value for the non-clustered
@@ -2387,15 +2348,17 @@ row_ins_duplicate_error_in_clust(
user records on the leaf level. So, even if low_match would suggest
that a duplicate key violation may occur, this may not be the case. */
- n_unique = dict_index_get_n_unique(cursor->index);
+ n_unique = dict_index_get_n_unique(cursor->index());
if (cursor->low_match >= n_unique) {
rec = btr_cur_get_rec(cursor);
if (!page_rec_is_infimum(rec)) {
- offsets = rec_get_offsets(rec, cursor->index, offsets,
- cursor->index->n_core_fields,
+ offsets = rec_get_offsets(rec, cursor->index(),
+ offsets,
+ cursor->index()
+ ->n_core_fields,
ULINT_UNDEFINED, &heap);
/* We set a lock on the possible duplicate: this
@@ -2416,13 +2379,13 @@ row_ins_duplicate_error_in_clust(
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor),
- rec, cursor->index, offsets, thr);
+ rec, cursor->index(), offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor), rec,
- cursor->index, offsets, thr);
+ cursor->index(), offsets, thr);
}
switch (err) {
@@ -2434,11 +2397,11 @@ row_ins_duplicate_error_in_clust(
}
if (row_ins_dupl_error_with_rec(
- rec, entry, cursor->index, offsets)) {
+ rec, entry, cursor->index(), offsets)) {
duplicate:
- trx->error_info = cursor->index;
+ trx->error_info = cursor->index();
err = DB_DUPLICATE_KEY;
- if (cursor->index->table->versioned()
+ if (cursor->index()->table->versioned()
&& entry->vers_history_row())
{
ulint trx_id_len;
@@ -2455,13 +2418,17 @@ duplicate:
}
}
+ err = DB_SUCCESS;
+
if (cursor->up_match >= n_unique) {
rec = page_rec_get_next(btr_cur_get_rec(cursor));
- if (!page_rec_is_supremum(rec)) {
- offsets = rec_get_offsets(rec, cursor->index, offsets,
- cursor->index->n_core_fields,
+ if (rec && !page_rec_is_supremum(rec)) {
+ offsets = rec_get_offsets(rec, cursor->index(),
+ offsets,
+ cursor->index()
+ ->n_core_fields,
ULINT_UNDEFINED, &heap);
if (trx->duplicates) {
@@ -2474,34 +2441,33 @@ duplicate:
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor),
- rec, cursor->index, offsets, thr);
+ rec, cursor->index(), offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,
btr_cur_get_block(cursor),
- rec, cursor->index, offsets, thr);
+ rec, cursor->index(), offsets, thr);
}
switch (err) {
+ default:
+ break;
case DB_SUCCESS_LOCKED_REC:
+ err = DB_SUCCESS;
+ /* fall through */
case DB_SUCCESS:
- break;
- default:
- goto func_exit;
- }
-
- if (row_ins_dupl_error_with_rec(
- rec, entry, cursor->index, offsets)) {
- goto duplicate;
+ if (row_ins_dupl_error_with_rec(
+ rec, entry, cursor->index(),
+ offsets)) {
+ goto duplicate;
+ }
}
}
/* This should never happen */
- ut_error;
+ err = DB_CORRUPTION;
}
-
- err = DB_SUCCESS;
func_exit:
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
@@ -2534,7 +2500,7 @@ row_ins_must_modify_rec(
and a secondary index node pointer contains all index fields. */
return(cursor->low_match
- >= dict_index_get_n_unique_in_tree(cursor->index)
+ >= dict_index_get_n_unique_in_tree(cursor->index())
&& !page_rec_is_infimum(btr_cur_get_rec(cursor)));
}
@@ -2562,9 +2528,9 @@ row_ins_index_entry_big_rec(
mtr_t mtr;
btr_pcur_t pcur;
rec_t* rec;
- dberr_t error;
- ut_ad(dict_index_is_clust(index));
+ pcur.btr_cur.page_cur.index = index;
+ ut_ad(index->is_primary());
DEBUG_SYNC_C_IF_THD(thd, "before_row_ins_extern_latch");
@@ -2575,8 +2541,12 @@ row_ins_index_entry_big_rec(
index->set_modified(mtr);
}
- btr_pcur_open(index, entry, PAGE_CUR_LE, BTR_MODIFY_TREE,
- &pcur, &mtr);
+ dberr_t error = btr_pcur_open(entry, PAGE_CUR_LE, BTR_MODIFY_TREE,
+ &pcur, &mtr);
+ if (error != DB_SUCCESS) {
+ return error;
+ }
+
rec = btr_pcur_get_rec(&pcur);
offsets = rec_get_offsets(rec, index, offsets, index->n_core_fields,
ULINT_UNDEFINED, heap);
@@ -2586,18 +2556,25 @@ row_ins_index_entry_big_rec(
&pcur, offsets, big_rec, &mtr, BTR_STORE_INSERT);
DEBUG_SYNC_C_IF_THD(thd, "after_row_ins_extern");
- if (error == DB_SUCCESS
- && dict_index_is_online_ddl(index)) {
- row_log_table_insert(btr_pcur_get_rec(&pcur), index, offsets);
- }
-
mtr.commit();
- btr_pcur_close(&pcur);
-
+ ut_free(pcur.old_rec_buf);
return(error);
}
+#if 0
+extern "C" int thd_is_slave(const MYSQL_THD thd);
+#else
+# define thd_is_slave(thd) 0
+#endif
+
+#if defined __aarch64__&&defined __GNUC__&&__GNUC__==4&&!defined __clang__
+/* Avoid GCC 4.8.5 internal compiler error due to srw_mutex::wr_unlock().
+We would only need this for row_ins_clust_index_entry_low(),
+but GCC 4.8.5 does not support pop_options. */
+# pragma GCC optimize ("O0")
+#endif
+
/***************************************************************//**
Tries to insert an entry into a clustered index, ignoring foreign key
constraints. If a record with the same unique key is found, the other
@@ -2613,7 +2590,7 @@ dberr_t
row_ins_clust_index_entry_low(
/*==========================*/
ulint flags, /*!< in: undo logging and locking flags */
- ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
+ btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /*!< in: clustered index */
@@ -2623,15 +2600,16 @@ row_ins_clust_index_entry_low(
que_thr_t* thr) /*!< in: query thread */
{
btr_pcur_t pcur;
- btr_cur_t* cursor;
dberr_t err = DB_SUCCESS;
big_rec_t* big_rec = NULL;
mtr_t mtr;
- ib_uint64_t auto_inc = 0;
+ uint64_t auto_inc = 0;
mem_heap_t* offsets_heap = NULL;
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");
@@ -2639,9 +2617,9 @@ row_ins_clust_index_entry_low(
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);
- mtr_start(&mtr);
+ mtr.start();
if (index->table->is_temporary()) {
/* Disable REDO logging as the lifetime of temp-tables is
@@ -2664,7 +2642,7 @@ row_ins_clust_index_entry_low(
} else {
if (mode == BTR_MODIFY_LEAF
&& dict_index_is_online_ddl(index)) {
- mode = BTR_MODIFY_LEAF_ALREADY_S_LATCHED;
+ mode = BTR_MODIFY_LEAF_ALREADY_LATCHED;
mtr_s_lock_index(index, &mtr);
}
@@ -2681,6 +2659,13 @@ row_ins_clust_index_entry_low(
dfield->type.mtype,
dfield->type.prtype
& DATA_UNSIGNED);
+ if (auto_inc
+ && mode != BTR_MODIFY_TREE) {
+ mode = btr_latch_mode(
+ BTR_MODIFY_ROOT_AND_LEAF
+ ^ BTR_MODIFY_LEAF
+ ^ mode);
+ }
}
}
}
@@ -2689,20 +2674,27 @@ row_ins_clust_index_entry_low(
/* Note that we use PAGE_CUR_LE as the search mode, because then
the function will return in both low_match and up_match of the
cursor sensible values */
- err = btr_pcur_open_low(index, 0, entry, PAGE_CUR_LE, mode, &pcur,
- __FILE__, __LINE__, auto_inc, &mtr);
+ pcur.btr_cur.page_cur.index = index;
+ err = btr_pcur_open(entry, PAGE_CUR_LE, mode, &pcur, &mtr);
if (err != DB_SUCCESS) {
index->table->file_unreadable = true;
+err_exit:
mtr.commit();
goto func_exit;
}
- cursor = btr_pcur_get_btr_cur(&pcur);
- cursor->thr = thr;
+ if (auto_inc) {
+ buf_block_t* root
+ = mtr.at_savepoint(mode != BTR_MODIFY_ROOT_AND_LEAF);
+ ut_ad(index->page == root->page.id().page_no());
+ page_set_autoinc(root, auto_inc, &mtr, false);
+ }
+
+ btr_pcur_get_btr_cur(&pcur)->thr = thr;
#ifdef UNIV_DEBUG
{
- page_t* page = btr_cur_get_page(cursor);
+ page_t* page = btr_pcur_get_page(&pcur);
rec_t* first_rec = page_rec_get_next(
page_get_infimum_rec(page));
@@ -2711,31 +2703,91 @@ row_ins_clust_index_entry_low(
}
#endif /* UNIV_DEBUG */
+ block = btr_pcur_get_block(&pcur);
+
+ DBUG_EXECUTE_IF("row_ins_row_level", goto skip_bulk_insert;);
+
+ if (!(flags & BTR_NO_UNDO_LOG_FLAG)
+ && page_is_empty(block->page.frame)
+ && !entry->is_metadata() && !trx->duplicates
+ && !trx->check_unique_secondary && !trx->check_foreigns
+ && !trx->dict_operation
+ && block->page.id().page_no() == index->page
+ && !index->table->skip_alter_undo
+ && !index->table->n_rec_locks
+ && !index->table->is_active_ddl()
+ && !index->table->versioned()
+ && !thd_is_slave(trx->mysql_thd) /* FIXME: MDEV-24622 */) {
+ DEBUG_SYNC_C("empty_root_page_insert");
+
+ if (!index->table->is_temporary()) {
+ err = lock_table(index->table, NULL, LOCK_X, thr);
+
+ if (err != DB_SUCCESS) {
+ trx->error_state = err;
+ goto err_exit;
+ }
+
+ if (index->table->n_rec_locks) {
+ goto skip_bulk_insert;
+ }
+
+#if 0
+ if (trx->is_wsrep())
+ {
+ if (!wsrep_thd_is_local_transaction(trx->mysql_thd))
+ goto skip_bulk_insert;
+ if (wsrep_append_table_key(trx->mysql_thd, *index->table))
+ {
+ trx->error_state = DB_ROLLBACK;
+ goto err_exit;
+ }
+ }
+#endif /* WITH_WSREP */
+
+#ifdef BTR_CUR_HASH_ADAPT
+ if (btr_search_enabled) {
+ btr_search_x_lock_all();
+ index->table->bulk_trx_id = trx->id;
+ btr_search_x_unlock_all();
+ } else {
+ index->table->bulk_trx_id = trx->id;
+ }
+#else /* BTR_CUR_HASH_ADAPT */
+ index->table->bulk_trx_id = trx->id;
+#endif /* BTR_CUR_HASH_ADAPT */
+ }
+
+ trx->bulk_insert = true;
+ }
+
+skip_bulk_insert:
if (UNIV_UNLIKELY(entry->info_bits != 0)) {
ut_ad(entry->is_metadata());
ut_ad(flags == BTR_NO_LOCKING_FLAG);
ut_ad(index->is_instant());
ut_ad(!dict_index_is_online_ddl(index));
- const rec_t* rec = btr_cur_get_rec(cursor);
+ const rec_t* rec = btr_pcur_get_rec(&pcur);
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;
}
- ut_ad(!row_ins_must_modify_rec(cursor));
+ ut_ad(!row_ins_must_modify_rec(&pcur.btr_cur));
goto do_insert;
}
- if (rec_is_metadata(btr_cur_get_rec(cursor), *index)) {
+ if (rec_is_metadata(btr_pcur_get_rec(&pcur), *index)) {
goto do_insert;
}
if (n_uniq
- && (cursor->up_match >= n_uniq || cursor->low_match >= n_uniq)) {
+ && (pcur.btr_cur.up_match >= n_uniq
+ || pcur.btr_cur.low_match >= n_uniq)) {
if (flags
== (BTR_CREATE_FLAG | BTR_NO_LOCKING_FLAG
@@ -2743,7 +2795,7 @@ row_ins_clust_index_entry_low(
/* Set no locks when applying log
in online table rebuild. Only check for duplicates. */
err = row_ins_duplicate_error_in_clust_online(
- n_uniq, entry, cursor,
+ n_uniq, entry, &pcur.btr_cur,
&offsets, &offsets_heap);
switch (err) {
@@ -2754,26 +2806,24 @@ 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 = index;
}
} else {
/* Note that the following may return also
DB_LOCK_WAIT */
err = row_ins_duplicate_error_in_clust(
- flags, cursor, entry, thr);
+ flags, &pcur.btr_cur, entry, thr);
}
if (err != DB_SUCCESS) {
-err_exit:
- mtr_commit(&mtr);
- goto func_exit;
+ goto err_exit;
}
}
/* Note: Allowing duplicates would qualify for modification of
an existing record as the new entry is exactly same as old entry. */
- if (row_ins_must_modify_rec(cursor)) {
+ if (row_ins_must_modify_rec(&pcur.btr_cur)) {
/* There is already an index entry with a long enough common
prefix, we must convert the insert into a modify of an
existing record */
@@ -2783,11 +2833,6 @@ err_exit:
&pcur, flags, mode, &offsets, &offsets_heap,
entry_heap, entry, thr, &mtr);
- if (err == DB_SUCCESS && dict_index_is_online_ddl(index)) {
- row_log_table_insert(btr_cur_get_rec(cursor),
- index, offsets);
- }
-
mtr_commit(&mtr);
mem_heap_free(entry_heap);
} else {
@@ -2796,10 +2841,13 @@ do_insert:
rec_t* insert_rec;
if (mode != BTR_MODIFY_TREE) {
- ut_ad((mode & ulint(~BTR_ALREADY_S_LATCHED))
- == BTR_MODIFY_LEAF);
+ ut_ad(mode == BTR_MODIFY_LEAF
+ || mode == BTR_MODIFY_LEAF_ALREADY_LATCHED
+ || mode == BTR_MODIFY_ROOT_AND_LEAF
+ || mode
+ == BTR_MODIFY_ROOT_AND_LEAF_ALREADY_LATCHED);
err = btr_cur_optimistic_insert(
- flags, cursor, &offsets, &offsets_heap,
+ flags, &pcur.btr_cur, &offsets, &offsets_heap,
entry, &insert_rec, &big_rec,
n_ext, thr, &mtr);
} else {
@@ -2808,26 +2856,24 @@ do_insert:
goto err_exit;
}
- DEBUG_SYNC_C("before_insert_pessimitic_row_ins_clust");
-
err = btr_cur_optimistic_insert(
- flags, cursor,
+ flags, &pcur.btr_cur,
&offsets, &offsets_heap,
entry, &insert_rec, &big_rec,
n_ext, thr, &mtr);
if (err == DB_FAIL) {
err = btr_cur_pessimistic_insert(
- flags, cursor,
+ flags, &pcur.btr_cur,
&offsets, &offsets_heap,
entry, &insert_rec, &big_rec,
n_ext, thr, &mtr);
}
}
- if (big_rec != NULL) {
- mtr_commit(&mtr);
+ mtr.commit();
+ if (big_rec) {
/* Online table rebuild could read (and
ignore) the incomplete record at this point.
If online rebuild is in progress, the
@@ -2838,16 +2884,8 @@ 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
- && dict_index_is_online_ddl(index)) {
- row_log_table_insert(
- insert_rec, index, offsets);
- }
-
- mtr_commit(&mtr);
}
}
@@ -2856,24 +2894,14 @@ func_exit:
mem_heap_free(offsets_heap);
}
- btr_pcur_close(&pcur);
-
+ ut_free(pcur.old_rec_buf);
DBUG_RETURN(err);
}
-/** Start a mini-transaction and check if the index will be dropped.
+/** Start a mini-transaction.
@param[in,out] mtr mini-transaction
-@param[in,out] index secondary index
-@param[in] check whether to check
-@param[in] search_mode flags
-@return true if the index is to be dropped */
-static MY_ATTRIBUTE((warn_unused_result))
-bool
-row_ins_sec_mtr_start_and_check_if_aborted(
- mtr_t* mtr,
- dict_index_t* index,
- bool check,
- ulint search_mode)
+@param[in,out] index secondary index */
+static void row_ins_sec_mtr_start(mtr_t *mtr, dict_index_t *index)
{
ut_ad(!dict_index_is_clust(index));
ut_ad(mtr->is_named_space(index->table->space));
@@ -2883,30 +2911,6 @@ row_ins_sec_mtr_start_and_check_if_aborted(
mtr->start();
index->set_modified(*mtr);
mtr->set_log_mode(log_mode);
-
- if (!check) {
- return(false);
- }
-
- if (search_mode & BTR_ALREADY_S_LATCHED) {
- mtr_s_lock_index(index, mtr);
- } else {
- mtr_sx_lock_index(index, mtr);
- }
-
- switch (index->online_status) {
- case ONLINE_INDEX_ABORTED:
- case ONLINE_INDEX_ABORTED_DROPPED:
- ut_ad(!index->is_committed());
- return(true);
- case ONLINE_INDEX_COMPLETE:
- return(false);
- case ONLINE_INDEX_CREATION:
- break;
- }
-
- ut_error;
- return(true);
}
/***************************************************************//**
@@ -2915,13 +2919,13 @@ same fields is found, the other record is necessarily marked deleted.
It is then unmarked. Otherwise, the entry is just inserted to the index.
@retval DB_SUCCESS on success
@retval DB_LOCK_WAIT on lock wait when !(flags & BTR_NO_LOCKING_FLAG)
-@retval DB_FAIL if retry with BTR_MODIFY_TREE is needed
+@retval DB_FAIL if retry with BTR_INSERT_TREE is needed
@return error code */
dberr_t
row_ins_sec_index_entry_low(
/*========================*/
ulint flags, /*!< in: undo logging and locking flags */
- ulint mode, /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,
+ btr_latch_mode mode, /*!< in: BTR_MODIFY_LEAF or BTR_INSERT_TREE,
depending on whether we wish optimistic or
pessimistic descent down the index tree */
dict_index_t* index, /*!< in: secondary index */
@@ -2936,8 +2940,8 @@ row_ins_sec_index_entry_low(
DBUG_ENTER("row_ins_sec_index_entry_low");
btr_cur_t cursor;
- ulint search_mode = mode;
- dberr_t err = DB_SUCCESS;
+ btr_latch_mode search_mode = mode;
+ dberr_t err;
ulint n_unique;
mtr_t mtr;
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
@@ -2946,10 +2950,11 @@ row_ins_sec_index_entry_low(
rtr_info_t rtr_info;
ut_ad(!dict_index_is_clust(index));
- ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_MODIFY_TREE);
+ ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_INSERT_TREE);
cursor.thr = thr;
cursor.rtr_info = NULL;
+ cursor.page_cur.index = index;
ut_ad(thr_get_trx(thr)->id != 0);
mtr.start();
@@ -2961,53 +2966,22 @@ row_ins_sec_index_entry_low(
mtr.set_log_mode(MTR_LOG_NO_REDO);
} else {
index->set_modified(mtr);
- if (!dict_index_is_spatial(index)) {
- search_mode |= BTR_INSERT;
- }
- }
-
- /* Ensure that we acquire index->lock when inserting into an
- index with index->online_status == ONLINE_INDEX_COMPLETE, but
- could still be subject to rollback_inplace_alter_table().
- This prevents a concurrent change of index->online_status.
- The memory object cannot be freed as long as we have an open
- reference to the table, or index->table->n_ref_count > 0. */
- const bool check = !index->is_committed();
- if (check) {
- DEBUG_SYNC_C("row_ins_sec_index_enter");
- if (mode == BTR_MODIFY_LEAF) {
- search_mode |= BTR_ALREADY_S_LATCHED;
- mtr_s_lock_index(index, &mtr);
- } else {
- mtr_sx_lock_index(index, &mtr);
- }
-
- if (row_log_online_op_try(
- index, entry, thr_get_trx(thr)->id)) {
- goto func_exit;
- }
}
/* Note that we use PAGE_CUR_LE as the search mode, because then
the function will return in both low_match and up_match of the
cursor sensible values */
- if (!thr_get_trx(thr)->check_unique_secondary) {
- search_mode |= BTR_IGNORE_SEC_UNIQUE;
- }
-
- if (dict_index_is_spatial(index)) {
- cursor.index = index;
+ if (index->is_spatial()) {
rtr_init_rtr_info(&rtr_info, false, &cursor, index, false);
rtr_info_update_btr(&cursor, &rtr_info);
- err = btr_cur_search_to_nth_level(
- index, 0, entry, PAGE_CUR_RTREE_INSERT,
- search_mode,
- &cursor, __FILE__, __LINE__, &mtr);
+ err = rtr_insert_leaf(&cursor, entry, search_mode, &mtr);
- if (mode == BTR_MODIFY_LEAF && rtr_info.mbr_adj) {
+ if (err == DB_SUCCESS && search_mode == BTR_MODIFY_LEAF
+ && rtr_info.mbr_adj) {
mtr_commit(&mtr);
+ search_mode = mode = BTR_MODIFY_TREE;
rtr_clean_rtr_info(&rtr_info, true);
rtr_init_rtr_info(&rtr_info, false, &cursor,
index, false);
@@ -3018,13 +2992,8 @@ row_ins_sec_index_entry_low(
} else {
index->set_modified(mtr);
}
- search_mode &= ulint(~BTR_MODIFY_LEAF);
- search_mode |= BTR_MODIFY_TREE;
- err = btr_cur_search_to_nth_level(
- index, 0, entry, PAGE_CUR_RTREE_INSERT,
- search_mode,
- &cursor, __FILE__, __LINE__, &mtr);
- mode = BTR_MODIFY_TREE;
+ err = rtr_insert_leaf(&cursor, entry,
+ search_mode, &mtr);
}
DBUG_EXECUTE_IF(
@@ -3032,21 +3001,21 @@ row_ins_sec_index_entry_low(
goto func_exit;});
} else {
- err = btr_cur_search_to_nth_level(
- index, 0, entry, PAGE_CUR_LE,
- search_mode,
- &cursor, __FILE__, __LINE__, &mtr);
+ if (!index->table->is_temporary()) {
+ search_mode = btr_latch_mode(
+ search_mode
+ | (thr_get_trx(thr)->check_unique_secondary
+ ? BTR_INSERT | BTR_IGNORE_SEC_UNIQUE
+ : BTR_INSERT));
+ }
+
+ err = cursor.search_leaf(entry, PAGE_CUR_LE, search_mode,
+ &mtr);
}
if (err != DB_SUCCESS) {
if (err == DB_DECRYPTION_FAILED) {
- ib_push_warning(thr_get_trx(thr)->mysql_thd,
- DB_DECRYPTION_FAILED,
- "Table %s is encrypted but encryption service or"
- " used key_id is not available. "
- " Can't continue reading table.",
- index->table->name.m_name);
- index->table->file_unreadable = true;
+ btr_decryption_failed(*index);
}
goto func_exit;
}
@@ -3076,13 +3045,10 @@ row_ins_sec_index_entry_low(
DEBUG_SYNC_C("row_ins_sec_index_unique");
- if (row_ins_sec_mtr_start_and_check_if_aborted(
- &mtr, index, check, search_mode)) {
- goto func_exit;
- }
+ row_ins_sec_mtr_start(&mtr, index);
err = row_ins_scan_sec_index_for_duplicate(
- flags, index, entry, thr, check, &mtr, offsets_heap);
+ flags, index, entry, thr, &mtr, offsets_heap);
mtr_commit(&mtr);
@@ -3093,9 +3059,7 @@ row_ins_sec_index_entry_low(
if (!index->is_committed()) {
ut_ad(!thr_get_trx(thr)
->dict_operation_lock_mode);
- mutex_enter(&dict_sys.mutex);
- dict_set_corrupted_index_cache_only(index);
- mutex_exit(&dict_sys.mutex);
+ index->type |= DICT_CORRUPT;
/* Do not return any error to the
caller. The duplicate will be reported
by ALTER TABLE or CREATE UNIQUE INDEX.
@@ -3113,10 +3077,7 @@ row_ins_sec_index_entry_low(
DBUG_RETURN(err);
}
- if (row_ins_sec_mtr_start_and_check_if_aborted(
- &mtr, index, check, search_mode)) {
- goto func_exit;
- }
+ row_ins_sec_mtr_start(&mtr, index);
DEBUG_SYNC_C("row_ins_sec_index_entry_dup_locks_created");
@@ -3124,12 +3085,16 @@ row_ins_sec_index_entry_low(
locked with s-locks the necessary records to
prevent any insertion of a duplicate by another
transaction. Let us now reposition the cursor and
- continue the insertion. */
- btr_cur_search_to_nth_level(
- index, 0, entry, PAGE_CUR_LE,
- (search_mode
- & ~(BTR_INSERT | BTR_IGNORE_SEC_UNIQUE)),
- &cursor, __FILE__, __LINE__, &mtr);
+ continue the insertion (bypassing the change buffer). */
+ err = cursor.search_leaf(
+ entry, PAGE_CUR_LE,
+ btr_latch_mode(search_mode
+ & ~(BTR_INSERT
+ | BTR_IGNORE_SEC_UNIQUE)),
+ &mtr);
+ if (err != DB_SUCCESS) {
+ goto func_exit;
+ }
}
if (row_ins_must_modify_rec(&cursor)) {
@@ -3164,7 +3129,6 @@ row_ins_sec_index_entry_low(
err = rtr_ins_enlarge_mbr(&cursor, &mtr);
}
} else {
- ut_ad(mode == BTR_MODIFY_TREE);
if (buf_pool.running_out()) {
err = DB_LOCK_TABLE_FULL;
goto func_exit;
@@ -3367,7 +3331,7 @@ row_ins_sec_index_entry(
log_free_check();
err = row_ins_sec_index_entry_low(
- flags, BTR_MODIFY_TREE, index,
+ flags, BTR_INSERT_TREE, index,
offsets_heap, heap, entry, 0, thr);
}
@@ -3582,22 +3546,9 @@ row_ins_alloc_row_id_step(
/*======================*/
ins_node_t* node) /*!< in: row insert node */
{
- row_id_t row_id;
-
- ut_ad(node->state == INS_NODE_ALLOC_ROW_ID);
-
- if (dict_index_is_unique(dict_table_get_first_index(node->table))) {
-
- /* No row id is stored if the clustered index is unique */
-
- return;
- }
-
- /* Fill in row id value to row */
-
- row_id = dict_sys_get_new_row_id();
-
- dict_sys_write_row_id(node->sys_buf, row_id);
+ ut_ad(node->state == INS_NODE_ALLOC_ROW_ID);
+ if (dict_table_get_first_index(node->table)->is_gen_clust())
+ dict_sys_write_row_id(node->sys_buf, dict_sys.get_new_row_id());
}
/***********************************************************//**
@@ -3701,23 +3652,14 @@ row_ins(
ut_ad(node->state == INS_NODE_INSERT_ENTRIES);
- while (node->index != NULL) {
- if (!(node->index->type & DICT_FTS)) {
- dberr_t err = row_ins_index_entry_step(node, thr);
-
- if (err != DB_SUCCESS) {
- DBUG_RETURN(err);
- }
+ while (dict_index_t *index = node->index) {
+ if (index->type & (DICT_FTS | DICT_CORRUPT)
+ || !index->is_committed()) {
+ } else if (dberr_t err = row_ins_index_entry_step(node, thr)) {
+ DBUG_RETURN(err);
}
-
- node->index = dict_table_get_next_index(node->index);
+ node->index = dict_table_get_next_index(index);
++node->entry;
-
- /* Skip corrupted secondary index and its entry */
- while (node->index && node->index->is_corrupted()) {
- node->index = dict_table_get_next_index(node->index);
- ++node->entry;
- }
}
ut_ad(node->entry == node->entry_list.end());
@@ -3788,10 +3730,6 @@ row_ins_step(
goto do_insert;
}
- if (UNIV_LIKELY(!node->table->skip_alter_undo)) {
- trx_write_trx_id(&node->sys_buf[DATA_TRX_ID_LEN], trx->id);
- }
-
if (node->state == INS_NODE_SET_IX_LOCK) {
node->state = INS_NODE_ALLOC_ROW_ID;
@@ -3809,13 +3747,13 @@ row_ins_step(
goto same_trx;
}
- err = lock_table(0, node->table, LOCK_IX, thr);
+ err = lock_table(node->table, NULL, LOCK_IX, thr);
DBUG_EXECUTE_IF("ib_row_ins_ix_lock_wait",
err = DB_LOCK_WAIT;);
if (err != DB_SUCCESS) {
-
+ node->state = INS_NODE_SET_IX_LOCK;
goto error_handling;
}