mirror of
https://github.com/MariaDB/server.git
synced 2025-12-28 08:10:14 +00:00
Merge branch '10.7' into 10.8
# Conflicts: # storage/innobase/btr/btr0pcur.cc # storage/innobase/log/log0log.cc
This commit is contained in:
commit
eb25f47423
35
mysql-test/suite/innodb/r/cursor-restore-locking.result
Normal file
35
mysql-test/suite/innodb/r/cursor-restore-locking.result
Normal file
@ -0,0 +1,35 @@
|
||||
CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB;
|
||||
connect prevent_purge,localhost,root,,;
|
||||
start transaction with consistent snapshot;
|
||||
connect con_del_1,localhost,root,,;
|
||||
INSERT INTO t VALUES (20,20);
|
||||
SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont';
|
||||
DELETE FROM t WHERE b = 20;
|
||||
connect con_ins_1,localhost,root,,;
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished';
|
||||
SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL first_ins_locked';
|
||||
SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont';
|
||||
INSERT INTO t VALUES(10, 20);
|
||||
connect con_del_2,localhost,root,,;
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked';
|
||||
SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL second_del_locked';
|
||||
DELETE FROM t WHERE b = 20;
|
||||
connection default;
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR second_del_locked';
|
||||
SET DEBUG_SYNC = 'now SIGNAL first_del_cont';
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted';
|
||||
connection con_del_1;
|
||||
connection default;
|
||||
disconnect prevent_purge;
|
||||
InnoDB 0 transactions not purged
|
||||
SET DEBUG_SYNC = 'now SIGNAL first_ins_cont';
|
||||
connection con_del_2;
|
||||
connection con_ins_1;
|
||||
connection default;
|
||||
INSERT INTO t VALUES(30, 20);
|
||||
disconnect con_ins_1;
|
||||
disconnect con_del_1;
|
||||
disconnect con_del_2;
|
||||
connection default;
|
||||
SET DEBUG_SYNC = 'RESET';
|
||||
DROP TABLE t;
|
||||
79
mysql-test/suite/innodb/t/cursor-restore-locking.test
Normal file
79
mysql-test/suite/innodb/t/cursor-restore-locking.test
Normal file
@ -0,0 +1,79 @@
|
||||
--source include/have_innodb.inc
|
||||
--source include/count_sessions.inc
|
||||
source include/have_debug.inc;
|
||||
source include/have_debug_sync.inc;
|
||||
|
||||
CREATE TABLE t (a int PRIMARY KEY, b int NOT NULL UNIQUE) engine = InnoDB;
|
||||
|
||||
--connect(prevent_purge,localhost,root,,)
|
||||
start transaction with consistent snapshot;
|
||||
|
||||
--connect(con_del_1,localhost,root,,)
|
||||
INSERT INTO t VALUES (20,20);
|
||||
SET DEBUG_SYNC = 'innodb_row_search_for_mysql_exit SIGNAL first_del_row_search_mvcc_finished WAIT_FOR first_del_cont';
|
||||
--send DELETE FROM t WHERE b = 20
|
||||
|
||||
--connect(con_ins_1,localhost,root,,)
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR first_del_row_search_mvcc_finished';
|
||||
# It's supposed the following INSERT will be suspended just after
|
||||
# lock_wait_suspend_thread_enter syncpoint, and will be awaken
|
||||
# after the previous DELETE commits. ib_after_row_insert will be executed
|
||||
# after the INSERT is woken up. The previous DELETE will wait for
|
||||
# first_del_cont signal before commit, and this signal will be sent later.
|
||||
# So it's safe to use two signals in a row here, it's guaranted the first
|
||||
# signal will be received before the second signal is sent.
|
||||
SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL first_ins_locked';
|
||||
SET DEBUG_SYNC = 'ib_after_row_insert SIGNAL first_ins_row_inserted WAIT_FOR first_ins_cont';
|
||||
--send INSERT INTO t VALUES(10, 20)
|
||||
|
||||
--connect(con_del_2,localhost,root,,)
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_locked';
|
||||
SET DEBUG_SYNC = 'lock_wait_suspend_thread_enter SIGNAL second_del_locked';
|
||||
###############################################################################
|
||||
# This DELETE is locked by the previous DELETE, after that DELETE is
|
||||
# committed, it will still be locked by the next INSERT on delete-marked
|
||||
# heap_no 2 record. After that INSERT inserted the record with heap_no 3,
|
||||
# and after heap_no 2 record is purged, this DELETE will be unlocked and
|
||||
# must restore persistent cursor position at heap_no 3 record, as it has the
|
||||
# same secondary key value as former heap_no 2 record. Then it must be blocked
|
||||
# by the previous INSERT, and after the INSERT is committed, it must
|
||||
# delete the record, inserted by the previous INSERT, and the last INSERT(see
|
||||
# below) must be finished without error. But instead this DELETE restores
|
||||
# persistent cursor position to supremum, as a result, it does not delete the
|
||||
# record, inserted by the previous INSERT, and the last INSERT is finished with
|
||||
# duplicate key check error.
|
||||
###############################################################################
|
||||
--send DELETE FROM t WHERE b = 20
|
||||
|
||||
--connection default
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR second_del_locked';
|
||||
SET DEBUG_SYNC = 'now SIGNAL first_del_cont';
|
||||
SET DEBUG_SYNC = 'now WAIT_FOR first_ins_row_inserted';
|
||||
--connection con_del_1
|
||||
--reap
|
||||
|
||||
--connection default
|
||||
--disconnect prevent_purge
|
||||
--source include/wait_all_purged.inc
|
||||
SET DEBUG_SYNC = 'now SIGNAL first_ins_cont';
|
||||
|
||||
--connection con_del_2
|
||||
--reap
|
||||
|
||||
--connection con_ins_1
|
||||
--reap
|
||||
|
||||
--connection default
|
||||
###############################################################################
|
||||
# Duplicate key error is expected if the bug is not fixed.
|
||||
###############################################################################
|
||||
INSERT INTO t VALUES(30, 20);
|
||||
|
||||
--disconnect con_ins_1
|
||||
--disconnect con_del_1
|
||||
--disconnect con_del_2
|
||||
--connection default
|
||||
|
||||
SET DEBUG_SYNC = 'RESET';
|
||||
DROP TABLE t;
|
||||
--source include/wait_until_count_sessions.inc
|
||||
@ -6834,11 +6834,9 @@ struct btr_blob_log_check_t {
|
||||
m_pcur->btr_cur.page_cur.block->page.unfix();
|
||||
} else {
|
||||
ut_ad(m_pcur->rel_pos == BTR_PCUR_ON);
|
||||
bool ret = btr_pcur_restore_position(
|
||||
BTR_MODIFY_LEAF | BTR_MODIFY_EXTERNAL,
|
||||
m_pcur, m_mtr);
|
||||
|
||||
ut_a(ret);
|
||||
ut_a(m_pcur->restore_position(
|
||||
BTR_MODIFY_LEAF | BTR_MODIFY_EXTERNAL,
|
||||
m_mtr) == btr_pcur_t::SAME_ALL);
|
||||
}
|
||||
|
||||
*m_block = btr_pcur_get_block(m_pcur);
|
||||
|
||||
@ -672,7 +672,7 @@ processed:
|
||||
mtr_x_lock_index(index, &mtr);
|
||||
/* This will acquire index->lock SX-latch, which per WL#6363 is allowed
|
||||
when we are already holding the X-latch. */
|
||||
btr_pcur_restore_position(BTR_MODIFY_TREE, item->pcur, &mtr);
|
||||
item->pcur->restore_position(BTR_MODIFY_TREE, &mtr);
|
||||
buf_block_t* first_block = btr_pcur_get_block(item->pcur);
|
||||
if (buf_block_t *last_block =
|
||||
btr_defragment_n_pages(first_block, index,
|
||||
|
||||
@ -259,26 +259,29 @@ struct optimistic_latch_leaves
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************************************//**
|
||||
Restores the stored position of a persistent cursor bufferfixing the page and
|
||||
obtaining the specified latches. If the cursor position was saved when the
|
||||
(1) cursor was positioned on a user record: this function restores the position
|
||||
to the last record LESS OR EQUAL to the stored record;
|
||||
(2) cursor was positioned on a page infimum record: restores the position to
|
||||
the last record LESS than the user record which was the successor of the page
|
||||
infimum;
|
||||
(3) cursor was positioned on the page supremum: restores to the first record
|
||||
GREATER than the user record which was the predecessor of the supremum.
|
||||
(4) cursor was positioned before the first or after the last in an empty tree:
|
||||
restores to before first or after the last in the tree.
|
||||
@return TRUE if the cursor position was stored when it was on a user
|
||||
record and it can be restored on a user record whose ordering fields
|
||||
are identical to the ones of the original user record */
|
||||
ibool
|
||||
btr_pcur_restore_position(
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /*!< in: detached persistent cursor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
/** Restores the stored position of a persistent cursor bufferfixing
|
||||
the page and obtaining the specified latches. If the cursor position
|
||||
was saved when the
|
||||
(1) cursor was positioned on a user record: this function restores the
|
||||
position to the last record LESS OR EQUAL to the stored record;
|
||||
(2) cursor was positioned on a page infimum record: restores the
|
||||
position to the last record LESS than the user record which was the
|
||||
successor of the page infimum;
|
||||
(3) cursor was positioned on the page supremum: restores to the first
|
||||
record GREATER than the user record which was the predecessor of the
|
||||
supremum.
|
||||
(4) cursor was positioned before the first or after the last in an
|
||||
empty tree: restores to before first or after the last in the tree.
|
||||
@param restore_latch_mode BTR_SEARCH_LEAF, ...
|
||||
@param mtr mtr
|
||||
@return btr_pcur_t::SAME_ALL cursor position on user rec and points on
|
||||
the record with the same field values as in the stored record,
|
||||
btr_pcur_t::SAME_UNIQ cursor position is on user rec and points on the
|
||||
record with the same unique field values as in the stored record,
|
||||
btr_pcur_t::NOT_SAME cursor position is not on user rec or points on
|
||||
the record with not the samebuniq field values as in the stored */
|
||||
btr_pcur_t::restore_status
|
||||
btr_pcur_t::restore_position(ulint restore_latch_mode, mtr_t *mtr)
|
||||
{
|
||||
dict_index_t* index;
|
||||
dtuple_t* tuple;
|
||||
@ -288,97 +291,97 @@ btr_pcur_restore_position(
|
||||
|
||||
ut_ad(mtr->is_active());
|
||||
//ut_ad(cursor->old_stored);
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_WAS_POSITIONED
|
||||
|| cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(pos_state == BTR_PCUR_WAS_POSITIONED
|
||||
|| pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
|
||||
index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
|
||||
index = btr_cur_get_index(&btr_cur);
|
||||
|
||||
if (UNIV_UNLIKELY
|
||||
(cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
|
||||
|| cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
|
||||
(rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
|
||||
|| rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
|
||||
dberr_t err = DB_SUCCESS;
|
||||
|
||||
/* In these cases we do not try an optimistic restoration,
|
||||
but always do a search */
|
||||
|
||||
err = btr_cur_open_at_index_side(
|
||||
cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
|
||||
index, latch_mode,
|
||||
btr_pcur_get_btr_cur(cursor), 0, mtr);
|
||||
rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
|
||||
index, restore_latch_mode,
|
||||
&btr_cur, 0, mtr);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
ib::warn() << " Error code: " << err
|
||||
<< " btr_pcur_restore_position "
|
||||
<< " btr_pcur_t::restore_position "
|
||||
<< " table: " << index->table->name
|
||||
<< " index: " << index->name;
|
||||
}
|
||||
|
||||
cursor->latch_mode =
|
||||
BTR_LATCH_MODE_WITHOUT_INTENTION(latch_mode);
|
||||
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
cursor->block_when_stored.clear();
|
||||
latch_mode =
|
||||
BTR_LATCH_MODE_WITHOUT_INTENTION(restore_latch_mode);
|
||||
pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
block_when_stored.clear();
|
||||
|
||||
return(FALSE);
|
||||
return restore_status::NOT_SAME;
|
||||
}
|
||||
|
||||
ut_a(cursor->old_rec);
|
||||
ut_a(cursor->old_n_core_fields);
|
||||
ut_a(cursor->old_n_core_fields <= index->n_core_fields);
|
||||
ut_a(cursor->old_n_fields);
|
||||
ut_a(old_rec);
|
||||
ut_a(old_n_core_fields);
|
||||
ut_a(old_n_core_fields <= index->n_core_fields);
|
||||
ut_a(old_n_fields);
|
||||
|
||||
switch (latch_mode) {
|
||||
switch (restore_latch_mode) {
|
||||
case BTR_SEARCH_LEAF:
|
||||
case BTR_MODIFY_LEAF:
|
||||
case BTR_SEARCH_PREV:
|
||||
case BTR_MODIFY_PREV:
|
||||
/* Try optimistic restoration. */
|
||||
|
||||
if (cursor->block_when_stored.run_with_hint(
|
||||
optimistic_latch_leaves(cursor, &latch_mode,
|
||||
if (block_when_stored.run_with_hint(
|
||||
optimistic_latch_leaves(this, &restore_latch_mode,
|
||||
mtr))) {
|
||||
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
cursor->latch_mode = latch_mode;
|
||||
pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
latch_mode = restore_latch_mode;
|
||||
|
||||
if (cursor->rel_pos == BTR_PCUR_ON) {
|
||||
if (rel_pos == BTR_PCUR_ON) {
|
||||
#ifdef UNIV_DEBUG
|
||||
const rec_t* rec;
|
||||
rec_offs offsets1_[REC_OFFS_NORMAL_SIZE];
|
||||
rec_offs offsets2_[REC_OFFS_NORMAL_SIZE];
|
||||
rec_offs* offsets1 = offsets1_;
|
||||
rec_offs* offsets2 = offsets2_;
|
||||
rec = btr_pcur_get_rec(cursor);
|
||||
rec = btr_pcur_get_rec(this);
|
||||
|
||||
rec_offs_init(offsets1_);
|
||||
rec_offs_init(offsets2_);
|
||||
|
||||
heap = mem_heap_create(256);
|
||||
ut_ad(cursor->old_n_core_fields
|
||||
ut_ad(old_n_core_fields
|
||||
== index->n_core_fields);
|
||||
|
||||
offsets1 = rec_get_offsets(
|
||||
cursor->old_rec, index, offsets1,
|
||||
cursor->old_n_core_fields,
|
||||
cursor->old_n_fields, &heap);
|
||||
old_rec, index, offsets1,
|
||||
old_n_core_fields,
|
||||
old_n_fields, &heap);
|
||||
offsets2 = rec_get_offsets(
|
||||
rec, index, offsets2,
|
||||
index->n_core_fields,
|
||||
cursor->old_n_fields, &heap);
|
||||
old_n_fields, &heap);
|
||||
|
||||
ut_ad(!cmp_rec_rec(cursor->old_rec,
|
||||
ut_ad(!cmp_rec_rec(old_rec,
|
||||
rec, offsets1, offsets2,
|
||||
index));
|
||||
mem_heap_free(heap);
|
||||
#endif /* UNIV_DEBUG */
|
||||
return(TRUE);
|
||||
return restore_status::SAME_ALL;
|
||||
}
|
||||
/* This is the same record as stored,
|
||||
may need to be adjusted for BTR_PCUR_BEFORE/AFTER,
|
||||
depending on search mode and direction. */
|
||||
if (btr_pcur_is_on_user_rec(cursor)) {
|
||||
cursor->pos_state
|
||||
if (btr_pcur_is_on_user_rec(this)) {
|
||||
pos_state
|
||||
= BTR_PCUR_IS_POSITIONED_OPTIMISTIC;
|
||||
}
|
||||
return(FALSE);
|
||||
return restore_status::NOT_SAME;
|
||||
}
|
||||
}
|
||||
|
||||
@ -386,19 +389,19 @@ btr_pcur_restore_position(
|
||||
|
||||
heap = mem_heap_create(256);
|
||||
|
||||
tuple = dtuple_create(heap, cursor->old_n_fields);
|
||||
tuple = dtuple_create(heap, old_n_fields);
|
||||
|
||||
dict_index_copy_types(tuple, index, cursor->old_n_fields);
|
||||
dict_index_copy_types(tuple, index, old_n_fields);
|
||||
|
||||
rec_copy_prefix_to_dtuple(tuple, cursor->old_rec, index,
|
||||
cursor->old_n_core_fields,
|
||||
cursor->old_n_fields, heap);
|
||||
rec_copy_prefix_to_dtuple(tuple, old_rec, index,
|
||||
old_n_core_fields,
|
||||
old_n_fields, heap);
|
||||
ut_ad(dtuple_check_typed(tuple));
|
||||
|
||||
/* Save the old search mode of the cursor */
|
||||
old_mode = cursor->search_mode;
|
||||
old_mode = search_mode;
|
||||
|
||||
switch (cursor->rel_pos) {
|
||||
switch (rel_pos) {
|
||||
case BTR_PCUR_ON:
|
||||
mode = PAGE_CUR_LE;
|
||||
break;
|
||||
@ -413,41 +416,45 @@ btr_pcur_restore_position(
|
||||
mode = PAGE_CUR_UNSUPP;
|
||||
}
|
||||
|
||||
btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
|
||||
cursor,
|
||||
btr_pcur_open_with_no_init_func(index, tuple, mode, restore_latch_mode,
|
||||
this,
|
||||
#ifdef BTR_CUR_HASH_ADAPT
|
||||
NULL,
|
||||
#endif /* BTR_CUR_HASH_ADAPT */
|
||||
mtr);
|
||||
|
||||
/* Restore the old search mode */
|
||||
cursor->search_mode = old_mode;
|
||||
search_mode = old_mode;
|
||||
|
||||
ut_ad(cursor->rel_pos == BTR_PCUR_ON
|
||||
|| cursor->rel_pos == BTR_PCUR_BEFORE
|
||||
|| cursor->rel_pos == BTR_PCUR_AFTER);
|
||||
ut_ad(rel_pos == BTR_PCUR_ON
|
||||
|| rel_pos == BTR_PCUR_BEFORE
|
||||
|| rel_pos == BTR_PCUR_AFTER);
|
||||
rec_offs offsets[REC_OFFS_NORMAL_SIZE];
|
||||
rec_offs_init(offsets);
|
||||
if (cursor->rel_pos == BTR_PCUR_ON
|
||||
&& btr_pcur_is_on_user_rec(cursor)
|
||||
&& !cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor), index,
|
||||
rec_get_offsets(btr_pcur_get_rec(cursor),
|
||||
index, offsets,
|
||||
index->n_core_fields,
|
||||
ULINT_UNDEFINED, &heap))) {
|
||||
restore_status ret_val= restore_status::NOT_SAME;
|
||||
if (rel_pos == BTR_PCUR_ON && btr_pcur_is_on_user_rec(this)) {
|
||||
ulint n_matched_fields= 0;
|
||||
if (!cmp_dtuple_rec_with_match(
|
||||
tuple, btr_pcur_get_rec(this), index,
|
||||
rec_get_offsets(btr_pcur_get_rec(this), index, offsets,
|
||||
index->n_core_fields, ULINT_UNDEFINED, &heap),
|
||||
&n_matched_fields)) {
|
||||
|
||||
/* We have to store the NEW value for the modify clock,
|
||||
since the cursor can now be on a different page!
|
||||
But we can retain the value of old_rec */
|
||||
/* We have to store the NEW value for the modify clock,
|
||||
since the cursor can now be on a different page!
|
||||
But we can retain the value of old_rec */
|
||||
|
||||
cursor->block_when_stored.store(btr_pcur_get_block(cursor));
|
||||
cursor->modify_clock = buf_block_get_modify_clock(
|
||||
cursor->block_when_stored.block());
|
||||
cursor->old_stored = true;
|
||||
block_when_stored.store(btr_pcur_get_block(this));
|
||||
modify_clock= buf_block_get_modify_clock(
|
||||
block_when_stored.block());
|
||||
old_stored= true;
|
||||
|
||||
mem_heap_free(heap);
|
||||
mem_heap_free(heap);
|
||||
|
||||
return(TRUE);
|
||||
return restore_status::SAME_ALL;
|
||||
}
|
||||
if (n_matched_fields >= index->n_uniq)
|
||||
ret_val= restore_status::SAME_UNIQ;
|
||||
}
|
||||
|
||||
mem_heap_free(heap);
|
||||
@ -456,9 +463,9 @@ btr_pcur_restore_position(
|
||||
to the cursor because it can now be on a different page, the record
|
||||
under it may have been removed, etc. */
|
||||
|
||||
btr_pcur_store_position(cursor, mtr);
|
||||
btr_pcur_store_position(this, mtr);
|
||||
|
||||
return(FALSE);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/*********************************************************//**
|
||||
@ -567,7 +574,7 @@ btr_pcur_move_backward_from_page(
|
||||
|
||||
mtr_start(mtr);
|
||||
|
||||
btr_pcur_restore_position(latch_mode2, cursor, mtr);
|
||||
cursor->restore_position(latch_mode2, mtr);
|
||||
|
||||
page = btr_pcur_get_page(cursor);
|
||||
|
||||
|
||||
@ -227,7 +227,7 @@ dict_getnext_system(
|
||||
const rec_t* rec;
|
||||
|
||||
/* Restore the position */
|
||||
btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
|
||||
pcur->restore_position(BTR_SEARCH_LEAF, mtr);
|
||||
|
||||
/* Get the next record */
|
||||
rec = dict_getnext_system_low(pcur, mtr);
|
||||
@ -3024,7 +3024,7 @@ loop:
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
pcur.restore_position(BTR_SEARCH_LEAF, &mtr);
|
||||
next_rec:
|
||||
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
|
||||
|
||||
|
||||
@ -3448,7 +3448,6 @@ fts_add_doc_by_id(
|
||||
get_doc, clust_index, doc_pcur, offsets, &doc);
|
||||
|
||||
if (doc.found) {
|
||||
ibool success MY_ATTRIBUTE((unused));
|
||||
|
||||
btr_pcur_store_position(doc_pcur, &mtr);
|
||||
mtr_commit(&mtr);
|
||||
@ -3507,12 +3506,10 @@ fts_add_doc_by_id(
|
||||
mtr_start(&mtr);
|
||||
|
||||
if (i < num_idx - 1) {
|
||||
|
||||
success = btr_pcur_restore_position(
|
||||
BTR_SEARCH_LEAF, doc_pcur,
|
||||
&mtr);
|
||||
|
||||
ut_ad(success);
|
||||
ut_d(auto status=)
|
||||
doc_pcur->restore_position(
|
||||
BTR_SEARCH_LEAF, &mtr);
|
||||
ut_ad(status == btr_pcur_t::SAME_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2047,7 +2047,7 @@ fail:
|
||||
os_file_close(d);
|
||||
|
||||
mtr.start();
|
||||
btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
pcur.restore_position(BTR_SEARCH_LEAF, &mtr);
|
||||
}
|
||||
|
||||
btr_pcur_close(&pcur);
|
||||
|
||||
@ -4008,7 +4008,8 @@ ibuf_restore_pos(
|
||||
ut_ad(mode == BTR_MODIFY_LEAF
|
||||
|| BTR_LATCH_MODE_WITHOUT_INTENTION(mode) == BTR_MODIFY_TREE);
|
||||
|
||||
if (UNIV_LIKELY(btr_pcur_restore_position(mode, pcur, mtr))) {
|
||||
if (UNIV_LIKELY(pcur->restore_position(mode, mtr) ==
|
||||
btr_pcur_t::SAME_ALL)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -238,26 +238,6 @@ btr_pcur_store_position(
|
||||
/*====================*/
|
||||
btr_pcur_t* cursor, /*!< in: persistent cursor */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/**************************************************************//**
|
||||
Restores the stored position of a persistent cursor bufferfixing the page and
|
||||
obtaining the specified latches. If the cursor position was saved when the
|
||||
(1) cursor was positioned on a user record: this function restores the position
|
||||
to the last record LESS OR EQUAL to the stored record;
|
||||
(2) cursor was positioned on a page infimum record: restores the position to
|
||||
the last record LESS than the user record which was the successor of the page
|
||||
infimum;
|
||||
(3) cursor was positioned on the page supremum: restores to the first record
|
||||
GREATER than the user record which was the predecessor of the supremum.
|
||||
(4) cursor was positioned before the first or after the last in an empty tree:
|
||||
restores to before first or after the last in the tree.
|
||||
@return TRUE if the cursor position was stored when it was on a user
|
||||
record and it can be restored on a user record whose ordering fields
|
||||
are identical to the ones of the original user record */
|
||||
ibool
|
||||
btr_pcur_restore_position(
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /*!< in: detached persistent cursor */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/*********************************************************//**
|
||||
Gets the rel_pos field for a cursor whose position has been stored.
|
||||
@return BTR_PCUR_ON, ... */
|
||||
@ -419,6 +399,18 @@ enum pcur_pos_t {
|
||||
selects, updates, and deletes. */
|
||||
|
||||
struct btr_pcur_t{
|
||||
/** Return value of restore_position() */
|
||||
enum restore_status {
|
||||
/** cursor position on user rec and points on the record with
|
||||
the same field values as in the stored record */
|
||||
SAME_ALL,
|
||||
/** cursor position is on user rec and points on the record with
|
||||
the same unique field values as in the stored record */
|
||||
SAME_UNIQ,
|
||||
/** cursor position is not on user rec or points on the record
|
||||
with not the same uniq field values as in the stored record */
|
||||
NOT_SAME
|
||||
};
|
||||
/** a B-tree cursor */
|
||||
btr_cur_t btr_cur;
|
||||
/** see TODO note below!
|
||||
@ -476,6 +468,28 @@ struct btr_pcur_t{
|
||||
|
||||
/** Return the index of this persistent cursor */
|
||||
dict_index_t* index() const { return(btr_cur.index); }
|
||||
/** Restores the stored position of a persistent cursor bufferfixing
|
||||
the page and obtaining the specified latches. If the cursor position
|
||||
was saved when the
|
||||
(1) cursor was positioned on a user record: this function restores the
|
||||
position to the last record LESS OR EQUAL to the stored record;
|
||||
(2) cursor was positioned on a page infimum record: restores the
|
||||
position to the last record LESS than the user record which was the
|
||||
successor of the page infimum;
|
||||
(3) cursor was positioned on the page supremum: restores to the first
|
||||
record GREATER than the user record which was the predecessor of the
|
||||
supremum.
|
||||
(4) cursor was positioned before the first or after the last in an
|
||||
empty tree: restores to before first or after the last in the tree.
|
||||
@param restore_latch_mode BTR_SEARCH_LEAF, ...
|
||||
@param mtr mtr
|
||||
@return btr_pcur_t::SAME_ALL cursor position on user rec and points on
|
||||
the record with the same field values as in the stored record,
|
||||
btr_pcur_t::SAME_UNIQ cursor position is on user rec and points on the
|
||||
record with the same unique field values as in the stored record,
|
||||
btr_pcur_t::NOT_SAME cursor position is not on user rec or points on
|
||||
the record with not the samebuniq field values as in the stored */
|
||||
restore_status restore_position(ulint latch_mode, mtr_t *mtr);
|
||||
};
|
||||
|
||||
inline buf_block_t *btr_pcur_get_block(btr_pcur_t *cursor)
|
||||
|
||||
@ -652,9 +652,13 @@ void log_write_up_to(lsn_t lsn, bool durable,
|
||||
#endif
|
||||
|
||||
repeat:
|
||||
if (durable &&
|
||||
flush_lock.acquire(lsn, callback) != group_commit_lock::ACQUIRED)
|
||||
return;
|
||||
if (durable)
|
||||
{
|
||||
if (flush_lock.acquire(lsn, callback) != group_commit_lock::ACQUIRED)
|
||||
return;
|
||||
flush_lock.set_pending(log_sys.get_lsn());
|
||||
}
|
||||
|
||||
|
||||
lsn_t pending_write_lsn= 0, pending_flush_lsn= 0;
|
||||
|
||||
|
||||
@ -222,7 +222,7 @@ group_commit_lock::lock_return_code group_commit_lock::acquire(value_type num, c
|
||||
thread_local_waiter.m_value = num;
|
||||
thread_local_waiter.m_group_commit_leader= false;
|
||||
std::unique_lock<std::mutex> lk(m_mtx, std::defer_lock);
|
||||
while (num > value())
|
||||
while (num > value() || thread_local_waiter.m_group_commit_leader)
|
||||
{
|
||||
lk.lock();
|
||||
|
||||
@ -232,11 +232,9 @@ group_commit_lock::lock_return_code group_commit_lock::acquire(value_type num, c
|
||||
{
|
||||
lk.unlock();
|
||||
do_completion_callback(callback);
|
||||
thread_local_waiter.m_group_commit_leader=false;
|
||||
return lock_return_code::EXPIRED;
|
||||
}
|
||||
|
||||
thread_local_waiter.m_group_commit_leader= false;
|
||||
if (!m_lock)
|
||||
{
|
||||
/* Take the lock, become group commit leader.*/
|
||||
@ -249,17 +247,23 @@ group_commit_lock::lock_return_code group_commit_lock::acquire(value_type num, c
|
||||
return lock_return_code::ACQUIRED;
|
||||
}
|
||||
|
||||
if (callback && m_waiters_list)
|
||||
if (callback && (m_waiters_list || num <= pending()))
|
||||
{
|
||||
/*
|
||||
We need to have at least one waiter,
|
||||
so it can become the new group commit leader.
|
||||
If num > pending(), we have a good candidate for the next group
|
||||
commit lead, that will be taking over the lock after current owner
|
||||
releases it. We put current thread into waiter's list so it sleeps
|
||||
and can be signaled and marked as group commit lead during lock release.
|
||||
|
||||
For this to work well, pending() must deliver a good approximation for N
|
||||
in the next call to group_commit_lock::release(N).
|
||||
*/
|
||||
m_pending_callbacks.push_back({num, *callback});
|
||||
return lock_return_code::CALLBACK_QUEUED;
|
||||
}
|
||||
|
||||
/* Add yourself to waiters list.*/
|
||||
thread_local_waiter.m_group_commit_leader= false;
|
||||
thread_local_waiter.m_next = m_waiters_list;
|
||||
m_waiters_list = &thread_local_waiter;
|
||||
lk.unlock();
|
||||
@ -369,6 +373,17 @@ group_commit_lock::value_type group_commit_lock::release(value_type num)
|
||||
|
||||
lk.unlock();
|
||||
|
||||
/*
|
||||
Release designated next group commit lead first,
|
||||
to minimize spurious wakeups.
|
||||
*/
|
||||
if (wakeup_list && wakeup_list->m_group_commit_leader)
|
||||
{
|
||||
next = wakeup_list->m_next;
|
||||
wakeup_list->m_sema.wake();
|
||||
wakeup_list= next;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < callback_count; i++)
|
||||
callbacks[i].m_callback(callbacks[i].m_param);
|
||||
|
||||
|
||||
@ -1563,7 +1563,7 @@ IndexPurge::next() UNIV_NOTHROW
|
||||
|
||||
mtr_set_log_mode(&m_mtr, MTR_LOG_NO_REDO);
|
||||
|
||||
btr_pcur_restore_position(BTR_MODIFY_LEAF, &m_pcur, &m_mtr);
|
||||
m_pcur.restore_position(BTR_MODIFY_LEAF, &m_mtr);
|
||||
/* The following is based on btr_pcur_move_to_next_user_rec(). */
|
||||
m_pcur.old_stored = false;
|
||||
ut_ad(m_pcur.latch_mode == BTR_MODIFY_LEAF);
|
||||
@ -1639,8 +1639,7 @@ IndexPurge::purge_pessimistic_delete() UNIV_NOTHROW
|
||||
{
|
||||
dberr_t err;
|
||||
|
||||
btr_pcur_restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
&m_pcur, &m_mtr);
|
||||
m_pcur.restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, &m_mtr);
|
||||
|
||||
ut_ad(rec_get_deleted_flag(
|
||||
btr_pcur_get_rec(&m_pcur),
|
||||
@ -1668,7 +1667,7 @@ IndexPurge::purge() UNIV_NOTHROW
|
||||
|
||||
mtr_set_log_mode(&m_mtr, MTR_LOG_NO_REDO);
|
||||
|
||||
btr_pcur_restore_position(BTR_MODIFY_LEAF, &m_pcur, &m_mtr);
|
||||
m_pcur.restore_position(BTR_MODIFY_LEAF, &m_mtr);
|
||||
}
|
||||
|
||||
/** Adjust the BLOB reference for a single column that is externally stored
|
||||
|
||||
@ -1350,7 +1350,7 @@ row_ins_foreign_check_on_constraint(
|
||||
|
||||
/* Restore pcur position */
|
||||
|
||||
btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
|
||||
pcur->restore_position(BTR_SEARCH_LEAF, mtr);
|
||||
|
||||
if (tmp_heap) {
|
||||
mem_heap_free(tmp_heap);
|
||||
@ -1369,7 +1369,7 @@ nonstandard_exit_func:
|
||||
mtr_commit(mtr);
|
||||
mtr_start(mtr);
|
||||
|
||||
btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
|
||||
pcur->restore_position(BTR_SEARCH_LEAF, mtr);
|
||||
|
||||
DBUG_RETURN(err);
|
||||
}
|
||||
|
||||
@ -2175,8 +2175,8 @@ scan_next:
|
||||
/* Restore position on the record, or its
|
||||
predecessor if the record was purged
|
||||
meanwhile. */
|
||||
btr_pcur_restore_position(
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
pcur.restore_position(
|
||||
BTR_SEARCH_LEAF, &mtr);
|
||||
/* Move to the successor of the
|
||||
original record. */
|
||||
if (!btr_pcur_move_to_next_user_rec(
|
||||
@ -2719,9 +2719,8 @@ write_buffers:
|
||||
overflow). */
|
||||
mtr.start();
|
||||
mtr_started = true;
|
||||
btr_pcur_restore_position(
|
||||
BTR_SEARCH_LEAF, &pcur,
|
||||
&mtr);
|
||||
pcur.restore_position(
|
||||
BTR_SEARCH_LEAF, &mtr);
|
||||
buf = row_merge_buf_empty(buf);
|
||||
merge_buf[i] = buf;
|
||||
/* Restart the outer loop on the
|
||||
|
||||
@ -1818,7 +1818,7 @@ row_unlock_for_mysql(
|
||||
/* Restore the cursor position and find the record */
|
||||
|
||||
if (!has_latches_on_recs) {
|
||||
btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, &mtr);
|
||||
pcur->restore_position(BTR_SEARCH_LEAF, &mtr);
|
||||
}
|
||||
|
||||
rec = btr_pcur_get_rec(pcur);
|
||||
@ -1829,8 +1829,8 @@ row_unlock_for_mysql(
|
||||
in the clustered index. */
|
||||
|
||||
if (!has_latches_on_recs) {
|
||||
btr_pcur_restore_position(BTR_SEARCH_LEAF,
|
||||
clust_pcur, &mtr);
|
||||
clust_pcur->restore_position(BTR_SEARCH_LEAF,
|
||||
&mtr);
|
||||
}
|
||||
|
||||
rec = btr_pcur_get_rec(clust_pcur);
|
||||
|
||||
@ -75,7 +75,9 @@ row_purge_reposition_pcur(
|
||||
if (node->found_clust) {
|
||||
ut_ad(node->validate_pcur());
|
||||
|
||||
node->found_clust = btr_pcur_restore_position(mode, &node->pcur, mtr);
|
||||
node->found_clust =
|
||||
node->pcur.restore_position(mode, mtr) ==
|
||||
btr_pcur_t::SAME_ALL;
|
||||
|
||||
} else {
|
||||
node->found_clust = row_search_on_row_ref(
|
||||
|
||||
@ -1438,8 +1438,9 @@ row_sel_restore_pcur_pos(
|
||||
|
||||
relative_position = btr_pcur_get_rel_pos(&(plan->pcur));
|
||||
|
||||
equal_position = btr_pcur_restore_position(BTR_SEARCH_LEAF,
|
||||
&(plan->pcur), mtr);
|
||||
equal_position =
|
||||
plan->pcur.restore_position(BTR_SEARCH_LEAF, mtr) ==
|
||||
btr_pcur_t::SAME_ALL;
|
||||
|
||||
/* If the cursor is traveling upwards, and relative_position is
|
||||
|
||||
@ -3592,36 +3593,28 @@ err_exit:
|
||||
return(err);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Restores cursor position after it has been stored. We have to take into
|
||||
/** Restores cursor position after it has been stored. We have to take into
|
||||
account that the record cursor was positioned on may have been deleted.
|
||||
Then we may have to move the cursor one step up or down.
|
||||
@param[out] same_user_rec true if we were able to restore the cursor on a user
|
||||
record with the same ordering prefix in in the B-tree index
|
||||
@param[in] latch_mode latch mode wished in restoration
|
||||
@param[in] pcur cursor whose position has been stored
|
||||
@param[in] moves_up true if the cursor moves up in the index
|
||||
@param[in] mtr mtr; CAUTION: may commit mtr temporarily!
|
||||
@param[in] select_lock_type select lock type
|
||||
@return true if we may need to process the record the cursor is now
|
||||
positioned on (i.e. we should not go to the next record yet) */
|
||||
static
|
||||
bool
|
||||
sel_restore_position_for_mysql(
|
||||
/*===========================*/
|
||||
ibool* same_user_rec, /*!< out: TRUE if we were able to restore
|
||||
the cursor on a user record with the
|
||||
same ordering prefix in in the
|
||||
B-tree index */
|
||||
ulint latch_mode, /*!< in: latch mode wished in
|
||||
restoration */
|
||||
btr_pcur_t* pcur, /*!< in: cursor whose position
|
||||
has been stored */
|
||||
ibool moves_up, /*!< in: TRUE if the cursor moves up
|
||||
in the index */
|
||||
mtr_t* mtr) /*!< in: mtr; CAUTION: may commit
|
||||
mtr temporarily! */
|
||||
static bool sel_restore_position_for_mysql(bool *same_user_rec,
|
||||
ulint latch_mode, btr_pcur_t *pcur,
|
||||
bool moves_up, mtr_t *mtr,
|
||||
lock_mode select_lock_type)
|
||||
{
|
||||
ibool success;
|
||||
auto status = pcur->restore_position(latch_mode, mtr);
|
||||
|
||||
success = btr_pcur_restore_position(latch_mode, pcur, mtr);
|
||||
*same_user_rec = status == btr_pcur_t::SAME_ALL;
|
||||
|
||||
*same_user_rec = success;
|
||||
|
||||
ut_ad(!success || pcur->rel_pos == BTR_PCUR_ON);
|
||||
ut_ad(!*same_user_rec || pcur->rel_pos == BTR_PCUR_ON);
|
||||
#ifdef UNIV_DEBUG
|
||||
if (pcur->pos_state == BTR_PCUR_IS_POSITIONED_OPTIMISTIC) {
|
||||
ut_ad(pcur->rel_pos == BTR_PCUR_BEFORE
|
||||
@ -3637,7 +3630,10 @@ sel_restore_position_for_mysql(
|
||||
|
||||
switch (pcur->rel_pos) {
|
||||
case BTR_PCUR_ON:
|
||||
if (!success && moves_up) {
|
||||
if (!*same_user_rec && moves_up) {
|
||||
if (status == btr_pcur_t::SAME_UNIQ
|
||||
&& select_lock_type != LOCK_NONE)
|
||||
return true;
|
||||
next:
|
||||
if (btr_pcur_move_to_next(pcur, mtr)
|
||||
&& rec_is_metadata(btr_pcur_get_rec(pcur),
|
||||
@ -3647,7 +3643,7 @@ next:
|
||||
|
||||
return true;
|
||||
}
|
||||
return(!success);
|
||||
return(!*same_user_rec);
|
||||
case BTR_PCUR_AFTER_LAST_IN_TREE:
|
||||
case BTR_PCUR_BEFORE_FIRST_IN_TREE:
|
||||
return true;
|
||||
@ -4330,12 +4326,12 @@ row_search_mvcc(
|
||||
Row_sel_get_clust_rec_for_mysql row_sel_get_clust_rec_for_mysql;
|
||||
ibool unique_search = FALSE;
|
||||
ibool mtr_has_extra_clust_latch = FALSE;
|
||||
ibool moves_up = FALSE;
|
||||
bool moves_up = false;
|
||||
/* if the returned record was locked and we did a semi-consistent
|
||||
read (fetch the newest committed version), then this is set to
|
||||
TRUE */
|
||||
ulint next_offs;
|
||||
ibool same_user_rec;
|
||||
bool same_user_rec;
|
||||
ibool table_lock_waited = FALSE;
|
||||
byte* next_buf = 0;
|
||||
bool spatial_search = false;
|
||||
@ -4648,10 +4644,10 @@ aborted:
|
||||
if (UNIV_UNLIKELY(direction == 0)) {
|
||||
if (mode == PAGE_CUR_GE || mode == PAGE_CUR_G
|
||||
|| mode >= PAGE_CUR_CONTAIN) {
|
||||
moves_up = TRUE;
|
||||
moves_up = true;
|
||||
}
|
||||
} else if (direction == ROW_SEL_NEXT) {
|
||||
moves_up = TRUE;
|
||||
moves_up = true;
|
||||
}
|
||||
|
||||
thr = que_fork_get_first_thr(prebuilt->sel_graph);
|
||||
@ -4701,7 +4697,7 @@ wait_table_again:
|
||||
|
||||
bool need_to_process = sel_restore_position_for_mysql(
|
||||
&same_user_rec, BTR_SEARCH_LEAF,
|
||||
pcur, moves_up, &mtr);
|
||||
pcur, moves_up, &mtr, prebuilt->select_lock_type);
|
||||
|
||||
if (UNIV_UNLIKELY(need_to_process)) {
|
||||
if (UNIV_UNLIKELY(prebuilt->row_read_type
|
||||
@ -4952,7 +4948,7 @@ rec_loop:
|
||||
if (UNIV_UNLIKELY(next_offs >= srv_page_size - PAGE_DIR)) {
|
||||
|
||||
wrong_offs:
|
||||
if (srv_force_recovery == 0 || moves_up == FALSE) {
|
||||
if (srv_force_recovery == 0 || moves_up == false) {
|
||||
ib::error() << "Rec address "
|
||||
<< static_cast<const void*>(rec)
|
||||
<< ", buf block fix count "
|
||||
@ -5764,7 +5760,9 @@ next_rec:
|
||||
|
||||
if (sel_restore_position_for_mysql(&same_user_rec,
|
||||
BTR_SEARCH_LEAF,
|
||||
pcur, moves_up, &mtr)) {
|
||||
pcur, moves_up, &mtr,
|
||||
prebuilt->select_lock_type)
|
||||
) {
|
||||
goto rec_loop;
|
||||
}
|
||||
}
|
||||
@ -5848,7 +5846,7 @@ lock_table_wait:
|
||||
if (!dict_index_is_spatial(index)) {
|
||||
sel_restore_position_for_mysql(
|
||||
&same_user_rec, BTR_SEARCH_LEAF, pcur,
|
||||
moves_up, &mtr);
|
||||
moves_up, &mtr, prebuilt->select_lock_type);
|
||||
}
|
||||
|
||||
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
|
||||
|
||||
@ -66,7 +66,6 @@ row_undo_ins_remove_clust_rec(
|
||||
/*==========================*/
|
||||
undo_node_t* node) /*!< in: undo node */
|
||||
{
|
||||
ibool success;
|
||||
dberr_t err;
|
||||
ulint n_tries = 0;
|
||||
mtr_t mtr;
|
||||
@ -112,14 +111,12 @@ restart:
|
||||
We must log the removal, so that the row will be correctly
|
||||
purged. However, we can log the removal out of sync with the
|
||||
B-tree modification. */
|
||||
|
||||
success = btr_pcur_restore_position(
|
||||
online
|
||||
? BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED
|
||||
: (node->rec_type == TRX_UNDO_INSERT_METADATA)
|
||||
? BTR_MODIFY_TREE : BTR_MODIFY_LEAF, &node->pcur, &mtr);
|
||||
ut_a(success);
|
||||
|
||||
ut_a(node->pcur.restore_position(
|
||||
online ? BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED
|
||||
: (node->rec_type == TRX_UNDO_INSERT_METADATA)
|
||||
? BTR_MODIFY_TREE
|
||||
: BTR_MODIFY_LEAF,
|
||||
&mtr) == btr_pcur_t::SAME_ALL);
|
||||
rec_t* rec = btr_pcur_get_rec(&node->pcur);
|
||||
|
||||
ut_ad(rec_get_trx_id(rec, index) == node->trx->id
|
||||
@ -214,9 +211,8 @@ restart:
|
||||
}
|
||||
|
||||
mtr.start();
|
||||
success = btr_pcur_restore_position(
|
||||
BTR_MODIFY_LEAF, &node->pcur, &mtr);
|
||||
ut_a(success);
|
||||
ut_a(node->pcur.restore_position(
|
||||
BTR_MODIFY_LEAF, &mtr) == btr_pcur_t::SAME_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,11 +230,9 @@ retry:
|
||||
} else {
|
||||
index->set_modified(mtr);
|
||||
}
|
||||
|
||||
success = btr_pcur_restore_position(
|
||||
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
&node->pcur, &mtr);
|
||||
ut_a(success);
|
||||
ut_a(
|
||||
node->pcur.restore_position(BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
&mtr) == btr_pcur_t::SAME_ALL);
|
||||
|
||||
btr_cur_pessimistic_delete(&err, FALSE, &node->pcur.btr_cur, 0, true,
|
||||
&mtr);
|
||||
|
||||
@ -95,19 +95,14 @@ row_undo_mod_clust_low(
|
||||
btr_pcur_t* pcur;
|
||||
btr_cur_t* btr_cur;
|
||||
dberr_t err;
|
||||
#ifdef UNIV_DEBUG
|
||||
ibool success;
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
pcur = &node->pcur;
|
||||
btr_cur = btr_pcur_get_btr_cur(pcur);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
success =
|
||||
#endif /* UNIV_DEBUG */
|
||||
btr_pcur_restore_position(mode, pcur, mtr);
|
||||
ut_d(auto pcur_restore_result =)
|
||||
pcur->restore_position(mode, mtr);
|
||||
|
||||
ut_ad(success);
|
||||
ut_ad(pcur_restore_result == btr_pcur_t::SAME_ALL);
|
||||
ut_ad(rec_get_trx_id(btr_cur_get_rec(btr_cur),
|
||||
btr_cur_get_index(btr_cur))
|
||||
== thr_get_trx(thr)->id
|
||||
@ -381,7 +376,8 @@ row_undo_mod_clust(
|
||||
ut_ad(node->new_trx_id);
|
||||
|
||||
mtr.start();
|
||||
if (!btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, &mtr)) {
|
||||
if (pcur->restore_position(BTR_MODIFY_LEAF, &mtr) !=
|
||||
btr_pcur_t::SAME_ALL) {
|
||||
goto mtr_commit_exit;
|
||||
}
|
||||
|
||||
@ -412,9 +408,9 @@ row_undo_mod_clust(
|
||||
}
|
||||
|
||||
mtr.start();
|
||||
if (!btr_pcur_restore_position(
|
||||
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE,
|
||||
pcur, &mtr)) {
|
||||
if (pcur->restore_position(
|
||||
BTR_MODIFY_TREE | BTR_LATCH_FOR_DELETE, &mtr) !=
|
||||
btr_pcur_t::SAME_ALL) {
|
||||
goto mtr_commit_exit;
|
||||
}
|
||||
|
||||
@ -447,7 +443,8 @@ row_undo_mod_clust(
|
||||
longer accessible by any active read view. */
|
||||
|
||||
mtr.start();
|
||||
if (!btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, &mtr)) {
|
||||
if (pcur->restore_position(BTR_MODIFY_LEAF, &mtr)
|
||||
!= btr_pcur_t::SAME_ALL) {
|
||||
goto mtr_commit_exit;
|
||||
}
|
||||
rec_t* rec = btr_pcur_get_rec(pcur);
|
||||
@ -554,7 +551,6 @@ row_undo_mod_del_mark_or_remove_sec_low(
|
||||
{
|
||||
btr_pcur_t pcur;
|
||||
btr_cur_t* btr_cur;
|
||||
ibool success;
|
||||
dberr_t err = DB_SUCCESS;
|
||||
mtr_t mtr;
|
||||
mtr_t mtr_vers;
|
||||
@ -626,9 +622,8 @@ row_undo_mod_del_mark_or_remove_sec_low(
|
||||
|
||||
mtr_vers.start();
|
||||
|
||||
success = btr_pcur_restore_position(BTR_SEARCH_LEAF, &(node->pcur),
|
||||
&mtr_vers);
|
||||
ut_a(success);
|
||||
ut_a(node->pcur.restore_position(BTR_SEARCH_LEAF, &mtr_vers) ==
|
||||
btr_pcur_t::SAME_ALL);
|
||||
|
||||
/* For temporary table, we can skip to check older version of
|
||||
clustered index entry, because there is no MVCC or purge. */
|
||||
|
||||
@ -2553,7 +2553,8 @@ row_upd_clust_rec(
|
||||
the same transaction do not modify the record in the meantime.
|
||||
Therefore we can assert that the restoration of the cursor succeeds. */
|
||||
|
||||
ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
|
||||
ut_a(pcur->restore_position(BTR_MODIFY_TREE, mtr) ==
|
||||
btr_pcur_t::SAME_ALL);
|
||||
|
||||
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
|
||||
dict_table_is_comp(index->table)));
|
||||
@ -2756,7 +2757,7 @@ row_upd_clust_step(
|
||||
mode = BTR_MODIFY_LEAF;
|
||||
}
|
||||
|
||||
if (!btr_pcur_restore_position(mode, pcur, &mtr)) {
|
||||
if (pcur->restore_position(mode, &mtr) != btr_pcur_t::SAME_ALL) {
|
||||
err = DB_RECORD_NOT_FOUND;
|
||||
goto exit_func;
|
||||
}
|
||||
|
||||
@ -652,15 +652,15 @@
|
||||
|
||||
<CustomAction Id='ErrorDataDir'
|
||||
Error='Invalid data directory, choose a different one. Error : [DATADIRERROR]'/>
|
||||
<CustomAction Id="ErrorInstallDir"
|
||||
Error="[INSTALLDIRERROR]" />
|
||||
<CustomAction Id="ErrorInstallDir"
|
||||
Error="[INSTALLDIRERROR]" />
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="CheckDataDirectory" After="CostFinalize">
|
||||
<![CDATA[&DBInstance=3 AND NOT !DBInstance=3 AND OLDERVERSIONBEINGUPGRADED=""]]>
|
||||
</Custom>
|
||||
<Custom Action="ErrorDataDir" After="CheckDataDirectory">DATADIRERROR</Custom>
|
||||
<Custom Action="CheckInstallDirectory" After="CostFinalize">
|
||||
NOT Installed
|
||||
<Custom Action="ErrorDataDir" After="CheckDataDirectory">DATADIRERROR</Custom>
|
||||
<Custom Action="CheckInstallDirectory" After="CostFinalize">
|
||||
NOT Installed AND OLDERVERSIONBEINGUPGRADED=""
|
||||
</Custom>
|
||||
<Custom Action="ErrorInstallDir" After="CheckInstallDirectory">INSTALLDIRERROR</Custom>
|
||||
<Custom Action="CheckDatabaseProperties" Before="CreateDatabaseCommand">SERVICENAME</Custom>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user